From c5c517a4d08da51f155b8ade1c842c55ae29e619 Mon Sep 17 00:00:00 2001 From: Chris Hofstaedtler Date: Mon, 2 Dec 2019 22:47:13 +0000 Subject: [PATCH] Import pdns_4.2.1.orig.tar.bz2 [dgit import orig pdns_4.2.1.orig.tar.bz2] --- COPYING | 339 + INSTALL | 219 + Makefile.am | 16 + Makefile.in | 984 + NOTICE | 16 + README | 219 + aclocal.m4 | 1558 + build-aux/compile | 348 + build-aux/config.guess | 1473 + build-aux/config.sub | 1836 + build-aux/depcomp | 791 + build-aux/install-sh | 501 + build-aux/ltmain.sh | 11153 ++++++ build-aux/missing | 215 + build-aux/test-driver | 148 + build-aux/ylwrap | 247 + builder-support/gen-version | 74 + codedocs/Makefile.am | 2 + codedocs/Makefile.in | 594 + codedocs/doxygen.conf | 1213 + config.h.in | 390 + configure | 29621 ++++++++++++++++ configure.ac | 413 + contrib/powerdns.solaris.init.d | 187 + docs/Makefile.am | 120 + docs/Makefile.in | 808 + docs/calidns.1 | 101 + docs/dnsbulktest.1 | 65 + docs/dnsgram.1 | 52 + docs/dnspcap2calidns.1 | 57 + docs/dnspcap2protobuf.1 | 54 + docs/dnsreplay.1 | 104 + docs/dnsscan.1 | 51 + docs/dnsscope.1 | 96 + docs/dnstcpbench.1 | 101 + docs/dnswasher.1 | 65 + docs/dumresp.1 | 55 + docs/ixfrdist.1 | 74 + docs/ixfrdist.yml.5 | 176 + docs/ixplore.1 | 89 + docs/nproxy.1 | 88 + docs/nsec3dig.1 | 50 + docs/pdns_control.1 | 179 + docs/pdns_notify.1 | 49 + docs/pdns_server.1 | 74 + docs/pdnsutil.1 | 359 + docs/saxfr.1 | 58 + docs/sdig.1 | 76 + docs/zone2json.1 | 76 + docs/zone2ldap.1 | 78 + docs/zone2sql.1 | 145 + ext/Makefile.am | 12 + ext/Makefile.in | 784 + ext/ipcrypt/LICENSE | 14 + ext/ipcrypt/Makefile.am | 8 + ext/ipcrypt/Makefile.in | 750 + ext/ipcrypt/ipcrypt.c | 87 + ext/ipcrypt/ipcrypt.h | 24 + ext/json11/Makefile.am | 2 + ext/json11/Makefile.in | 762 + ext/json11/json11.cpp | 784 + ext/json11/json11.hpp | 232 + ext/luawrapper/include/LuaContext.hpp | 2960 ++ ext/yahttp/LICENSE | 21 + ext/yahttp/Makefile.am | 3 + ext/yahttp/Makefile.in | 774 + ext/yahttp/README.md | 69 + ext/yahttp/yahttp/Makefile.am | 13 + ext/yahttp/yahttp/Makefile.in | 774 + ext/yahttp/yahttp/cookie.hpp | 143 + ext/yahttp/yahttp/exception.hpp | 24 + ext/yahttp/yahttp/reqresp.cpp | 326 + ext/yahttp/yahttp/reqresp.hpp | 351 + ext/yahttp/yahttp/router.cpp | 161 + ext/yahttp/yahttp/router.hpp | 72 + ext/yahttp/yahttp/url.hpp | 189 + ext/yahttp/yahttp/utility.hpp | 459 + ext/yahttp/yahttp/yahttp-config.h | 1 + ext/yahttp/yahttp/yahttp.hpp | 37 + m4/ac_pthread_set_name.m4 | 71 + m4/ax_arg_default_enable_disable.m4 | 21 + m4/ax_cxx_compile_stdcxx_11.m4 | 165 + m4/boost.m4 | 1776 + m4/libcurl.m4 | 272 + m4/libtool.m4 | 8369 +++++ m4/ltoptions.m4 | 437 + m4/ltsugar.m4 | 124 + m4/ltversion.m4 | 23 + m4/lt~obsolete.m4 | 99 + m4/pdns_check_bison.m4 | 15 + m4/pdns_check_cdb.m4 | 14 + m4/pdns_check_clock_gettime.m4 | 6 + m4/pdns_check_curl_program.m4 | 7 + m4/pdns_check_flex.m4 | 15 + m4/pdns_check_ldap.m4 | 54 + m4/pdns_check_libcrypto.m4 | 128 + m4/pdns_check_libcrypto_ecdsa.m4 | 33 + m4/pdns_check_libcrypto_eddsa.m4 | 36 + m4/pdns_check_libcurl.m4 | 6 + m4/pdns_check_lmdb.m4 | 46 + m4/pdns_check_lua_hpp.m4 | 10 + m4/pdns_check_network_libs.m4 | 7 + m4/pdns_check_opendbx.m4 | 14 + m4/pdns_check_os.m4 | 56 + m4/pdns_check_ragel.m4 | 8 + m4/pdns_check_sqlite3.m4 | 8 + m4/pdns_check_virtualenv.m4 | 12 + m4/pdns_d_fortify_source.m4 | 28 + m4/pdns_enable_backend_unit_tests.m4 | 18 + m4/pdns_enable_coverage.m4 | 17 + m4/pdns_enable_fuzz_targets.m4 | 11 + m4/pdns_enable_gss_tsig.m4 | 24 + m4/pdns_enable_ixfrdist.m4 | 18 + m4/pdns_enable_kiss.m4 | 7 + m4/pdns_enable_malloc_trace.m4 | 13 + m4/pdns_enable_p11kit.m4 | 21 + m4/pdns_enable_remotebackend_zeromq.m4 | 45 + m4/pdns_enable_reproducible.m4 | 29 + m4/pdns_enable_sanitizers.m4 | 167 + m4/pdns_enable_tools.m4 | 12 + m4/pdns_enable_unit_tests.m4 | 18 + m4/pdns_enable_verbose_logging.m4 | 17 + m4/pdns_from_git.m4 | 3 + m4/pdns_param_ssp_buffer_size.m4 | 26 + m4/pdns_pie.m4 | 55 + m4/pdns_relro.m4 | 37 + m4/pdns_stack_protector.m4 | 26 + m4/pdns_with_geo.m4 | 47 + m4/pdns_with_libdecaf.m4 | 23 + m4/pdns_with_libsodium.m4 | 30 + m4/pdns_with_lua.m4 | 62 + m4/pdns_with_lua_records.m4 | 23 + m4/pdns_with_mysql.m4 | 111 + m4/pdns_with_oracle.m4 | 62 + m4/pdns_with_postgresql.m4 | 35 + m4/pdns_with_protobuf.m4 | 27 + m4/pdns_with_sqlite3.m4 | 13 + m4/pdns_with_unixodbc.m4 | 106 + m4/systemd.m4 | 197 + m4/tm-gmtoff.m4 | 14 + m4/warnings.m4 | 79 + modules/Makefile.am | 21 + modules/Makefile.in | 792 + modules/bindbackend/Makefile.am | 25 + modules/bindbackend/Makefile.in | 846 + modules/bindbackend/OBJECTFILES | 1 + modules/bindbackend/OBJECTLIBS | 0 modules/bindbackend/bindbackend2.cc | 1424 + modules/bindbackend/bindbackend2.hh | 331 + modules/bindbackend/binddnssec.cc | 478 + modules/geoipbackend/Makefile.am | 12 + modules/geoipbackend/Makefile.in | 836 + modules/geoipbackend/OBJECTFILES | 1 + modules/geoipbackend/OBJECTLIBS | 1 + modules/geoipbackend/geoipbackend.cc | 946 + modules/geoipbackend/geoipbackend.hh | 81 + modules/geoipbackend/geoipinterface-dat.cc | 481 + modules/geoipbackend/geoipinterface-mmdb.cc | 278 + modules/geoipbackend/geoipinterface.cc | 67 + modules/geoipbackend/geoipinterface.hh | 71 + .../3.4.0_to_4.1.0_schema.mysql.sql | 21 + .../4.1.0_to_4.2.0_schema.mysql.sql | 3 + modules/gmysqlbackend/Makefile.am | 24 + modules/gmysqlbackend/Makefile.in | 868 + modules/gmysqlbackend/OBJECTFILES | 1 + modules/gmysqlbackend/OBJECTLIBS | 1 + .../dnssec-3.x_to_3.4.0_schema.mysql.sql | 36 + modules/gmysqlbackend/gmysqlbackend.cc | 184 + modules/gmysqlbackend/gmysqlbackend.hh | 41 + .../nodnssec-3.x_to_3.4.0_schema.mysql.sql | 63 + modules/gmysqlbackend/schema.mysql.sql | 88 + modules/gmysqlbackend/smysql.cc | 569 + modules/gmysqlbackend/smysql.hh | 69 + .../4.0.0_to_4.2.0_schema.mssql.sql | 1 + modules/godbcbackend/Makefile.am | 13 + modules/godbcbackend/Makefile.in | 857 + modules/godbcbackend/OBJECTFILES | 1 + modules/godbcbackend/OBJECTLIBS | 1 + modules/godbcbackend/godbcbackend.cc | 170 + modules/godbcbackend/godbcbackend.hh | 32 + modules/godbcbackend/schema.mssql.sql | 87 + modules/godbcbackend/sodbc.cc | 487 + modules/godbcbackend/sodbc.hh | 80 + modules/goraclebackend/Makefile.am | 20 + modules/goraclebackend/Makefile.in | 864 + modules/goraclebackend/OBJECTFILES | 1 + modules/goraclebackend/OBJECTLIBS | 0 .../goraclebackend/drop-schema.goracle.sql | 19 + modules/goraclebackend/goraclebackend.cc | 186 + modules/goraclebackend/goraclebackend.hh | 39 + modules/goraclebackend/schema.goracle.sql | 93 + modules/goraclebackend/soracle.cc | 554 + modules/goraclebackend/soracle.hh | 64 + .../3.4.0_to_4.1.0_schema.pgsql.sql | 1 + .../4.1.0_to_4.2.0_schema.pgsql.sql | 2 + modules/gpgsqlbackend/Makefile.am | 23 + modules/gpgsqlbackend/Makefile.in | 868 + modules/gpgsqlbackend/OBJECTFILES | 1 + modules/gpgsqlbackend/OBJECTLIBS | 1 + .../dnssec-3.x_to_3.4.0_schema.pgsql.sql | 35 + modules/gpgsqlbackend/gpgsqlbackend.cc | 190 + modules/gpgsqlbackend/gpgsqlbackend.hh | 42 + .../nodnssec-3.x_to_3.4.0_schema.pgsql.sql | 64 + modules/gpgsqlbackend/schema.pgsql.sql | 94 + modules/gpgsqlbackend/spgsql.cc | 390 + modules/gpgsqlbackend/spgsql.hh | 61 + .../3.4.0_to_4.0.0_schema.sqlite3.sql | 139 + .../4.0.0_to_4.2.0_schema.sqlite3.sql | 39 + modules/gsqlite3backend/Makefile.am | 19 + modules/gsqlite3backend/Makefile.in | 862 + modules/gsqlite3backend/OBJECTFILES | 1 + modules/gsqlite3backend/OBJECTLIBS | 1 + .../dnssec-3.x_to_3.4.0_schema.sqlite3.sql | 101 + modules/gsqlite3backend/gsqlite3backend.cc | 185 + modules/gsqlite3backend/gsqlite3backend.hh | 36 + .../nodnssec-3.x_to_3.4.0_schema.sqlite3.sql | 74 + modules/gsqlite3backend/schema.sqlite3.sql | 91 + modules/ldapbackend/Makefile.am | 22 + modules/ldapbackend/Makefile.in | 874 + modules/ldapbackend/OBJECTFILES | 1 + modules/ldapbackend/OBJECTLIBS | 1 + modules/ldapbackend/dnsdomain2.schema | 283 + modules/ldapbackend/exceptions.hh | 51 + modules/ldapbackend/ldapauthenticator.cc | 299 + modules/ldapbackend/ldapauthenticator.hh | 37 + modules/ldapbackend/ldapauthenticator_p.hh | 72 + modules/ldapbackend/ldapbackend.cc | 328 + modules/ldapbackend/ldapbackend.hh | 187 + modules/ldapbackend/ldaputils.cc | 49 + modules/ldapbackend/ldaputils.hh | 36 + modules/ldapbackend/master.cc | 160 + modules/ldapbackend/native.cc | 448 + modules/ldapbackend/pdns-domaininfo.schema | 77 + modules/ldapbackend/powerldap.cc | 468 + modules/ldapbackend/powerldap.hh | 105 + modules/ldapbackend/utils.hh | 177 + modules/lmdbbackend/Makefile.am | 9 + modules/lmdbbackend/Makefile.in | 830 + modules/lmdbbackend/OBJECTFILES | 1 + modules/lmdbbackend/OBJECTLIBS | 1 + modules/lmdbbackend/lmdb-safe.cc | 373 + modules/lmdbbackend/lmdb-safe.hh | 623 + modules/lmdbbackend/lmdb-typed.cc | 14 + modules/lmdbbackend/lmdb-typed.hh | 723 + modules/lmdbbackend/lmdbbackend.cc | 1635 + modules/lmdbbackend/lmdbbackend.hh | 273 + modules/lua2backend/Makefile.am | 13 + modules/lua2backend/Makefile.in | 831 + modules/lua2backend/OBJECTFILES | 1 + modules/lua2backend/OBJECTLIBS | 1 + modules/lua2backend/lua2api2.cc | 30 + modules/lua2backend/lua2api2.hh | 419 + modules/lua2backend/lua2backend.cc | 73 + modules/lua2backend/lua2backend.hh | 30 + modules/luabackend/Makefile.am | 19 + modules/luabackend/Makefile.in | 846 + modules/luabackend/OBJECTFILES | 1 + modules/luabackend/OBJECTLIBS | 1 + modules/luabackend/README | 191 + modules/luabackend/dnssec.cc | 603 + modules/luabackend/lua_functions.cc | 376 + modules/luabackend/lua_functions.hh | 30 + modules/luabackend/luabackend.cc | 68 + modules/luabackend/luabackend.hh | 250 + modules/luabackend/master.cc | 85 + modules/luabackend/minimal.cc | 243 + modules/luabackend/private.cc | 129 + modules/luabackend/reload.cc | 195 + modules/luabackend/slave.cc | 254 + modules/luabackend/supermaster.cc | 139 + modules/mydnsbackend/Makefile.am | 17 + modules/mydnsbackend/Makefile.in | 862 + modules/mydnsbackend/OBJECTFILES | 1 + modules/mydnsbackend/OBJECTLIBS | 1 + modules/mydnsbackend/mydnsbackend.cc | 500 + modules/mydnsbackend/mydnsbackend.hh | 65 + modules/mydnsbackend/schema.mydns.sql | 42 + modules/opendbxbackend/Makefile.am | 10 + modules/opendbxbackend/Makefile.in | 830 + modules/opendbxbackend/OBJECTFILES | 1 + modules/opendbxbackend/OBJECTLIBS | 1 + modules/opendbxbackend/README | 2 + modules/opendbxbackend/odbxbackend.cc | 777 + modules/opendbxbackend/odbxbackend.hh | 180 + modules/opendbxbackend/odbxprivate.cc | 289 + modules/oraclebackend/ChangeLog | 0 modules/oraclebackend/INSTALL | 0 modules/oraclebackend/Makefile.am | 17 + modules/oraclebackend/Makefile.in | 860 + modules/oraclebackend/OBJECTFILES | 1 + modules/oraclebackend/OBJECTLIBS | 0 modules/oraclebackend/README | 43 + modules/oraclebackend/TODO | 6 + modules/oraclebackend/drop-schema.oracle.sql | 23 + modules/oraclebackend/oraclebackend.cc | 2259 ++ modules/oraclebackend/oraclebackend.hh | 219 + modules/oraclebackend/schema.oracle.sql | 484 + modules/pipebackend/Makefile.am | 13 + modules/pipebackend/Makefile.in | 832 + modules/pipebackend/OBJECTFILES | 1 + modules/pipebackend/OBJECTLIBS | 0 modules/pipebackend/backend.pl | 63 + modules/pipebackend/coprocess.cc | 257 + modules/pipebackend/coprocess.hh | 73 + modules/pipebackend/pipebackend.cc | 390 + modules/pipebackend/pipebackend.hh | 76 + modules/randombackend/Makefile.am | 6 + modules/randombackend/Makefile.in | 806 + modules/randombackend/OBJECTFILES | 1 + modules/randombackend/OBJECTLIBS | 0 modules/randombackend/randombackend.cc | 131 + modules/remotebackend/Gemfile | 6 + modules/remotebackend/Gemfile.lock | 25 + modules/remotebackend/Makefile.am | 210 + modules/remotebackend/Makefile.in | 1865 + modules/remotebackend/OBJECTFILES | 1 + modules/remotebackend/OBJECTLIBS | 1 + modules/remotebackend/httpconnector.cc | 429 + modules/remotebackend/pipeconnector.cc | 201 + modules/remotebackend/remotebackend.cc | 974 + modules/remotebackend/remotebackend.hh | 226 + .../remotebackend/test-remotebackend-http.cc | 83 + .../remotebackend/test-remotebackend-json.cc | 82 + .../remotebackend/test-remotebackend-keys.hh | 24 + .../remotebackend/test-remotebackend-pipe.cc | 87 + .../remotebackend/test-remotebackend-post.cc | 82 + .../remotebackend/test-remotebackend-unix.cc | 87 + .../test-remotebackend-zeromq.cc | 99 + modules/remotebackend/test-remotebackend.cc | 343 + modules/remotebackend/testrunner.sh | 257 + modules/remotebackend/unittest.rb | 271 + modules/remotebackend/unittest_http.rb | 200 + modules/remotebackend/unittest_json.rb | 61 + modules/remotebackend/unittest_pipe.rb | 41 + modules/remotebackend/unittest_post.rb | 62 + modules/remotebackend/unittest_zeromq.rb | 57 + modules/remotebackend/unixconnector.cc | 186 + modules/remotebackend/zmqconnector.cc | 146 + modules/tinydnsbackend/Makefile.am | 12 + modules/tinydnsbackend/Makefile.in | 830 + modules/tinydnsbackend/OBJECTFILES | 1 + modules/tinydnsbackend/OBJECTLIBS | 1 + modules/tinydnsbackend/cdb.cc | 154 + modules/tinydnsbackend/cdb.hh | 55 + modules/tinydnsbackend/tinydnsbackend.cc | 355 + modules/tinydnsbackend/tinydnsbackend.hh | 113 + pdns/Makefile.am | 1635 + pdns/Makefile.in | 3573 ++ pdns/anadns.hh | 88 + pdns/arguments.cc | 502 + pdns/arguments.hh | 133 + pdns/ascii.hh | 41 + pdns/auth-caches.cc | 57 + pdns/auth-caches.hh | 34 + pdns/auth-carbon.cc | 104 + pdns/auth-packetcache.cc | 289 + pdns/auth-packetcache.hh | 136 + pdns/auth-querycache.cc | 251 + pdns/auth-querycache.hh | 117 + pdns/backends/gsql/gsqlbackend.cc | 1793 + pdns/backends/gsql/gsqlbackend.hh | 407 + pdns/backends/gsql/ssql.hh | 92 + pdns/base32.cc | 167 + pdns/base32.hh | 29 + pdns/base64.cc | 103 + pdns/base64.hh | 30 + pdns/bind-dnssec.schema.sqlite3.sql | 27 + pdns/bind-dnssec.schema.sqlite3.sql.h | 29 + pdns/bindlexer.c | 2090 ++ pdns/bindlexer.l | 130 + pdns/bindparser.cc | 1705 + pdns/bindparser.h | 94 + pdns/bindparser.hh | 94 + pdns/bindparser.yy | 288 + pdns/bindparserclasses.hh | 101 + pdns/cachecleaner.hh | 215 + pdns/calidns.cc | 536 + pdns/circular_buffer.hh | 38 + pdns/comfun.cc | 545 + pdns/comment.hh | 45 + pdns/common_startup.cc | 646 + pdns/common_startup.hh | 63 + pdns/communicator.cc | 168 + pdns/communicator.hh | 296 + pdns/dbdnsseckeeper.cc | 843 + pdns/decafsigners.cc | 293 + pdns/devpollmplexer.cc | 207 + pdns/digests.hh | 81 + pdns/distributor.hh | 342 + pdns/dns.cc | 132 + pdns/dns.hh | 247 + pdns/dns_random.cc | 322 + pdns/dns_random.hh | 29 + pdns/dns_random_urandom.cc | 2 + pdns/dnsbackend.cc | 378 + pdns/dnsbackend.hh | 441 + pdns/dnsbulktest.cc | 370 + pdns/dnsdemog.cc | 107 + pdns/dnsdist-cache.cc | 478 + pdns/dnsdist-cache.hh | 138 + pdns/dnsdist-ecs.cc | 767 + pdns/dnsdist-ecs.hh | 48 + pdns/dnsgram.cc | 254 + pdns/dnslabeltext.cc | 527 + pdns/dnslabeltext.rl | 185 + pdns/dnsmessage.proto | 90 + pdns/dnsname.cc | 458 + pdns/dnsname.hh | 469 + pdns/dnspacket.cc | 704 + pdns/dnspacket.hh | 196 + pdns/dnsparser.cc | 989 + pdns/dnsparser.hh | 411 + pdns/dnspcap.cc | 246 + pdns/dnspcap.hh | 147 + pdns/dnspcap2calidns.cc | 121 + pdns/dnspcap2protobuf.cc | 167 + pdns/dnsproxy.cc | 320 + pdns/dnsproxy.hh | 95 + pdns/dnsrecords.cc | 708 + pdns/dnsrecords.hh | 906 + pdns/dnsreplay.cc | 848 + pdns/dnsscan.cc | 109 + pdns/dnsscope.cc | 551 + pdns/dnssecinfra.cc | 764 + pdns/dnssecinfra.hh | 170 + pdns/dnsseckeeper.hh | 306 + pdns/dnssecsigner.cc | 237 + pdns/dnstcpbench.cc | 316 + pdns/dnswasher.cc | 274 + pdns/dnswriter.cc | 439 + pdns/dnswriter.hh | 177 + pdns/doh.hh | 68 + pdns/dumresp.cc | 226 + pdns/dynhandler.cc | 401 + pdns/dynhandler.hh | 60 + pdns/dynlistener.cc | 415 + pdns/dynlistener.hh | 82 + pdns/dynloader.cc | 186 + pdns/dynmessenger.cc | 154 + pdns/dynmessenger.hh | 66 + pdns/ednscookies.cc | 51 + pdns/ednscookies.hh | 36 + pdns/ednsoptions.cc | 115 + pdns/ednsoptions.hh | 53 + pdns/ednssubnet.cc | 108 + pdns/ednssubnet.hh | 38 + pdns/effective_tld_names.dat | 12987 +++++++ pdns/epollmplexer.cc | 203 + pdns/filterpo.hh | 244 + pdns/fuzz_dnsdistcache.cc | 47 + pdns/fuzz_moadnsparser.cc | 63 + pdns/fuzz_packetcache.cc | 57 + pdns/fuzz_zoneparsertng.cc | 60 + pdns/gettime.cc | 52 + pdns/gettime.hh | 24 + pdns/gss_context.cc | 490 + pdns/gss_context.hh | 184 + pdns/histog.hh | 101 + pdns/inflighter.cc | 271 + pdns/ipcipher.cc | 99 + pdns/ipcipher.hh | 9 + pdns/iputils.cc | 415 + pdns/iputils.hh | 1069 + pdns/ixfr.cc | 259 + pdns/ixfr.hh | 33 + pdns/ixfrdist-stats.cc | 108 + pdns/ixfrdist-stats.hh | 98 + pdns/ixfrdist-web.cc | 51 + pdns/ixfrdist-web.hh | 37 + pdns/ixfrdist.cc | 1393 + pdns/ixfrdist.example.yml | 107 + pdns/ixfrdist.service.in | 24 + pdns/ixfrutils.cc | 183 + pdns/ixfrutils.hh | 57 + pdns/ixplore.cc | 252 + pdns/json.cc | 115 + pdns/json.hh | 41 + pdns/kqueuemplexer.cc | 193 + pdns/kvresp.cc | 81 + pdns/lock.hh | 224 + pdns/logger.cc | 198 + pdns/logger.hh | 128 + pdns/lua-auth4.cc | 192 + pdns/lua-auth4.hh | 46 + pdns/lua-base4.cc | 253 + pdns/lua-base4.hh | 33 + pdns/lua-record.cc | 928 + pdns/mastercommunicator.cc | 317 + pdns/minicurl.cc | 177 + pdns/minicurl.hh | 51 + pdns/misc.cc | 1524 + pdns/misc.hh | 605 + pdns/mplexer.hh | 241 + pdns/mtasker.cc | 412 + pdns/named.conf.parsertest | 70 + pdns/nameserver.cc | 398 + pdns/nameserver.hh | 109 + pdns/namespaces.hh | 81 + pdns/notify.cc | 171 + pdns/nproxy.cc | 367 + pdns/nsec3dig.cc | 291 + pdns/nsecrecords.cc | 337 + pdns/opensslsigners.cc | 1111 + pdns/opensslsigners.hh | 35 + pdns/packetcache.hh | 152 + pdns/packethandler.cc | 1585 + pdns/packethandler.hh | 121 + pdns/pdns.init.in | 206 + pdns/pdns.service.in | 32 + pdns/pdnsexception.hh | 47 + pdns/pdnsutil.cc | 3342 ++ pdns/pkcs11signers.cc | 1026 + pdns/pkcs11signers.hh | 71 + pdns/pollmplexer.cc | 182 + pdns/portsmplexer.cc | 169 + pdns/protobuf.cc | 345 + pdns/protobuf.hh | 87 + pdns/qtype.cc | 116 + pdns/qtype.hh | 240 + pdns/rcpgenerator.cc | 664 + pdns/rcpgenerator.hh | 109 + pdns/rec-lua-conf.hh | 93 + pdns/receiver.cc | 636 + pdns/recursor_cache.hh | 222 + pdns/resolver.cc | 582 + pdns/resolver.hh | 111 + pdns/responsestats-auth.cc | 56 + pdns/responsestats.cc | 96 + pdns/responsestats.hh | 46 + pdns/rfc2136handler.cc | 1121 + pdns/root-dnssec.hh | 25 + pdns/saxfr.cc | 308 + pdns/sdig.cc | 293 + pdns/secpoll-auth.cc | 83 + pdns/secpoll-auth.hh | 31 + pdns/serialtweaker.cc | 182 + pdns/sha.hh | 57 + pdns/sholder.hh | 138 + pdns/signingpipe.cc | 344 + pdns/signingpipe.hh | 84 + pdns/sillyrecords.cc | 334 + pdns/slavecommunicator.cc | 1008 + pdns/sodiumsigners.cc | 140 + pdns/sortlist.hh | 48 + pdns/speedtest.cc | 939 + pdns/ssqlite3.cc | 276 + pdns/ssqlite3.hh | 62 + pdns/sstuff.hh | 365 + pdns/statbag.cc | 342 + pdns/statbag.hh | 152 + pdns/statnode.cc | 119 + pdns/statnode.hh | 72 + pdns/stubquery.cc | 69 + pdns/stubresolver.cc | 171 + pdns/stubresolver.hh | 28 + pdns/tcpreceiver.cc | 1397 + pdns/tcpreceiver.hh | 80 + pdns/test-arguments_cc.cc | 61 + pdns/test-base32_cc.cc | 38 + pdns/test-base64_cc.cc | 77 + pdns/test-bindparser_cc.cc | 60 + pdns/test-common.hh | 42 + pdns/test-digests_hh.cc | 32 + pdns/test-distributor_hh.cc | 163 + pdns/test-dns_random_hh.cc | 184 + pdns/test-dnsname_cc.cc | 967 + pdns/test-dnsparser_cc.cc | 487 + pdns/test-dnsparser_hh.cc | 21 + pdns/test-dnsrecordcontent.cc | 45 + pdns/test-dnsrecords_cc.cc | 568 + pdns/test-dnswriter_cc.cc | 81 + pdns/test-ipcrypt_cc.cc | 70 + pdns/test-iputils_hh.cc | 472 + pdns/test-ixfr_cc.cc | 310 + pdns/test-lock_hh.cc | 63 + pdns/test-lua_auth4_cc.cc | 73 + pdns/test-misc_hh.cc | 180 + pdns/test-mplexer.cc | 182 + pdns/test-nameserver_cc.cc | 52 + pdns/test-packetcache_cc.cc | 472 + pdns/test-packetcache_hh.cc | 337 + pdns/test-rcpgenerator_cc.cc | 34 + pdns/test-sha_hh.cc | 63 + pdns/test-signers.cc | 260 + pdns/test-statbag_cc.cc | 109 + pdns/test-tsig.cc | 243 + pdns/test-zoneparser_tng_cc.cc | 57 + pdns/testrunner.cc | 31 + pdns/threadname.cc | 69 + pdns/threadname.hh | 25 + pdns/tkey.cc | 99 + pdns/toysdig.cc | 183 + pdns/tsig-tests.cc | 82 + pdns/tsigutils.cc | 58 + pdns/tsigutils.hh | 26 + pdns/tsigverifier.cc | 74 + pdns/tsigverifier.hh | 22 + pdns/ueberbackend.cc | 700 + pdns/ueberbackend.hh | 167 + pdns/unix_semaphore.cc | 186 + pdns/unix_utility.cc | 300 + pdns/utility.hh | 155 + pdns/uuid-utils.cc | 47 + pdns/uuid-utils.hh | 28 + pdns/validate.cc | 1102 + pdns/validate.hh | 81 + pdns/version.cc | 175 + pdns/version.hh | 39 + pdns/webserver.cc | 477 + pdns/webserver.hh | 248 + pdns/ws-api.cc | 372 + pdns/ws-api.hh | 46 + pdns/ws-auth.cc | 2309 ++ pdns/ws-auth.hh | 101 + pdns/zone2json.cc | 241 + pdns/zone2ldap.cc | 372 + pdns/zone2sql.cc | 467 + pdns/zoneparser-tng.cc | 542 + pdns/zoneparser-tng.hh | 72 + regression-tests/zones/unit.test | 10 + 620 files changed, 221424 insertions(+) create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NOTICE create mode 100644 README create mode 100644 aclocal.m4 create mode 100755 build-aux/compile create mode 100755 build-aux/config.guess create mode 100755 build-aux/config.sub create mode 100755 build-aux/depcomp create mode 100755 build-aux/install-sh create mode 100644 build-aux/ltmain.sh create mode 100755 build-aux/missing create mode 100755 build-aux/test-driver create mode 100755 build-aux/ylwrap create mode 100755 builder-support/gen-version create mode 100644 codedocs/Makefile.am create mode 100644 codedocs/Makefile.in create mode 100644 codedocs/doxygen.conf create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100644 contrib/powerdns.solaris.init.d create mode 100644 docs/Makefile.am create mode 100644 docs/Makefile.in create mode 100644 docs/calidns.1 create mode 100644 docs/dnsbulktest.1 create mode 100644 docs/dnsgram.1 create mode 100644 docs/dnspcap2calidns.1 create mode 100644 docs/dnspcap2protobuf.1 create mode 100644 docs/dnsreplay.1 create mode 100644 docs/dnsscan.1 create mode 100644 docs/dnsscope.1 create mode 100644 docs/dnstcpbench.1 create mode 100644 docs/dnswasher.1 create mode 100644 docs/dumresp.1 create mode 100644 docs/ixfrdist.1 create mode 100644 docs/ixfrdist.yml.5 create mode 100644 docs/ixplore.1 create mode 100644 docs/nproxy.1 create mode 100644 docs/nsec3dig.1 create mode 100644 docs/pdns_control.1 create mode 100644 docs/pdns_notify.1 create mode 100644 docs/pdns_server.1 create mode 100644 docs/pdnsutil.1 create mode 100644 docs/saxfr.1 create mode 100644 docs/sdig.1 create mode 100644 docs/zone2json.1 create mode 100644 docs/zone2ldap.1 create mode 100644 docs/zone2sql.1 create mode 100644 ext/Makefile.am create mode 100644 ext/Makefile.in create mode 100644 ext/ipcrypt/LICENSE create mode 100644 ext/ipcrypt/Makefile.am create mode 100644 ext/ipcrypt/Makefile.in create mode 100644 ext/ipcrypt/ipcrypt.c create mode 100644 ext/ipcrypt/ipcrypt.h create mode 100644 ext/json11/Makefile.am create mode 100644 ext/json11/Makefile.in create mode 100644 ext/json11/json11.cpp create mode 100644 ext/json11/json11.hpp create mode 100644 ext/luawrapper/include/LuaContext.hpp create mode 100644 ext/yahttp/LICENSE create mode 100644 ext/yahttp/Makefile.am create mode 100644 ext/yahttp/Makefile.in create mode 100644 ext/yahttp/README.md create mode 100644 ext/yahttp/yahttp/Makefile.am create mode 100644 ext/yahttp/yahttp/Makefile.in create mode 100644 ext/yahttp/yahttp/cookie.hpp create mode 100644 ext/yahttp/yahttp/exception.hpp create mode 100644 ext/yahttp/yahttp/reqresp.cpp create mode 100644 ext/yahttp/yahttp/reqresp.hpp create mode 100644 ext/yahttp/yahttp/router.cpp create mode 100644 ext/yahttp/yahttp/router.hpp create mode 100644 ext/yahttp/yahttp/url.hpp create mode 100644 ext/yahttp/yahttp/utility.hpp create mode 100644 ext/yahttp/yahttp/yahttp-config.h create mode 100644 ext/yahttp/yahttp/yahttp.hpp create mode 100644 m4/ac_pthread_set_name.m4 create mode 100644 m4/ax_arg_default_enable_disable.m4 create mode 100644 m4/ax_cxx_compile_stdcxx_11.m4 create mode 100644 m4/boost.m4 create mode 100644 m4/libcurl.m4 create mode 100644 m4/libtool.m4 create mode 100644 m4/ltoptions.m4 create mode 100644 m4/ltsugar.m4 create mode 100644 m4/ltversion.m4 create mode 100644 m4/lt~obsolete.m4 create mode 100644 m4/pdns_check_bison.m4 create mode 100644 m4/pdns_check_cdb.m4 create mode 100644 m4/pdns_check_clock_gettime.m4 create mode 100644 m4/pdns_check_curl_program.m4 create mode 100644 m4/pdns_check_flex.m4 create mode 100644 m4/pdns_check_ldap.m4 create mode 100644 m4/pdns_check_libcrypto.m4 create mode 100644 m4/pdns_check_libcrypto_ecdsa.m4 create mode 100644 m4/pdns_check_libcrypto_eddsa.m4 create mode 100644 m4/pdns_check_libcurl.m4 create mode 100644 m4/pdns_check_lmdb.m4 create mode 100644 m4/pdns_check_lua_hpp.m4 create mode 100644 m4/pdns_check_network_libs.m4 create mode 100644 m4/pdns_check_opendbx.m4 create mode 100644 m4/pdns_check_os.m4 create mode 100644 m4/pdns_check_ragel.m4 create mode 100644 m4/pdns_check_sqlite3.m4 create mode 100644 m4/pdns_check_virtualenv.m4 create mode 100644 m4/pdns_d_fortify_source.m4 create mode 100644 m4/pdns_enable_backend_unit_tests.m4 create mode 100644 m4/pdns_enable_coverage.m4 create mode 100644 m4/pdns_enable_fuzz_targets.m4 create mode 100644 m4/pdns_enable_gss_tsig.m4 create mode 100644 m4/pdns_enable_ixfrdist.m4 create mode 100644 m4/pdns_enable_kiss.m4 create mode 100644 m4/pdns_enable_malloc_trace.m4 create mode 100644 m4/pdns_enable_p11kit.m4 create mode 100644 m4/pdns_enable_remotebackend_zeromq.m4 create mode 100644 m4/pdns_enable_reproducible.m4 create mode 100644 m4/pdns_enable_sanitizers.m4 create mode 100644 m4/pdns_enable_tools.m4 create mode 100644 m4/pdns_enable_unit_tests.m4 create mode 100644 m4/pdns_enable_verbose_logging.m4 create mode 100644 m4/pdns_from_git.m4 create mode 100644 m4/pdns_param_ssp_buffer_size.m4 create mode 100644 m4/pdns_pie.m4 create mode 100644 m4/pdns_relro.m4 create mode 100644 m4/pdns_stack_protector.m4 create mode 100644 m4/pdns_with_geo.m4 create mode 100644 m4/pdns_with_libdecaf.m4 create mode 100644 m4/pdns_with_libsodium.m4 create mode 100644 m4/pdns_with_lua.m4 create mode 100644 m4/pdns_with_lua_records.m4 create mode 100644 m4/pdns_with_mysql.m4 create mode 100644 m4/pdns_with_oracle.m4 create mode 100644 m4/pdns_with_postgresql.m4 create mode 100644 m4/pdns_with_protobuf.m4 create mode 100644 m4/pdns_with_sqlite3.m4 create mode 100644 m4/pdns_with_unixodbc.m4 create mode 100644 m4/systemd.m4 create mode 100644 m4/tm-gmtoff.m4 create mode 100644 m4/warnings.m4 create mode 100644 modules/Makefile.am create mode 100644 modules/Makefile.in create mode 100644 modules/bindbackend/Makefile.am create mode 100644 modules/bindbackend/Makefile.in create mode 100644 modules/bindbackend/OBJECTFILES create mode 100644 modules/bindbackend/OBJECTLIBS create mode 100644 modules/bindbackend/bindbackend2.cc create mode 100644 modules/bindbackend/bindbackend2.hh create mode 100644 modules/bindbackend/binddnssec.cc create mode 100644 modules/geoipbackend/Makefile.am create mode 100644 modules/geoipbackend/Makefile.in create mode 100644 modules/geoipbackend/OBJECTFILES create mode 100644 modules/geoipbackend/OBJECTLIBS create mode 100644 modules/geoipbackend/geoipbackend.cc create mode 100644 modules/geoipbackend/geoipbackend.hh create mode 100644 modules/geoipbackend/geoipinterface-dat.cc create mode 100644 modules/geoipbackend/geoipinterface-mmdb.cc create mode 100644 modules/geoipbackend/geoipinterface.cc create mode 100644 modules/geoipbackend/geoipinterface.hh create mode 100644 modules/gmysqlbackend/3.4.0_to_4.1.0_schema.mysql.sql create mode 100644 modules/gmysqlbackend/4.1.0_to_4.2.0_schema.mysql.sql create mode 100644 modules/gmysqlbackend/Makefile.am create mode 100644 modules/gmysqlbackend/Makefile.in create mode 100644 modules/gmysqlbackend/OBJECTFILES create mode 100644 modules/gmysqlbackend/OBJECTLIBS create mode 100644 modules/gmysqlbackend/dnssec-3.x_to_3.4.0_schema.mysql.sql create mode 100644 modules/gmysqlbackend/gmysqlbackend.cc create mode 100644 modules/gmysqlbackend/gmysqlbackend.hh create mode 100644 modules/gmysqlbackend/nodnssec-3.x_to_3.4.0_schema.mysql.sql create mode 100644 modules/gmysqlbackend/schema.mysql.sql create mode 100644 modules/gmysqlbackend/smysql.cc create mode 100644 modules/gmysqlbackend/smysql.hh create mode 100644 modules/godbcbackend/4.0.0_to_4.2.0_schema.mssql.sql create mode 100644 modules/godbcbackend/Makefile.am create mode 100644 modules/godbcbackend/Makefile.in create mode 100644 modules/godbcbackend/OBJECTFILES create mode 100644 modules/godbcbackend/OBJECTLIBS create mode 100644 modules/godbcbackend/godbcbackend.cc create mode 100644 modules/godbcbackend/godbcbackend.hh create mode 100644 modules/godbcbackend/schema.mssql.sql create mode 100644 modules/godbcbackend/sodbc.cc create mode 100644 modules/godbcbackend/sodbc.hh create mode 100644 modules/goraclebackend/Makefile.am create mode 100644 modules/goraclebackend/Makefile.in create mode 100644 modules/goraclebackend/OBJECTFILES create mode 100644 modules/goraclebackend/OBJECTLIBS create mode 100644 modules/goraclebackend/drop-schema.goracle.sql create mode 100644 modules/goraclebackend/goraclebackend.cc create mode 100644 modules/goraclebackend/goraclebackend.hh create mode 100644 modules/goraclebackend/schema.goracle.sql create mode 100644 modules/goraclebackend/soracle.cc create mode 100644 modules/goraclebackend/soracle.hh create mode 100644 modules/gpgsqlbackend/3.4.0_to_4.1.0_schema.pgsql.sql create mode 100644 modules/gpgsqlbackend/4.1.0_to_4.2.0_schema.pgsql.sql create mode 100644 modules/gpgsqlbackend/Makefile.am create mode 100644 modules/gpgsqlbackend/Makefile.in create mode 100644 modules/gpgsqlbackend/OBJECTFILES create mode 100644 modules/gpgsqlbackend/OBJECTLIBS create mode 100644 modules/gpgsqlbackend/dnssec-3.x_to_3.4.0_schema.pgsql.sql create mode 100644 modules/gpgsqlbackend/gpgsqlbackend.cc create mode 100644 modules/gpgsqlbackend/gpgsqlbackend.hh create mode 100644 modules/gpgsqlbackend/nodnssec-3.x_to_3.4.0_schema.pgsql.sql create mode 100644 modules/gpgsqlbackend/schema.pgsql.sql create mode 100644 modules/gpgsqlbackend/spgsql.cc create mode 100644 modules/gpgsqlbackend/spgsql.hh create mode 100644 modules/gsqlite3backend/3.4.0_to_4.0.0_schema.sqlite3.sql create mode 100644 modules/gsqlite3backend/4.0.0_to_4.2.0_schema.sqlite3.sql create mode 100644 modules/gsqlite3backend/Makefile.am create mode 100644 modules/gsqlite3backend/Makefile.in create mode 100644 modules/gsqlite3backend/OBJECTFILES create mode 100644 modules/gsqlite3backend/OBJECTLIBS create mode 100644 modules/gsqlite3backend/dnssec-3.x_to_3.4.0_schema.sqlite3.sql create mode 100644 modules/gsqlite3backend/gsqlite3backend.cc create mode 100644 modules/gsqlite3backend/gsqlite3backend.hh create mode 100644 modules/gsqlite3backend/nodnssec-3.x_to_3.4.0_schema.sqlite3.sql create mode 100644 modules/gsqlite3backend/schema.sqlite3.sql create mode 100644 modules/ldapbackend/Makefile.am create mode 100644 modules/ldapbackend/Makefile.in create mode 100644 modules/ldapbackend/OBJECTFILES create mode 100644 modules/ldapbackend/OBJECTLIBS create mode 100644 modules/ldapbackend/dnsdomain2.schema create mode 100644 modules/ldapbackend/exceptions.hh create mode 100644 modules/ldapbackend/ldapauthenticator.cc create mode 100644 modules/ldapbackend/ldapauthenticator.hh create mode 100644 modules/ldapbackend/ldapauthenticator_p.hh create mode 100644 modules/ldapbackend/ldapbackend.cc create mode 100644 modules/ldapbackend/ldapbackend.hh create mode 100644 modules/ldapbackend/ldaputils.cc create mode 100644 modules/ldapbackend/ldaputils.hh create mode 100644 modules/ldapbackend/master.cc create mode 100644 modules/ldapbackend/native.cc create mode 100644 modules/ldapbackend/pdns-domaininfo.schema create mode 100644 modules/ldapbackend/powerldap.cc create mode 100644 modules/ldapbackend/powerldap.hh create mode 100644 modules/ldapbackend/utils.hh create mode 100644 modules/lmdbbackend/Makefile.am create mode 100644 modules/lmdbbackend/Makefile.in create mode 100644 modules/lmdbbackend/OBJECTFILES create mode 100644 modules/lmdbbackend/OBJECTLIBS create mode 100644 modules/lmdbbackend/lmdb-safe.cc create mode 100644 modules/lmdbbackend/lmdb-safe.hh create mode 100644 modules/lmdbbackend/lmdb-typed.cc create mode 100644 modules/lmdbbackend/lmdb-typed.hh create mode 100644 modules/lmdbbackend/lmdbbackend.cc create mode 100644 modules/lmdbbackend/lmdbbackend.hh create mode 100644 modules/lua2backend/Makefile.am create mode 100644 modules/lua2backend/Makefile.in create mode 100644 modules/lua2backend/OBJECTFILES create mode 100644 modules/lua2backend/OBJECTLIBS create mode 100644 modules/lua2backend/lua2api2.cc create mode 100644 modules/lua2backend/lua2api2.hh create mode 100644 modules/lua2backend/lua2backend.cc create mode 100644 modules/lua2backend/lua2backend.hh create mode 100644 modules/luabackend/Makefile.am create mode 100644 modules/luabackend/Makefile.in create mode 100644 modules/luabackend/OBJECTFILES create mode 100644 modules/luabackend/OBJECTLIBS create mode 100644 modules/luabackend/README create mode 100644 modules/luabackend/dnssec.cc create mode 100644 modules/luabackend/lua_functions.cc create mode 100644 modules/luabackend/lua_functions.hh create mode 100644 modules/luabackend/luabackend.cc create mode 100644 modules/luabackend/luabackend.hh create mode 100644 modules/luabackend/master.cc create mode 100644 modules/luabackend/minimal.cc create mode 100644 modules/luabackend/private.cc create mode 100644 modules/luabackend/reload.cc create mode 100644 modules/luabackend/slave.cc create mode 100644 modules/luabackend/supermaster.cc create mode 100644 modules/mydnsbackend/Makefile.am create mode 100644 modules/mydnsbackend/Makefile.in create mode 100644 modules/mydnsbackend/OBJECTFILES create mode 100644 modules/mydnsbackend/OBJECTLIBS create mode 100644 modules/mydnsbackend/mydnsbackend.cc create mode 100644 modules/mydnsbackend/mydnsbackend.hh create mode 100644 modules/mydnsbackend/schema.mydns.sql create mode 100644 modules/opendbxbackend/Makefile.am create mode 100644 modules/opendbxbackend/Makefile.in create mode 100644 modules/opendbxbackend/OBJECTFILES create mode 100644 modules/opendbxbackend/OBJECTLIBS create mode 100644 modules/opendbxbackend/README create mode 100644 modules/opendbxbackend/odbxbackend.cc create mode 100644 modules/opendbxbackend/odbxbackend.hh create mode 100644 modules/opendbxbackend/odbxprivate.cc create mode 100644 modules/oraclebackend/ChangeLog create mode 100644 modules/oraclebackend/INSTALL create mode 100644 modules/oraclebackend/Makefile.am create mode 100644 modules/oraclebackend/Makefile.in create mode 100644 modules/oraclebackend/OBJECTFILES create mode 100644 modules/oraclebackend/OBJECTLIBS create mode 100644 modules/oraclebackend/README create mode 100644 modules/oraclebackend/TODO create mode 100644 modules/oraclebackend/drop-schema.oracle.sql create mode 100644 modules/oraclebackend/oraclebackend.cc create mode 100644 modules/oraclebackend/oraclebackend.hh create mode 100644 modules/oraclebackend/schema.oracle.sql create mode 100644 modules/pipebackend/Makefile.am create mode 100644 modules/pipebackend/Makefile.in create mode 100644 modules/pipebackend/OBJECTFILES create mode 100644 modules/pipebackend/OBJECTLIBS create mode 100755 modules/pipebackend/backend.pl create mode 100644 modules/pipebackend/coprocess.cc create mode 100644 modules/pipebackend/coprocess.hh create mode 100644 modules/pipebackend/pipebackend.cc create mode 100644 modules/pipebackend/pipebackend.hh create mode 100644 modules/randombackend/Makefile.am create mode 100644 modules/randombackend/Makefile.in create mode 100644 modules/randombackend/OBJECTFILES create mode 100644 modules/randombackend/OBJECTLIBS create mode 100644 modules/randombackend/randombackend.cc create mode 100644 modules/remotebackend/Gemfile create mode 100644 modules/remotebackend/Gemfile.lock create mode 100644 modules/remotebackend/Makefile.am create mode 100644 modules/remotebackend/Makefile.in create mode 100644 modules/remotebackend/OBJECTFILES create mode 100644 modules/remotebackend/OBJECTLIBS create mode 100644 modules/remotebackend/httpconnector.cc create mode 100644 modules/remotebackend/pipeconnector.cc create mode 100644 modules/remotebackend/remotebackend.cc create mode 100644 modules/remotebackend/remotebackend.hh create mode 100644 modules/remotebackend/test-remotebackend-http.cc create mode 100644 modules/remotebackend/test-remotebackend-json.cc create mode 100644 modules/remotebackend/test-remotebackend-keys.hh create mode 100644 modules/remotebackend/test-remotebackend-pipe.cc create mode 100644 modules/remotebackend/test-remotebackend-post.cc create mode 100644 modules/remotebackend/test-remotebackend-unix.cc create mode 100644 modules/remotebackend/test-remotebackend-zeromq.cc create mode 100644 modules/remotebackend/test-remotebackend.cc create mode 100755 modules/remotebackend/testrunner.sh create mode 100644 modules/remotebackend/unittest.rb create mode 100755 modules/remotebackend/unittest_http.rb create mode 100755 modules/remotebackend/unittest_json.rb create mode 100755 modules/remotebackend/unittest_pipe.rb create mode 100755 modules/remotebackend/unittest_post.rb create mode 100755 modules/remotebackend/unittest_zeromq.rb create mode 100644 modules/remotebackend/unixconnector.cc create mode 100644 modules/remotebackend/zmqconnector.cc create mode 100644 modules/tinydnsbackend/Makefile.am create mode 100644 modules/tinydnsbackend/Makefile.in create mode 100644 modules/tinydnsbackend/OBJECTFILES create mode 100644 modules/tinydnsbackend/OBJECTLIBS create mode 100644 modules/tinydnsbackend/cdb.cc create mode 100644 modules/tinydnsbackend/cdb.hh create mode 100644 modules/tinydnsbackend/tinydnsbackend.cc create mode 100644 modules/tinydnsbackend/tinydnsbackend.hh create mode 100644 pdns/Makefile.am create mode 100644 pdns/Makefile.in create mode 100644 pdns/anadns.hh create mode 100644 pdns/arguments.cc create mode 100644 pdns/arguments.hh create mode 100644 pdns/ascii.hh create mode 100644 pdns/auth-caches.cc create mode 100644 pdns/auth-caches.hh create mode 100644 pdns/auth-carbon.cc create mode 100644 pdns/auth-packetcache.cc create mode 100644 pdns/auth-packetcache.hh create mode 100644 pdns/auth-querycache.cc create mode 100644 pdns/auth-querycache.hh create mode 100644 pdns/backends/gsql/gsqlbackend.cc create mode 100644 pdns/backends/gsql/gsqlbackend.hh create mode 100644 pdns/backends/gsql/ssql.hh create mode 100644 pdns/base32.cc create mode 100644 pdns/base32.hh create mode 100644 pdns/base64.cc create mode 100644 pdns/base64.hh create mode 100644 pdns/bind-dnssec.schema.sqlite3.sql create mode 100644 pdns/bind-dnssec.schema.sqlite3.sql.h create mode 100644 pdns/bindlexer.c create mode 100644 pdns/bindlexer.l create mode 100644 pdns/bindparser.cc create mode 100644 pdns/bindparser.h create mode 100644 pdns/bindparser.hh create mode 100644 pdns/bindparser.yy create mode 100644 pdns/bindparserclasses.hh create mode 100644 pdns/cachecleaner.hh create mode 100644 pdns/calidns.cc create mode 100644 pdns/circular_buffer.hh create mode 100644 pdns/comfun.cc create mode 100644 pdns/comment.hh create mode 100644 pdns/common_startup.cc create mode 100644 pdns/common_startup.hh create mode 100644 pdns/communicator.cc create mode 100644 pdns/communicator.hh create mode 100644 pdns/dbdnsseckeeper.cc create mode 100644 pdns/decafsigners.cc create mode 100644 pdns/devpollmplexer.cc create mode 100644 pdns/digests.hh create mode 100644 pdns/distributor.hh create mode 100644 pdns/dns.cc create mode 100644 pdns/dns.hh create mode 100644 pdns/dns_random.cc create mode 100644 pdns/dns_random.hh create mode 100644 pdns/dns_random_urandom.cc create mode 100644 pdns/dnsbackend.cc create mode 100644 pdns/dnsbackend.hh create mode 100644 pdns/dnsbulktest.cc create mode 100644 pdns/dnsdemog.cc create mode 100644 pdns/dnsdist-cache.cc create mode 100644 pdns/dnsdist-cache.hh create mode 100644 pdns/dnsdist-ecs.cc create mode 100644 pdns/dnsdist-ecs.hh create mode 100644 pdns/dnsgram.cc create mode 100644 pdns/dnslabeltext.cc create mode 100644 pdns/dnslabeltext.rl create mode 100644 pdns/dnsmessage.proto create mode 100644 pdns/dnsname.cc create mode 100644 pdns/dnsname.hh create mode 100644 pdns/dnspacket.cc create mode 100644 pdns/dnspacket.hh create mode 100644 pdns/dnsparser.cc create mode 100644 pdns/dnsparser.hh create mode 100644 pdns/dnspcap.cc create mode 100644 pdns/dnspcap.hh create mode 100644 pdns/dnspcap2calidns.cc create mode 100644 pdns/dnspcap2protobuf.cc create mode 100644 pdns/dnsproxy.cc create mode 100644 pdns/dnsproxy.hh create mode 100644 pdns/dnsrecords.cc create mode 100644 pdns/dnsrecords.hh create mode 100644 pdns/dnsreplay.cc create mode 100644 pdns/dnsscan.cc create mode 100644 pdns/dnsscope.cc create mode 100644 pdns/dnssecinfra.cc create mode 100644 pdns/dnssecinfra.hh create mode 100644 pdns/dnsseckeeper.hh create mode 100644 pdns/dnssecsigner.cc create mode 100644 pdns/dnstcpbench.cc create mode 100644 pdns/dnswasher.cc create mode 100644 pdns/dnswriter.cc create mode 100644 pdns/dnswriter.hh create mode 100644 pdns/doh.hh create mode 100644 pdns/dumresp.cc create mode 100644 pdns/dynhandler.cc create mode 100644 pdns/dynhandler.hh create mode 100644 pdns/dynlistener.cc create mode 100644 pdns/dynlistener.hh create mode 100644 pdns/dynloader.cc create mode 100644 pdns/dynmessenger.cc create mode 100644 pdns/dynmessenger.hh create mode 100644 pdns/ednscookies.cc create mode 100644 pdns/ednscookies.hh create mode 100644 pdns/ednsoptions.cc create mode 100644 pdns/ednsoptions.hh create mode 100644 pdns/ednssubnet.cc create mode 100644 pdns/ednssubnet.hh create mode 100644 pdns/effective_tld_names.dat create mode 100644 pdns/epollmplexer.cc create mode 100644 pdns/filterpo.hh create mode 100644 pdns/fuzz_dnsdistcache.cc create mode 100644 pdns/fuzz_moadnsparser.cc create mode 100644 pdns/fuzz_packetcache.cc create mode 100644 pdns/fuzz_zoneparsertng.cc create mode 100644 pdns/gettime.cc create mode 100644 pdns/gettime.hh create mode 100644 pdns/gss_context.cc create mode 100644 pdns/gss_context.hh create mode 100644 pdns/histog.hh create mode 100644 pdns/inflighter.cc create mode 100644 pdns/ipcipher.cc create mode 100644 pdns/ipcipher.hh create mode 100644 pdns/iputils.cc create mode 100644 pdns/iputils.hh create mode 100644 pdns/ixfr.cc create mode 100644 pdns/ixfr.hh create mode 100644 pdns/ixfrdist-stats.cc create mode 100644 pdns/ixfrdist-stats.hh create mode 100644 pdns/ixfrdist-web.cc create mode 100644 pdns/ixfrdist-web.hh create mode 100644 pdns/ixfrdist.cc create mode 100644 pdns/ixfrdist.example.yml create mode 100644 pdns/ixfrdist.service.in create mode 100644 pdns/ixfrutils.cc create mode 100644 pdns/ixfrutils.hh create mode 100644 pdns/ixplore.cc create mode 100644 pdns/json.cc create mode 100644 pdns/json.hh create mode 100644 pdns/kqueuemplexer.cc create mode 100644 pdns/kvresp.cc create mode 100644 pdns/lock.hh create mode 100644 pdns/logger.cc create mode 100644 pdns/logger.hh create mode 100644 pdns/lua-auth4.cc create mode 100644 pdns/lua-auth4.hh create mode 100644 pdns/lua-base4.cc create mode 100644 pdns/lua-base4.hh create mode 100644 pdns/lua-record.cc create mode 100644 pdns/mastercommunicator.cc create mode 100644 pdns/minicurl.cc create mode 100644 pdns/minicurl.hh create mode 100644 pdns/misc.cc create mode 100644 pdns/misc.hh create mode 100644 pdns/mplexer.hh create mode 100644 pdns/mtasker.cc create mode 100644 pdns/named.conf.parsertest create mode 100644 pdns/nameserver.cc create mode 100644 pdns/nameserver.hh create mode 100644 pdns/namespaces.hh create mode 100644 pdns/notify.cc create mode 100644 pdns/nproxy.cc create mode 100644 pdns/nsec3dig.cc create mode 100644 pdns/nsecrecords.cc create mode 100644 pdns/opensslsigners.cc create mode 100644 pdns/opensslsigners.hh create mode 100644 pdns/packetcache.hh create mode 100644 pdns/packethandler.cc create mode 100644 pdns/packethandler.hh create mode 100755 pdns/pdns.init.in create mode 100644 pdns/pdns.service.in create mode 100644 pdns/pdnsexception.hh create mode 100644 pdns/pdnsutil.cc create mode 100644 pdns/pkcs11signers.cc create mode 100644 pdns/pkcs11signers.hh create mode 100644 pdns/pollmplexer.cc create mode 100644 pdns/portsmplexer.cc create mode 100644 pdns/protobuf.cc create mode 100644 pdns/protobuf.hh create mode 100644 pdns/qtype.cc create mode 100644 pdns/qtype.hh create mode 100644 pdns/rcpgenerator.cc create mode 100644 pdns/rcpgenerator.hh create mode 100644 pdns/rec-lua-conf.hh create mode 100644 pdns/receiver.cc create mode 100644 pdns/recursor_cache.hh create mode 100644 pdns/resolver.cc create mode 100644 pdns/resolver.hh create mode 100644 pdns/responsestats-auth.cc create mode 100644 pdns/responsestats.cc create mode 100644 pdns/responsestats.hh create mode 100644 pdns/rfc2136handler.cc create mode 100644 pdns/root-dnssec.hh create mode 100644 pdns/saxfr.cc create mode 100644 pdns/sdig.cc create mode 100644 pdns/secpoll-auth.cc create mode 100644 pdns/secpoll-auth.hh create mode 100644 pdns/serialtweaker.cc create mode 100644 pdns/sha.hh create mode 100644 pdns/sholder.hh create mode 100644 pdns/signingpipe.cc create mode 100644 pdns/signingpipe.hh create mode 100644 pdns/sillyrecords.cc create mode 100644 pdns/slavecommunicator.cc create mode 100644 pdns/sodiumsigners.cc create mode 100644 pdns/sortlist.hh create mode 100644 pdns/speedtest.cc create mode 100644 pdns/ssqlite3.cc create mode 100644 pdns/ssqlite3.hh create mode 100644 pdns/sstuff.hh create mode 100644 pdns/statbag.cc create mode 100644 pdns/statbag.hh create mode 100644 pdns/statnode.cc create mode 100644 pdns/statnode.hh create mode 100644 pdns/stubquery.cc create mode 100644 pdns/stubresolver.cc create mode 100644 pdns/stubresolver.hh create mode 100644 pdns/tcpreceiver.cc create mode 100644 pdns/tcpreceiver.hh create mode 100644 pdns/test-arguments_cc.cc create mode 100644 pdns/test-base32_cc.cc create mode 100644 pdns/test-base64_cc.cc create mode 100644 pdns/test-bindparser_cc.cc create mode 100644 pdns/test-common.hh create mode 100644 pdns/test-digests_hh.cc create mode 100644 pdns/test-distributor_hh.cc create mode 100644 pdns/test-dns_random_hh.cc create mode 100644 pdns/test-dnsname_cc.cc create mode 100644 pdns/test-dnsparser_cc.cc create mode 100644 pdns/test-dnsparser_hh.cc create mode 100644 pdns/test-dnsrecordcontent.cc create mode 100644 pdns/test-dnsrecords_cc.cc create mode 100644 pdns/test-dnswriter_cc.cc create mode 100644 pdns/test-ipcrypt_cc.cc create mode 100644 pdns/test-iputils_hh.cc create mode 100644 pdns/test-ixfr_cc.cc create mode 100644 pdns/test-lock_hh.cc create mode 100644 pdns/test-lua_auth4_cc.cc create mode 100644 pdns/test-misc_hh.cc create mode 100644 pdns/test-mplexer.cc create mode 100644 pdns/test-nameserver_cc.cc create mode 100644 pdns/test-packetcache_cc.cc create mode 100644 pdns/test-packetcache_hh.cc create mode 100644 pdns/test-rcpgenerator_cc.cc create mode 100644 pdns/test-sha_hh.cc create mode 100644 pdns/test-signers.cc create mode 100644 pdns/test-statbag_cc.cc create mode 100644 pdns/test-tsig.cc create mode 100644 pdns/test-zoneparser_tng_cc.cc create mode 100644 pdns/testrunner.cc create mode 100644 pdns/threadname.cc create mode 100644 pdns/threadname.hh create mode 100644 pdns/tkey.cc create mode 100644 pdns/toysdig.cc create mode 100644 pdns/tsig-tests.cc create mode 100644 pdns/tsigutils.cc create mode 100644 pdns/tsigutils.hh create mode 100644 pdns/tsigverifier.cc create mode 100644 pdns/tsigverifier.hh create mode 100644 pdns/ueberbackend.cc create mode 100644 pdns/ueberbackend.hh create mode 100644 pdns/unix_semaphore.cc create mode 100644 pdns/unix_utility.cc create mode 100644 pdns/utility.hh create mode 100644 pdns/uuid-utils.cc create mode 100644 pdns/uuid-utils.hh create mode 100644 pdns/validate.cc create mode 100644 pdns/validate.hh create mode 100644 pdns/version.cc create mode 100644 pdns/version.hh create mode 100644 pdns/webserver.cc create mode 100644 pdns/webserver.hh create mode 100644 pdns/ws-api.cc create mode 100644 pdns/ws-api.hh create mode 100644 pdns/ws-auth.cc create mode 100644 pdns/ws-auth.hh create mode 100644 pdns/zone2json.cc create mode 100644 pdns/zone2ldap.cc create mode 100644 pdns/zone2sql.cc create mode 100644 pdns/zoneparser-tng.cc create mode 100644 pdns/zoneparser-tng.hh create mode 100644 regression-tests/zones/unit.test diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..ecbc059 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..74a3b84 --- /dev/null +++ b/INSTALL @@ -0,0 +1,219 @@ +PowerDNS is copyright © 2001-2019 by PowerDNS.COM BV and lots of +contributors, using the GNU GPLv2 license (see NOTICE for the +exact license and exception used). + +All documentation can be found on http://doc.powerdns.com/ + +This file may lag behind at times. For most recent updates, always check +https://doc.powerdns.com/md/changelog/. + +Another good place to look for information is: +https://doc.powerdns.com/md/appendix/compiling-powerdns/ + +To file bugs, head towards: +https://github.com/PowerDNS/pdns/issues + +But please check if the issue is already reported there first. + +SOURCE CODE / GIT +----------------- +Source code is available on GitHub: + +```sh +git clone https://github.com/PowerDNS/pdns.git +``` + +This repository contains the sources for the PowerDNS Recursor, the PowerDNS +Authoritative Server, and dnsdist (a powerful DNS loadbalancer). All three can +be built from this repository. However, all three released separately as .tar.bz2, +.deb and .rpm. + +COMPILING Authoritative Server +------------------------------ +The PowerDNS Authoritative Server depends on Boost, OpenSSL and requires a +compiler with C++-2011 support. + +On Debian 9, the following is useful: + +```sh +apt install g++ libboost-all-dev libtool make pkg-config default-libmysqlclient-dev libssl-dev virtualenv +``` + +When building from git, the following packages are also required: + +```sh +apt install autoconf automake ragel bison flex +``` + +For Ubuntu 18.04 (Bionic Beaver), the following packages should be installed: + +```sh +apt install libcurl4-openssl-dev luajit lua-yaml-dev libyaml-cpp-dev libtolua-dev lua5.3 autoconf automake ragel bison flex g++ libboost-all-dev libtool make pkg-config libssl-dev virtualenv lua-yaml-dev libyaml-cpp-dev libluajit-5.1-dev libcurl4 gawk +# For DNSSEC ed25519 (algorithm 15) support with --with-libsodium +apt install libsodium-dev +# If using the gmysql (Generic MySQL) backend +apt install default-libmysqlclient-dev +# If using the gpgsql (Generic PostgreSQL) backend +apt install postgresql-server-dev-10 +# If using --enable-systemd (will create the service scripts so it can be managed with systemctl/service) +apt install libsystemd0 libsystemd-dev +# If using the geoip backend +apt install libmaxminddb-dev libmaxminddb0 libgeoip1 libgeoip-dev +``` + +Then generate the configure file: + +```sh +autoreconf -vi +``` + +To compile a very clean version, use: + +```sh +./configure --with-modules="" --without-lua --disable-lua-records +make +# make install +``` + +This generates a PowerDNS Authoritative Server binary with no modules built in. + +See https://doc.powerdns.com/authoritative/backends/index.html for a list of available modules. + +When `./configure` is run without `--with-modules`, the bind and gmysql module are +built-in by default and the pipe-backend is compiled for runtime loading. + +To add multiple modules, try: + +```sh +./configure --with-modules="bind gmysql gpgsql" +``` + +Note that you will need the development headers for PostgreSQL as well in this case. + +See https://doc.powerdns.com/authoritative/appendices/compiling.html for more details. + +If you run into C++11-related symbol trouble, please try passing `CPPFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0` (or 1) to `./configure` to make sure you are compatible with the installed dependencies. + +Compiling the Recursor +---------------------- +See [README.md](pdns/recursordist/README.md) in `pdns/recursordist/`. + +Compiling dnsdist +----------------- +See [README-dnsdist.md](pdns/README-dnsdist.md) in `pdns/`. + +Building the HTML documentation +------------------------------- + +The HTML documentation (as seen [on the PowerDNS docs site](https://doc.powerdns.com/authoritative/)) is built from ReStructured Text (rst) files located in `docs`. They are compiled into HTML files using [Sphinx](http://www.sphinx-doc.org/en/master/index.html), a documentation generator tool which is built in Python. + +**Using a normal Python installation** + +For those simply contributing to the documentation, this avoids needing to install the various build +tools and other dependencies. + +Install Python 2.7 or Python 3 (preferable) if you don't yet have it installed. On some operating +systems you may also have to install `python3-pip` or similarly named. + +Ubuntu 16.04 / 18.04 + +```sh +apt update +apt install python3 python3-pip python3-venv +``` + +macOS (using homebrew) + +```sh +brew install python3 +``` + +Update your `pip` and install/update `virtualenv` to avoid problems: + +```sh +# for python2, use "pip" instead of "pip3" +pip3 install -U pip +pip3 install -U virtualenv +``` + +Enter the repository's `docs` folder, set up the virtualenv, and install the requirements + +```sh +cd docs +# for python2, use "virtualenv .venv" instead +python3 -m venv .venv +source .venv/bin/activate +# The virtualenv may use an older pip, so upgrade it again +pip3 install -U pip setuptools setuptools-git +# Now you can install the requirements +pip3 install -r requirements.txt +``` + +Finally, you can build the documentation: + +```sh +sphinx-build . html-docs +``` + +Note: If your shell has problems finding sphinx-build, try using `.venv/bin/sphinx-build` instead. + +The HTML documentation is now available in `html-docs`. + +**Using the build tools** + +This method is preferable for those who already have a working build environment for PowerDNS. + +Install the dependencies under "COMPILING", and run autoreconf if you haven't already: + +```sh +autoreconf -vi +``` + +Enter the `docs` folder, and use make to build the HTML docs. + +``` +cd docs +make html-docs +``` + +The HTML documentation will now be available in `html-docs`. + +Solaris Notes +------------- +Use a recent gcc. OpenCSW is a good source, as is Solaris 11 IPS. + +If you encounter problems with the Solaris make, gmake is advised. + +FreeBSD Notes +------------- +You need to compile using gmake - regular make only appears to work, but doesn't in fact. Use gmake, not make. + +The clang compiler installed through FreeBSD's package manager does not expose all of the C++11 features needed under `std=gnuc++11`. Force the compiler to use `std=c++11` mode instead. + +```sh +export CXXFLAGS=-std=c++11 +``` + +macOS Notes +----------- +PowerDNS Authoritative Server is available through Homebrew: + +``` +brew install pdns +``` + +If you want to compile yourself, the dependencies can be installed using +Homebrew. You need to tell configure where to find OpenSSL, too. + +```sh +brew install boost lua pkg-config ragel openssl +./configure --with-modules="" --with-lua PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig +make -j4 +``` + +Additionally, for PostgreSQL support, run `brew install postgresql` and add `--with-modules="gpgsql"` to `./configure`. +For MySQL support, run `brew install mariadb` and add `--with-modules="gmysql"` to `./configure`. + +Linux notes +----------- +None really. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e26c915 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = ext modules pdns codedocs docs + +EXTRA_DIST = \ + INSTALL \ + NOTICE \ + README \ + COPYING \ + codedocs/doxygen.conf \ + contrib/powerdns.solaris.init.d \ + pdns/named.conf.parsertest \ + regression-tests/zones/unit.test \ + builder-support/gen-version + +ACLOCAL_AMFLAGS = -I m4 + +dvi: # do nothing to build dvi diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..b87c639 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,984 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-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 +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing COPYING INSTALL README \ + build-aux/compile build-aux/config.guess build-aux/config.sub \ + build-aux/install-sh build-aux/ltmain.sh build-aux/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.bz2 +DIST_TARGETS = dist-bzip2 +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = ext modules pdns codedocs docs +EXTRA_DIST = \ + INSTALL \ + NOTICE \ + README \ + COPYING \ + codedocs/doxygen.conf \ + contrib/powerdns.solaris.init.d \ + pdns/named.conf.parsertest \ + regression-tests/zones/unit.test \ + builder-support/gen-version + +ACLOCAL_AMFLAGS = -I m4 +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || 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; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am 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-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +dvi: # do nothing to build dvi + +# 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. +.NOEXPORT: diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..ddd9b42 --- /dev/null +++ b/NOTICE @@ -0,0 +1,16 @@ +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +In addition, for the avoidance of any doubt, permission is granted to +link this program with OpenSSL and to (re)distribute the binaries +produced as the result of such linking. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/README b/README new file mode 100644 index 0000000..74a3b84 --- /dev/null +++ b/README @@ -0,0 +1,219 @@ +PowerDNS is copyright © 2001-2019 by PowerDNS.COM BV and lots of +contributors, using the GNU GPLv2 license (see NOTICE for the +exact license and exception used). + +All documentation can be found on http://doc.powerdns.com/ + +This file may lag behind at times. For most recent updates, always check +https://doc.powerdns.com/md/changelog/. + +Another good place to look for information is: +https://doc.powerdns.com/md/appendix/compiling-powerdns/ + +To file bugs, head towards: +https://github.com/PowerDNS/pdns/issues + +But please check if the issue is already reported there first. + +SOURCE CODE / GIT +----------------- +Source code is available on GitHub: + +```sh +git clone https://github.com/PowerDNS/pdns.git +``` + +This repository contains the sources for the PowerDNS Recursor, the PowerDNS +Authoritative Server, and dnsdist (a powerful DNS loadbalancer). All three can +be built from this repository. However, all three released separately as .tar.bz2, +.deb and .rpm. + +COMPILING Authoritative Server +------------------------------ +The PowerDNS Authoritative Server depends on Boost, OpenSSL and requires a +compiler with C++-2011 support. + +On Debian 9, the following is useful: + +```sh +apt install g++ libboost-all-dev libtool make pkg-config default-libmysqlclient-dev libssl-dev virtualenv +``` + +When building from git, the following packages are also required: + +```sh +apt install autoconf automake ragel bison flex +``` + +For Ubuntu 18.04 (Bionic Beaver), the following packages should be installed: + +```sh +apt install libcurl4-openssl-dev luajit lua-yaml-dev libyaml-cpp-dev libtolua-dev lua5.3 autoconf automake ragel bison flex g++ libboost-all-dev libtool make pkg-config libssl-dev virtualenv lua-yaml-dev libyaml-cpp-dev libluajit-5.1-dev libcurl4 gawk +# For DNSSEC ed25519 (algorithm 15) support with --with-libsodium +apt install libsodium-dev +# If using the gmysql (Generic MySQL) backend +apt install default-libmysqlclient-dev +# If using the gpgsql (Generic PostgreSQL) backend +apt install postgresql-server-dev-10 +# If using --enable-systemd (will create the service scripts so it can be managed with systemctl/service) +apt install libsystemd0 libsystemd-dev +# If using the geoip backend +apt install libmaxminddb-dev libmaxminddb0 libgeoip1 libgeoip-dev +``` + +Then generate the configure file: + +```sh +autoreconf -vi +``` + +To compile a very clean version, use: + +```sh +./configure --with-modules="" --without-lua --disable-lua-records +make +# make install +``` + +This generates a PowerDNS Authoritative Server binary with no modules built in. + +See https://doc.powerdns.com/authoritative/backends/index.html for a list of available modules. + +When `./configure` is run without `--with-modules`, the bind and gmysql module are +built-in by default and the pipe-backend is compiled for runtime loading. + +To add multiple modules, try: + +```sh +./configure --with-modules="bind gmysql gpgsql" +``` + +Note that you will need the development headers for PostgreSQL as well in this case. + +See https://doc.powerdns.com/authoritative/appendices/compiling.html for more details. + +If you run into C++11-related symbol trouble, please try passing `CPPFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0` (or 1) to `./configure` to make sure you are compatible with the installed dependencies. + +Compiling the Recursor +---------------------- +See [README.md](pdns/recursordist/README.md) in `pdns/recursordist/`. + +Compiling dnsdist +----------------- +See [README-dnsdist.md](pdns/README-dnsdist.md) in `pdns/`. + +Building the HTML documentation +------------------------------- + +The HTML documentation (as seen [on the PowerDNS docs site](https://doc.powerdns.com/authoritative/)) is built from ReStructured Text (rst) files located in `docs`. They are compiled into HTML files using [Sphinx](http://www.sphinx-doc.org/en/master/index.html), a documentation generator tool which is built in Python. + +**Using a normal Python installation** + +For those simply contributing to the documentation, this avoids needing to install the various build +tools and other dependencies. + +Install Python 2.7 or Python 3 (preferable) if you don't yet have it installed. On some operating +systems you may also have to install `python3-pip` or similarly named. + +Ubuntu 16.04 / 18.04 + +```sh +apt update +apt install python3 python3-pip python3-venv +``` + +macOS (using homebrew) + +```sh +brew install python3 +``` + +Update your `pip` and install/update `virtualenv` to avoid problems: + +```sh +# for python2, use "pip" instead of "pip3" +pip3 install -U pip +pip3 install -U virtualenv +``` + +Enter the repository's `docs` folder, set up the virtualenv, and install the requirements + +```sh +cd docs +# for python2, use "virtualenv .venv" instead +python3 -m venv .venv +source .venv/bin/activate +# The virtualenv may use an older pip, so upgrade it again +pip3 install -U pip setuptools setuptools-git +# Now you can install the requirements +pip3 install -r requirements.txt +``` + +Finally, you can build the documentation: + +```sh +sphinx-build . html-docs +``` + +Note: If your shell has problems finding sphinx-build, try using `.venv/bin/sphinx-build` instead. + +The HTML documentation is now available in `html-docs`. + +**Using the build tools** + +This method is preferable for those who already have a working build environment for PowerDNS. + +Install the dependencies under "COMPILING", and run autoreconf if you haven't already: + +```sh +autoreconf -vi +``` + +Enter the `docs` folder, and use make to build the HTML docs. + +``` +cd docs +make html-docs +``` + +The HTML documentation will now be available in `html-docs`. + +Solaris Notes +------------- +Use a recent gcc. OpenCSW is a good source, as is Solaris 11 IPS. + +If you encounter problems with the Solaris make, gmake is advised. + +FreeBSD Notes +------------- +You need to compile using gmake - regular make only appears to work, but doesn't in fact. Use gmake, not make. + +The clang compiler installed through FreeBSD's package manager does not expose all of the C++11 features needed under `std=gnuc++11`. Force the compiler to use `std=c++11` mode instead. + +```sh +export CXXFLAGS=-std=c++11 +``` + +macOS Notes +----------- +PowerDNS Authoritative Server is available through Homebrew: + +``` +brew install pdns +``` + +If you want to compile yourself, the dependencies can be installed using +Homebrew. You need to tell configure where to find OpenSSL, too. + +```sh +brew install boost lua pkg-config ragel openssl +./configure --with-modules="" --with-lua PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig +make -j4 +``` + +Additionally, for PostgreSQL support, run `brew install postgresql` and add `--with-modules="gpgsql"` to `./configure`. +For MySQL support, run `brew install mariadb` and add `--with-modules="gmysql"` to `./configure`. + +Linux notes +----------- +None really. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..6ba8786 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1558 @@ +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. + +# This file 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 11 (pkg-config-0.29.1) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + +# Copyright (C) 2002-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file 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. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file 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. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file 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. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# +# This file 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. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2017 Free Software Foundation, Inc. +# +# This file 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2017 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2017 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/ac_pthread_set_name.m4]) +m4_include([m4/ax_arg_default_enable_disable.m4]) +m4_include([m4/ax_cxx_compile_stdcxx_11.m4]) +m4_include([m4/boost.m4]) +m4_include([m4/libcurl.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/pdns_check_bison.m4]) +m4_include([m4/pdns_check_cdb.m4]) +m4_include([m4/pdns_check_clock_gettime.m4]) +m4_include([m4/pdns_check_curl_program.m4]) +m4_include([m4/pdns_check_flex.m4]) +m4_include([m4/pdns_check_ldap.m4]) +m4_include([m4/pdns_check_libcrypto.m4]) +m4_include([m4/pdns_check_libcrypto_ecdsa.m4]) +m4_include([m4/pdns_check_libcrypto_eddsa.m4]) +m4_include([m4/pdns_check_libcurl.m4]) +m4_include([m4/pdns_check_lmdb.m4]) +m4_include([m4/pdns_check_lua_hpp.m4]) +m4_include([m4/pdns_check_network_libs.m4]) +m4_include([m4/pdns_check_opendbx.m4]) +m4_include([m4/pdns_check_os.m4]) +m4_include([m4/pdns_check_ragel.m4]) +m4_include([m4/pdns_check_sqlite3.m4]) +m4_include([m4/pdns_check_virtualenv.m4]) +m4_include([m4/pdns_d_fortify_source.m4]) +m4_include([m4/pdns_enable_backend_unit_tests.m4]) +m4_include([m4/pdns_enable_coverage.m4]) +m4_include([m4/pdns_enable_fuzz_targets.m4]) +m4_include([m4/pdns_enable_gss_tsig.m4]) +m4_include([m4/pdns_enable_ixfrdist.m4]) +m4_include([m4/pdns_enable_kiss.m4]) +m4_include([m4/pdns_enable_malloc_trace.m4]) +m4_include([m4/pdns_enable_p11kit.m4]) +m4_include([m4/pdns_enable_remotebackend_zeromq.m4]) +m4_include([m4/pdns_enable_reproducible.m4]) +m4_include([m4/pdns_enable_sanitizers.m4]) +m4_include([m4/pdns_enable_tools.m4]) +m4_include([m4/pdns_enable_unit_tests.m4]) +m4_include([m4/pdns_enable_verbose_logging.m4]) +m4_include([m4/pdns_from_git.m4]) +m4_include([m4/pdns_param_ssp_buffer_size.m4]) +m4_include([m4/pdns_pie.m4]) +m4_include([m4/pdns_relro.m4]) +m4_include([m4/pdns_stack_protector.m4]) +m4_include([m4/pdns_with_geo.m4]) +m4_include([m4/pdns_with_libdecaf.m4]) +m4_include([m4/pdns_with_libsodium.m4]) +m4_include([m4/pdns_with_lua.m4]) +m4_include([m4/pdns_with_lua_records.m4]) +m4_include([m4/pdns_with_mysql.m4]) +m4_include([m4/pdns_with_oracle.m4]) +m4_include([m4/pdns_with_postgresql.m4]) +m4_include([m4/pdns_with_protobuf.m4]) +m4_include([m4/pdns_with_sqlite3.m4]) +m4_include([m4/pdns_with_unixodbc.m4]) +m4_include([m4/systemd.m4]) +m4_include([m4/tm-gmtoff.m4]) +m4_include([m4/warnings.m4]) diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 0000000..2ab71e4 --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..2193702 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1473 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2017 Free Software Foundation, Inc. + +timestamp='2017-05-27' + +# This file 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = hppa2.0w ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; +esac + +cat >&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.sub b/build-aux/config.sub new file mode 100755 index 0000000..40ea5df --- /dev/null +++ b/build-aux/config.sub @@ -0,0 +1,1836 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2017 Free Software Foundation, Inc. + +timestamp='2017-04-02' + +# This file 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2017 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + wasm32) + basic_machine=wasm32-unknown + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -ios) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + pru-*) + os=-elf + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..b39f98f --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. + +# This program 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 2, or (at your option) +# any later version. + +# This program 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 this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..0360b79 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2016-01-11.22; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 0000000..bb9035a --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,11153 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program 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 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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 this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program 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 of the License, or +# (at your option) any later version. + +# This program 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 this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$lt_sysroot$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + func_stripname '=' '' "$libdir" + libdir=$func_stripname_result + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + func_stripname '=' '' "$libdir" + libdir=$func_stripname_result + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..c6e3795 --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program 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 2, or (at your option) +# any later version. + +# This program 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 this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/test-driver b/build-aux/test-driver new file mode 100755 index 0000000..0218a01 --- /dev/null +++ b/build-aux/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 2011-2017 Free Software Foundation, Inc. +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ylwrap b/build-aux/ylwrap new file mode 100755 index 0000000..d788f2d --- /dev/null +++ b/build-aux/ylwrap @@ -0,0 +1,247 @@ +#! /bin/sh +# ylwrap - wrapper for lex/yacc invocations. + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# +# Written by Tom Tromey . +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +get_dirname () +{ + case $1 in + */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';; + # Otherwise, we want the empty string (not "."). + esac +} + +# guard FILE +# ---------- +# The CPP macro used to guard inclusion of FILE. +guard () +{ + printf '%s\n' "$1" \ + | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ + -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \ + -e 's/__*/_/g' +} + +# quote_for_sed [STRING] +# ---------------------- +# Return STRING (or stdin) quoted to be used as a sed pattern. +quote_for_sed () +{ + case $# in + 0) cat;; + 1) printf '%s\n' "$1";; + esac \ + | sed -e 's|[][\\.*]|\\&|g' +} + +case "$1" in + '') + echo "$0: No files given. Try '$0 --help' for more information." 1>&2 + exit 1 + ;; + --basedir) + basedir=$2 + shift 2 + ;; + -h|--h*) + cat <<\EOF +Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... + +Wrapper for lex/yacc invocations, renaming files as desired. + + INPUT is the input file + OUTPUT is one file PROG generates + DESIRED is the file we actually want instead of OUTPUT + PROGRAM is program to run + ARGS are passed to PROG + +Any number of OUTPUT,DESIRED pairs may be used. + +Report bugs to . +EOF + exit $? + ;; + -v|--v*) + echo "ylwrap $scriptversion" + exit $? + ;; +esac + + +# The input. +input=$1 +shift +# We'll later need for a correct munging of "#line" directives. +input_sub_rx=`get_dirname "$input" | quote_for_sed` +case $input in + [\\/]* | ?:[\\/]*) + # Absolute path; do nothing. + ;; + *) + # Relative path. Make it absolute. + input=`pwd`/$input + ;; +esac +input_rx=`get_dirname "$input" | quote_for_sed` + +# Since DOS filename conventions don't allow two dots, +# the DOS version of Bison writes out y_tab.c instead of y.tab.c +# and y_tab.h instead of y.tab.h. Test to see if this is the case. +y_tab_nodot=false +if test -f y_tab.c || test -f y_tab.h; then + y_tab_nodot=true +fi + +# The parser itself, the first file, is the destination of the .y.c +# rule in the Makefile. +parser=$1 + +# A sed program to s/FROM/TO/g for all the FROM/TO so that, for +# instance, we rename #include "y.tab.h" into #include "parse.h" +# during the conversion from y.tab.c to parse.c. +sed_fix_filenames= + +# Also rename header guards, as Bison 2.7 for instance uses its header +# guard in its implementation file. +sed_fix_header_guards= + +while test $# -ne 0; do + if test x"$1" = x"--"; then + shift + break + fi + from=$1 + # Handle y_tab.c and y_tab.h output by DOS + if $y_tab_nodot; then + case $from in + "y.tab.c") from=y_tab.c;; + "y.tab.h") from=y_tab.h;; + esac + fi + shift + to=$1 + shift + sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;" + sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;" +done + +# The program to run. +prog=$1 +shift +# Make any relative path in $prog absolute. +case $prog in + [\\/]* | ?:[\\/]*) ;; + *[\\/]*) prog=`pwd`/$prog ;; +esac + +dirname=ylwrap$$ +do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret' +trap "ret=129; $do_exit" 1 +trap "ret=130; $do_exit" 2 +trap "ret=141; $do_exit" 13 +trap "ret=143; $do_exit" 15 +mkdir $dirname || exit 1 + +cd $dirname + +case $# in + 0) "$prog" "$input" ;; + *) "$prog" "$@" "$input" ;; +esac +ret=$? + +if test $ret -eq 0; then + for from in * + do + to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"` + if test -f "$from"; then + # If $2 is an absolute path name, then just use that, + # otherwise prepend '../'. + case $to in + [\\/]* | ?:[\\/]*) target=$to;; + *) target=../$to;; + esac + + # Do not overwrite unchanged header files to avoid useless + # recompilations. Always update the parser itself: it is the + # destination of the .y.c rule in the Makefile. Divert the + # output of all other files to a temporary file so we can + # compare them to existing versions. + if test $from != $parser; then + realtarget=$target + target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'` + fi + + # Munge "#line" or "#" directives. Don't let the resulting + # debug information point at an absolute srcdir. Use the real + # output file name, not yy.lex.c for instance. Adjust the + # include guards too. + sed -e "/^#/!b" \ + -e "s|$input_rx|$input_sub_rx|" \ + -e "$sed_fix_filenames" \ + -e "$sed_fix_header_guards" \ + "$from" >"$target" || ret=$? + + # Check whether files must be updated. + if test "$from" != "$parser"; then + if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then + echo "$to is unchanged" + rm -f "$target" + else + echo "updating $to" + mv -f "$target" "$realtarget" + fi + fi + else + # A missing file is only an error for the parser. This is a + # blatant hack to let us support using "yacc -d". If -d is not + # specified, don't fail when the header file is "missing". + if test "$from" = "$parser"; then + ret=1 + fi + fi + done +fi + +# Remove the directory. +cd .. +rm -rf $dirname + +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/builder-support/gen-version b/builder-support/gen-version new file mode 100755 index 0000000..4411794 --- /dev/null +++ b/builder-support/gen-version @@ -0,0 +1,74 @@ +#!/bin/sh +if [ ! -z "${BUILDER_VERSION}" ]; then + printf ${BUILDER_VERSION} + exit 0 +fi + +VERSION="unknown" + +DIRTY="" +git status | grep -q clean || DIRTY='.dirty' + +# Special environment variable to signal that we are building a release, as this +# has consequenses for the version number. +if [ "${IS_RELEASE}" = "YES" ]; then + TAG="$(git describe --tags --exact-match 2> /dev/null | cut -d- -f 2-)" + if [ -n "${TAG}" ]; then + # We're on a tag + echo "${TAG}${DIRTY}" > .version + printf "${TAG}${DIRTY}" + exit 0 + fi + echo 'This is not a tag, either tag this commit or do not set $IS_RELEASE' >&2 + exit 1 +fi + +# +# Generate the version number based on the branch +# +if [ ! -z "$(git rev-parse --abbrev-ref HEAD 2> /dev/null)" ]; then + if [ -n "${BUILDER_MODULES}" ]; then + match=${BUILDER_MODULES} + [ $match = "authoritative" ] && match='auth' + [ $match = "recursor" ] && match='rec' + GIT_VERSION="$(git describe --match=${match}-* --tags | cut -d- -f2-)" + if [ $(echo ${GIT_VERSION} | awk -F"-" '{print NF-1}') = '3' ]; then + # A prerelease happened before + LAST_TAG="$(echo ${GIT_VERSION} | cut -d- -f1-2)" + COMMITS_SINCE_TAG="$(echo ${GIT_VERSION} | cut -d- -f3)" + GIT_HASH="$(echo ${GIT_VERSION} | cut -d- -f4)" + else + LAST_TAG="$(echo ${GIT_VERSION} | cut -d- -f1)" + COMMITS_SINCE_TAG="$(echo ${GIT_VERSION} | cut -d- -f2)" + GIT_HASH="$(echo ${GIT_VERSION} | cut -d- -f3)" + fi + fi + + if [ -z "${GIT_VERSION}" ]; then + # BUILDER_SUPPORT has more than one product listed, fall back to the 0.0.0 logic + + # We used 0.0.XXXXgHASH for master in the previous incarnation of our build pipeline. + # This now becomes 0.0.XXXX.0.gHASH, as 0.0.0.XXXX.gHASH (which is more correct) + # would break upgrades for those running master + # This _should_ be ok for forever is we stick to X.Y.Z for version numbers + LAST_TAG=0.0 + COMMITS_SINCE_TAG="$(git rev-list --count 12c868770afc20b6cc0da439d881105151d557dd..HEAD 2> /dev/null).0" + [ "${COMMITS_SINCE_TAG}" = ".0" ] && COMMITS_SINCE_TAG=0.0 + GIT_HASH="g$(git rev-parse HEAD | cut -c1-10 2> /dev/null)" + fi + + BRANCH=".$(git rev-parse --abbrev-ref HEAD | perl -p -e 's/[^[:alnum:]]//g;')" + + TAG="$(git describe --tags --exact-match 2> /dev/null | cut -d- -f 2-)" + if [ -n "${TAG}" ]; then # We're exactly on a tag + COMMITS_SINCE_TAG="0" + GIT_HASH="g$(git show --no-patch --format=format:%h HEAD 2>/dev/null)" + if [ -z "$GIT_HASH" ]; then + GIT_HASH="g$(git show --format=format:%h HEAD | head -n1)" + fi + fi + + VERSION="${LAST_TAG}.${COMMITS_SINCE_TAG}${BRANCH}.${GIT_HASH}${DIRTY}" +fi + +printf $VERSION diff --git a/codedocs/Makefile.am b/codedocs/Makefile.am new file mode 100644 index 0000000..398a6eb --- /dev/null +++ b/codedocs/Makefile.am @@ -0,0 +1,2 @@ +codedocs: . + doxygen doxygen.conf diff --git a/codedocs/Makefile.in b/codedocs/Makefile.in new file mode 100644 index 0000000..76673a1 --- /dev/null +++ b/codedocs/Makefile.in @@ -0,0 +1,594 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = codedocs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign codedocs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign codedocs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + +codedocs: . + doxygen doxygen.conf + +# 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. +.NOEXPORT: diff --git a/codedocs/doxygen.conf b/codedocs/doxygen.conf new file mode 100644 index 0000000..4e76baa --- /dev/null +++ b/codedocs/doxygen.conf @@ -0,0 +1,1213 @@ +# Doxyfile 1.4.0 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = ahudns + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.cc \ + *.hh + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../ + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = *.hh + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..37a376f --- /dev/null +++ b/config.h.in @@ -0,0 +1,390 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Set to the user and host that builds PowerDNS */ +#undef BUILD_HOST + +/* Define to 1 if you want to enable GSS-TSIG support */ +#undef ENABLE_GSS_TSIG + +/* Define to 1 if you have the `accept4' function. */ +#undef HAVE_ACCEPT4 + +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + +/* Defined if the requested minimum BOOST version is satisfied */ +#undef HAVE_BOOST + +/* Define to 1 if you have */ +#undef HAVE_BOOST_ARCHIVE_TEXT_OARCHIVE_HPP + +/* Define to 1 if you have boost >= 1.48 */ +#undef HAVE_BOOST_GE_148 + +/* Defined if the Boost program_options library is available */ +#undef HAVE_BOOST_PROGRAM_OPTIONS + +/* Define to 1 if you have */ +#undef HAVE_BOOST_PROGRAM_OPTIONS_HPP + +/* Defined if the Boost serialization library is available */ +#undef HAVE_BOOST_SERIALIZATION + +/* Define to 1 if you have */ +#undef HAVE_BOOST_TEST_UNIT_TEST_HPP + +/* Defined if the Boost unit_test_framework library is available */ +#undef HAVE_BOOST_UNIT_TEST_FRAMEWORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_CDB_H + +/* Define to 1 if you have clock_gettime */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `crypto_box_curve25519xchacha20poly1305_easy' + function. */ +#undef HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_EASY + +/* Define to 1 if you have the `crypto_box_easy_afternm' function. */ +#undef HAVE_CRYPTO_BOX_EASY_AFTERNM + +/* define if the compiler supports basic C++11 syntax */ +#undef HAVE_CXX11 + +/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you + don't. */ +#undef HAVE_DECL_NID_ED25519 + +/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you + don't. */ +#undef HAVE_DECL_NID_ED448 + +/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you + don't. */ +#undef HAVE_DECL_NID_SECP384R1 + +/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 + if you don't. */ +#undef HAVE_DECL_NID_X9_62_PRIME256V1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if ASAN fiber annotation interface is available. */ +#undef HAVE_FIBER_SANITIZER + +/* Define this if you have GeoIP */ +#undef HAVE_GEOIP + +/* Define to 1 if you have the `getrandom' function. */ +#undef HAVE_GETRANDOM + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 to enable unsafe rng KISS */ +#undef HAVE_KISS_RNG + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_default_flags' + function. */ +#undef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS + +/* Define to 1 if you have the header file. */ +#undef HAVE_KRB5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have ldap_initialize */ +#undef HAVE_LDAP_INITIALIZE + +/* Define to 1 if you have ldap_sasl_bind */ +#undef HAVE_LDAP_SASL_BIND + +/* Define to 1 if you have OpenSSL libcrypto */ +#undef HAVE_LIBCRYPTO + +/* define to 1 if OpenSSL ecdsa support is available. */ +#undef HAVE_LIBCRYPTO_ECDSA + +/* define to 1 if OpenSSL ed25519 support is available. */ +#undef HAVE_LIBCRYPTO_ED25519 + +/* define to 1 if OpenSSL ed448 support is available. */ +#undef HAVE_LIBCRYPTO_ED448 + +/* define to 1 if OpenSSL EDDSA support is available. */ +#undef HAVE_LIBCRYPTO_EDDSA + +/* Define to 1 if you have a functional curl library. */ +#undef HAVE_LIBCURL + +/* Define to 1 if you have libdecaf */ +#undef HAVE_LIBDECAF + +/* Have -lldap */ +#undef HAVE_LIBLDAP + +/* Have -lldap_r */ +#undef HAVE_LIBLDAP_R + +/* Define to 1 if you have libsodium */ +#undef HAVE_LIBSODIUM + +/* Define to 1 if you have libzmq */ +#undef HAVE_LIBZMQ + +/* Define to 1 if you have the header file. */ +#undef HAVE_LMDB_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have lua */ +#undef HAVE_LUA + +/* Define if enabling LUA records. */ +#undef HAVE_LUA_RECORDS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have mmap */ +#undef HAVE_MMAP + +/* Define this if you have Maxmind DB */ +#undef HAVE_MMDB + +/* Define to 1 if you have the header file. */ +#undef HAVE_ODBX_H + +/* Define to 1 if you have p11-kit-1 */ +#undef HAVE_P11KIT1 + +/* Define to 1 if you have 0.20 or newer P11-kit */ +#undef HAVE_P11KIT1_V2 + +/* Define if using protobuf. */ +#undef HAVE_PROTOBUF + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_NP_H + +/* 1-arg pthread_setname_np */ +#undef HAVE_PTHREAD_SETNAME_NP_1 + +/* 2-arg pthread_setname_np */ +#undef HAVE_PTHREAD_SETNAME_NP_2 + +/* 3-arg pthread_setname_np */ +#undef HAVE_PTHREAD_SETNAME_NP_3 + +/* 2-arg pthread_set_name_np */ +#undef HAVE_PTHREAD_SET_NAME_NP_2 + +/* 2-arg void pthread_set_name_np */ +#undef HAVE_PTHREAD_SET_NAME_NP_2_VOID + +/* Define to 1 if you have the `randombytes_stir' function. */ +#undef HAVE_RANDOMBYTES_STIR + +/* Define to 1 if you have the `RAND_bytes' function. */ +#undef HAVE_RAND_BYTES + +/* Define to 1 if you have the `RAND_pseudo_bytes' function. */ +#undef HAVE_RAND_PSEUDO_BYTES + +/* Define to 1 if you have the `recvmmsg' function. */ +#undef HAVE_RECVMMSG + +/* Define to 1 if you have the header + file. */ +#undef HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H + +/* Define to 1 if __sanitizer_finish_switch_fiber takes only a pointer */ +#undef HAVE_SANITIZER_FINISH_SWITCH_FIBER_SINGLE_PTR + +/* Define to 1 if __sanitizer_finish_switch_fiber takes three pointers */ +#undef HAVE_SANITIZER_FINISH_SWITCH_FIBER_THREE_PTRS + +/* Define to 1 if you have the `sched_setscheduler' function. */ +#undef HAVE_SCHED_SETSCHEDULER + +/* Define to 1 if you have the `sendmmsg' function. */ +#undef HAVE_SENDMMSG + +/* Define to 1 if you have sqlite3 */ +#undef HAVE_SQLITE3 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasestr' function. */ +#undef HAVE_STRCASESTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Systemd available and enabled */ +#undef HAVE_SYSTEMD + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* tm_gmtoff is available. */ +#undef HAVE_TM_GMTOFF + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the ZeroMQ 3.x or greater API is available */ +#undef HAVE_ZMQ_MSG_SEND + +/* Defined if libcurl supports AsynchDNS */ +#undef LIBCURL_FEATURE_ASYNCHDNS + +/* Defined if libcurl supports IDN */ +#undef LIBCURL_FEATURE_IDN + +/* Defined if libcurl supports IPv6 */ +#undef LIBCURL_FEATURE_IPV6 + +/* Defined if libcurl supports KRB4 */ +#undef LIBCURL_FEATURE_KRB4 + +/* Defined if libcurl supports libz */ +#undef LIBCURL_FEATURE_LIBZ + +/* Defined if libcurl supports NTLM */ +#undef LIBCURL_FEATURE_NTLM + +/* Defined if libcurl supports SSL */ +#undef LIBCURL_FEATURE_SSL + +/* Defined if libcurl supports SSPI */ +#undef LIBCURL_FEATURE_SSPI + +/* Defined if libcurl supports DICT */ +#undef LIBCURL_PROTOCOL_DICT + +/* Defined if libcurl supports FILE */ +#undef LIBCURL_PROTOCOL_FILE + +/* Defined if libcurl supports FTP */ +#undef LIBCURL_PROTOCOL_FTP + +/* Defined if libcurl supports FTPS */ +#undef LIBCURL_PROTOCOL_FTPS + +/* Defined if libcurl supports HTTP */ +#undef LIBCURL_PROTOCOL_HTTP + +/* Defined if libcurl supports HTTPS */ +#undef LIBCURL_PROTOCOL_HTTPS + +/* Defined if libcurl supports IMAP */ +#undef LIBCURL_PROTOCOL_IMAP + +/* Defined if libcurl supports LDAP */ +#undef LIBCURL_PROTOCOL_LDAP + +/* Defined if libcurl supports POP3 */ +#undef LIBCURL_PROTOCOL_POP3 + +/* Defined if libcurl supports RTSP */ +#undef LIBCURL_PROTOCOL_RTSP + +/* Defined if libcurl supports SMTP */ +#undef LIBCURL_PROTOCOL_SMTP + +/* Defined if libcurl supports TELNET */ +#undef LIBCURL_PROTOCOL_TELNET + +/* Defined if libcurl supports TFTP */ +#undef LIBCURL_PROTOCOL_TFTP + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to 1 if you want to benefit from malloc trace */ +#undef MALLOC_TRACE + +/* If your OS is so broken that it needs an additional prototype */ +#undef NEED_INET_NTOP_PROTO + +/* If POSIX typedefs need to be defined */ +#undef NEED_POSIX_TYPEDEF + +/* Name of package */ +#undef PACKAGE + +/* Set to the package version used for secpoll */ +#undef PACKAGEVERSION + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* pdns configure arguments */ +#undef PDNS_CONFIG_ARGS + +/* Built-in modules */ +#undef PDNS_MODULES + +/* Define to 1 if you have the ZeroMQ connector */ +#undef REMOTEBACKEND_ZEROMQ + +/* Define to 1 for reproducible builds */ +#undef REPRODUCIBLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define to 1 if verbose logging is enabled */ +#undef VERBOSELOG + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Define _GNU_SOURCE so that we get all necessary prototypes */ +#undef _GNU_SOURCE + +/* Define curl_free() as free() if our version of curl lacks curl_free. */ +#undef curl_free diff --git a/configure b/configure new file mode 100755 index 0000000..2ca0033 --- /dev/null +++ b/configure @@ -0,0 +1,29621 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for pdns 4.2.1. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='pdns' +PACKAGE_TARNAME='pdns' +PACKAGE_VERSION='4.2.1' +PACKAGE_STRING='pdns 4.2.1' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="pdns/receiver.cc" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_func_list= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +PACKAGEVERSION +IPCRYPT_LIBS +IPCRYPT_CFLAGS +YAHTTP_LIBS +YAHTTP_CFLAGS +AM_CPPFLAGS +MALLOC_TRACE_FALSE +MALLOC_TRACE_TRUE +WARN_CFLAGS +SANITIZER_FLAGS +PROGRAM_LDFLAGS +HAVE_SYSTEMD_FALSE +HAVE_SYSTEMD_TRUE +HAVE_SYSTEMD_SYSTEM_CALL_FILTER_FALSE +HAVE_SYSTEMD_SYSTEM_CALL_FILTER_TRUE +HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_FALSE +HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_TRUE +HAVE_SYSTEMD_RESTRICT_REALTIME_FALSE +HAVE_SYSTEMD_RESTRICT_REALTIME_TRUE +HAVE_SYSTEMD_RESTRICT_NAMESPACES_FALSE +HAVE_SYSTEMD_RESTRICT_NAMESPACES_TRUE +HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_FALSE +HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_TRUE +HAVE_SYSTEMD_REMOVE_IPC_FALSE +HAVE_SYSTEMD_REMOVE_IPC_TRUE +HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_FALSE +HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_TRUE +HAVE_SYSTEMD_PROTECT_SYSTEM_FALSE +HAVE_SYSTEMD_PROTECT_SYSTEM_TRUE +HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_FALSE +HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_TRUE +HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_FALSE +HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_TRUE +HAVE_SYSTEMD_PROTECT_HOME_FALSE +HAVE_SYSTEMD_PROTECT_HOME_TRUE +HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_FALSE +HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_TRUE +HAVE_SYSTEMD_PRIVATE_USERS_FALSE +HAVE_SYSTEMD_PRIVATE_USERS_TRUE +HAVE_SYSTEMD_PRIVATE_TMP_FALSE +HAVE_SYSTEMD_PRIVATE_TMP_TRUE +HAVE_SYSTEMD_PRIVATE_DEVICES_FALSE +HAVE_SYSTEMD_PRIVATE_DEVICES_TRUE +HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_FALSE +HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_TRUE +HAVE_SYSTEMD_LOCK_PERSONALITY_FALSE +HAVE_SYSTEMD_LOCK_PERSONALITY_TRUE +HAVE_SYSTEMD_DYNAMIC_USER_FALSE +HAVE_SYSTEMD_DYNAMIC_USER_TRUE +SYSTEMCTL +SYSTEMD_LIBS +SYSTEMD_CFLAGS +SYSTEMD_MODULES_LOAD +SYSTEMD_DIR +systemd +SQLITE3_FALSE +SQLITE3_TRUE +SQLITE3_LIBS +SQLITE3_CFLAGS +LDAP_FALSE +LDAP_TRUE +ORACLE_FALSE +ORACLE_TRUE +HAVE_LUA_RECORDS_FALSE +HAVE_LUA_RECORDS_TRUE +HAVE_PROTOC_FALSE +HAVE_PROTOC_TRUE +HAVE_PROTOBUF_FALSE +HAVE_PROTOBUF_TRUE +PROTOC +PROTOBUF_LIBS +PROTOBUF_CFLAGS +IXFRDIST_FALSE +IXFRDIST_TRUE +TOOLS_FALSE +TOOLS_TRUE +HAVE_LIBCURL_FALSE +HAVE_LIBCURL_TRUE +LIBCURL +LIBCURL_CPPFLAGS +_libcurl_config +LIBZMQ_LIBS +LIBZMQ_CFLAGS +REMOTEBACKEND_ZEROMQ +REMOTEBACKEND_ZEROMQ_FALSE +REMOTEBACKEND_ZEROMQ_TRUE +BOOST_SERIALIZATION_LIBS +BOOST_SERIALIZATION_LDPATH +BOOST_SERIALIZATION_LDFLAGS +LMDB_LIBS +LMDB_CFLAGS +YAML_LIBS +YAML_CFLAGS +MMDB_LIBS +MMDB_CFLAGS +GEOIP_LIBS +GEOIP_CFLAGS +CDB_LIBS +CDB_CFLAGS +CURL +OPENDBX_LIBS +OPENDBX_CFLAGS +KRB5_LIBS +LDAP_LIBS +PG_CONFIG +PGSQL_LIBS +PGSQL_CFLAGS +MYSQL_CFLAGS +MYSQL_LIBS +MYSQL_config +UNIXODBC_LIBS +UNIXODBC_CFLAGS +UNIXODBC_config +ORACLE_LIBS +ORACLE_CFLAGS +modulelibs +moduleobjects +moduledirs +socketdir +GSS_LIBS +GSS_CFLAGS +GSS_TSIG +GSS_TSIG_FALSE +GSS_TSIG_TRUE +P11KIT1_LIBS +P11KIT1_CFLAGS +PKCS11_FALSE +PKCS11_TRUE +LIBDL +HAVE_RECVMMSG_FALSE +HAVE_RECVMMSG_TRUE +FROM_GIT_FALSE +FROM_GIT_TRUE +HAVE_MANPAGES_FALSE +HAVE_MANPAGES_TRUE +HAVE_VIRTUALENV_FALSE +HAVE_VIRTUALENV_TRUE +VIRTUALENV +FUZZ_TARGETS_FALSE +FUZZ_TARGETS_TRUE +BACKEND_UNIT_TESTS_FALSE +BACKEND_UNIT_TESTS_TRUE +BOOST_UNIT_TEST_FRAMEWORK_LIBS +BOOST_UNIT_TEST_FRAMEWORK_LDPATH +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS +UNIT_TESTS_FALSE +UNIT_TESTS_TRUE +BOOST_PROGRAM_OPTIONS_LIBS +BOOST_LDPATH +BOOST_PROGRAM_OPTIONS_LDPATH +BOOST_PROGRAM_OPTIONS_LDFLAGS +HAVE_BOOST_GE_148_FALSE +HAVE_BOOST_GE_148_TRUE +BOOST_CPPFLAGS +DISTCHECK_CONFIGURE_FLAGS +BOOST_ROOT +RT_LIBS +RAGEL +HAVE_LIBCRYPTO_FALSE +HAVE_LIBCRYPTO_TRUE +LIBCRYPTO_LDFLAGS +LIBCRYPTO_LIBS +LIBCRYPTO_INCLUDES +LIBDECAF_LIBS +LIBDECAF_FALSE +LIBDECAF_TRUE +LIBSODIUM_FALSE +LIBSODIUM_TRUE +LIBSODIUM_LIBS +LIBSODIUM_CFLAGS +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +RELRO_LDFLAGS +PIE_LDFLAGS +PIE_CFLAGS +HAVE_CXX11 +HAVE_LUA_HPP_FALSE +HAVE_LUA_HPP_TRUE +CXXCPP +LUA_FALSE +LUA_TRUE +LUA_LIBS +LUA_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +DYNLINKFLAGS +THREADFLAGS +HAVE_SOLARIS_FALSE +HAVE_SOLARIS_TRUE +HAVE_LINUX_FALSE +HAVE_LINUX_TRUE +HAVE_FREEBSD_FALSE +HAVE_FREEBSD_TRUE +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +LEXLIB +LEX_OUTPUT_ROOT +LEX +EGREP +GREP +YFLAGS +YACC +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +pdns_configure_args +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +with_lua +enable_hardening +enable_unsafe_rng_kiss +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +with_libsodium +with_libdecaf +with_libcrypto +with_boost +enable_static_boost +enable_unit_tests +enable_backend_unit_tests +enable_reproducible +enable_fuzz_targets +with_sqlite3 +enable_verbose_logging +enable_experimental_pkcs11 +enable_experimental_gss_tsig +with_socketdir +with_modules +with_dynmodules +with_oracle_includes +with_oracle_libs +with_unixodbc +with_odbc_config +with_unixodbc_lib +with_unixodbc_includes +with_mysql +with_mysql_config +with_mysql_lib +with_mysql_includes +with_pg_config +with_maxminddb_incdir +with_maxminddb_libdir +with_lmdb +enable_remotebackend_zeromq +with_libcurl +enable_tools +enable_ixfrdist +with_protobuf +enable_lua_records +enable_systemd +with_systemd +enable_coverage +enable_asan +enable_msan +enable_tsan +enable_lsan +enable_ubsan +enable_malloc_trace +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +YACC +YFLAGS +CXX +CXXFLAGS +CCC +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +LUA_CFLAGS +LUA_LIBS +CXXCPP +LT_SYS_LIBRARY_PATH +LIBSODIUM_CFLAGS +LIBSODIUM_LIBS +BOOST_ROOT +P11KIT1_CFLAGS +P11KIT1_LIBS +GSS_CFLAGS +GSS_LIBS +PGSQL_CFLAGS +PGSQL_LIBS +LDAP_LIBS +KRB5_LIBS +OPENDBX_CFLAGS +OPENDBX_LIBS +CDB_CFLAGS +CDB_LIBS +GEOIP_CFLAGS +GEOIP_LIBS +MMDB_CFLAGS +MMDB_LIBS +YAML_CFLAGS +YAML_LIBS +LMDB_CFLAGS +LMDB_LIBS +LIBZMQ_CFLAGS +LIBZMQ_LIBS +PROTOBUF_CFLAGS +PROTOBUF_LIBS +SQLITE3_CFLAGS +SQLITE3_LIBS +SYSTEMD_CFLAGS +SYSTEMD_LIBS +PACKAGEVERSION' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures pdns 4.2.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/pdns] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of pdns 4.2.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-hardening disable compiler security checks [default=no] + --enable-unsafe-rng-kiss + Enable unsafe rng KISS + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-static-boost Prefer the static boost libraries over the shared + ones [no] + --enable-unit-tests enable unit test building [default=no] + --enable-backend-unit-tests + enable backend unit test building [default=no] + --enable-reproducible Create reproducible builds. Use this only if you are + a distribution maintainer and need reproducible + builds. If you compile PowerDNS yourself, leave this + disabled, as it might make debugging harder. + [default=no] + --enable-fuzz-targets enable fuzz targets [default=no] + --enable-verbose-logging + enable verbose logging [default=no] + --enable-experimental-pkcs11 + enable experimental PKCS11 support [default=no] + --enable-experimental-gss-tsig + enable experimental GSS-TSIG support [default=no] + --enable-remotebackend-zeromq + enable ZeroMQ connector for remotebackend + [default=no] + --enable-tools if we should build and install the tools + [default=no] + --enable-ixfrdist if we should build and install ixfrdist [default=no] + + --disable-lua-records disable LUA records support [default=no] + --enable-systemd Enable systemd support (default is DISABLED, but + will be enabled when libraries are found) + --enable-coverage enable code coverage [default=no] + --enable-asan enable AddressSanitizer [default=no] + --enable-msan enable MemorySanitizer [default=no] + --enable-tsan enable ThreadSanitizer [default=no] + --enable-lsan enable LeakSanitizer [default=no] + --enable-ubsan enable Undefined Behaviour Sanitizer [default=no] + --enable-malloc-trace enable malloc-trace [default=no] + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-lua select Lua implementation [default=auto] + + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-libsodium use libsodium [default=auto] + --with-libdecaf use libdecaf [default=no] + --with-libcrypto=DIR root of the OpenSSL directory + --with-boost=DIR prefix of Boost 1.42 [guess] + --with-sqlite3 include sqlite3 driver [default=no] + --with-socketdir where the controlsocket lives [default=/var/run] + --with-modules which backends to compile with [default=bind gmysql + random] + --with-dynmodules which backends to build for dynamic loading + [default=pipe] + --with-oracle-includes= + instantclient sdk include dir + --with-oracle-libs= + instantclient oracle library dir + --with-unixodbc= root directory path of unixODBC installation + --with-odbc-config= + file path to odbc_config + --with-unixodbc-lib= + directory path of unixODBC library installation + --with-unixodbc-includes= + directory path of unixODBC header installation + --with-mysql= root directory path of MySQL installation + --with-mysql-config= + file path to mysql_config + --with-mysql-lib= directory path of MySQL library installation + --with-mysql-includes= + directory path of MySQL header installation + --with-pg-config= path to pg_config + + --with-maxminddb-includedir + path to maxminddb include directory [default=auto] + --with-maxminddb-libdir path to maxminddb library directory [default=auto] + --with-lmdb lmdb library to use [default=auto] + --with-libcurl=PREFIX look for the curl library in PREFIX/lib and headers + in PREFIX/include + --with-protobuf enable protobuf support [default=auto] + --with-systemd set directory for systemd service files + --with-systemd-modules-load set directory for systemd modules load files + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + CXX C++ compiler command + CXXFLAGS C++ compiler flags + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + LUA_CFLAGS C compiler flags for LUA, overriding pkg-config + LUA_LIBS linker flags for LUA, overriding pkg-config + CXXCPP C++ preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + LIBSODIUM_CFLAGS + C compiler flags for LIBSODIUM, overriding pkg-config + LIBSODIUM_LIBS + linker flags for LIBSODIUM, overriding pkg-config + BOOST_ROOT Location of Boost installation + P11KIT1_CFLAGS + C compiler flags for P11KIT1, overriding pkg-config + P11KIT1_LIBS + linker flags for P11KIT1, overriding pkg-config + GSS_CFLAGS C compiler flags for GSS, overriding pkg-config + GSS_LIBS linker flags for GSS, overriding pkg-config + PGSQL_CFLAGS + C compiler flags for PGSQL, overriding pkg-config + PGSQL_LIBS linker flags for PGSQL, overriding pkg-config + LDAP_LIBS linker flags for openldap + KRB5_LIBS linker flag to add Kerberos 5 libraries + OPENDBX_CFLAGS + C compiler flags for OPENDBX, overriding pkg-config + OPENDBX_LIBS + linker flags for OPENDBX, overriding pkg-config + CDB_CFLAGS C compiler flags for CDB, overriding pkg-config + CDB_LIBS linker flags for CDB, overriding pkg-config + GEOIP_CFLAGS + C compiler flags for GEOIP, overriding pkg-config + GEOIP_LIBS linker flags for GEOIP, overriding pkg-config + MMDB_CFLAGS C compiler flags for MMDB, overriding pkg-config + MMDB_LIBS linker flags for MMDB, overriding pkg-config + YAML_CFLAGS C compiler flags for YAML, overriding pkg-config + YAML_LIBS linker flags for YAML, overriding pkg-config + LMDB_CFLAGS C compiler flags for LMDB, overriding pkg-config + LMDB_LIBS linker flags for LMDB, overriding pkg-config + LIBZMQ_CFLAGS + C compiler flags for LIBZMQ, overriding pkg-config + LIBZMQ_LIBS linker flags for LIBZMQ, overriding pkg-config + PROTOBUF_CFLAGS + C compiler flags for PROTOBUF, overriding pkg-config + PROTOBUF_LIBS + linker flags for PROTOBUF, overriding pkg-config + SQLITE3_CFLAGS + C compiler flags for SQLITE3, overriding pkg-config + SQLITE3_LIBS + linker flags for SQLITE3, overriding pkg-config + SYSTEMD_CFLAGS + C compiler flags for SYSTEMD, overriding pkg-config + SYSTEMD_LIBS + linker flags for SYSTEMD, overriding pkg-config + PACKAGEVERSION + The version used in secpoll queries + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +pdns configure 4.2.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_func + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_check_decl LINENO SYMBOL VAR INCLUDES +# ----------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_cxx_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_decl +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by pdns $as_me 4.2.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +as_fn_append ac_func_list " strcasestr" +as_fn_append ac_func_list " localtime_r" +as_fn_append ac_func_list " recvmmsg" +as_fn_append ac_func_list " sched_setscheduler" +as_fn_append ac_func_list " getrandom" +as_fn_append ac_func_list " arc4random" +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +ac_config_headers="$ac_config_headers config.h" + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +pdns_configure_args="$ac_configure_args" + + +cat >>confdefs.h <<_ACEOF +#define PDNS_CONFIG_ARGS "$pdns_configure_args" +_ACEOF + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='pdns' + VERSION='4.2.1' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Add some default CFLAGS and CXXFLAGS, can be appended to using the environment variables +CFLAGS="-Wall -g -O2 $CFLAGS" +CXXFLAGS="-Wall -g -O2 $CXXFLAGS" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bison is the parser generator" >&5 +$as_echo_n "checking if bison is the parser generator... " >&6; } +if ${pdns_cv_prog_bison+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if $YACC --version 2>/dev/null | $EGREP -q '^bison '; then : + pdns_cv_prog_bison=yes +else + pdns_cv_prog_bison=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pdns_cv_prog_bison" >&5 +$as_echo "$pdns_cv_prog_bison" >&6; } + + if test "x$pdns_cv_prog_bison" = "xno"; then : + + if test ! -f "${srcdir}/pdns/bindparser.cc"; then : + as_fn_error $? "bison is missing and you don't have ${srcdir}/pdns/bindparser.cc. Please install bison" "$LINENO" 5 + +fi + +fi + + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 +$as_echo "$LEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ + yyless ((input () != 0)); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ { ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 +$as_echo_n "checking lex output file root... " >&6; } +if ${ac_cv_prog_lex_root+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 +$as_echo "$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 +$as_echo_n "checking lex library... " >&6; } +if ${ac_cv_lib_lex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lex=$ac_lib +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 +$as_echo "$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 +$as_echo_n "checking whether yytext is a pointer... " >&6; } +if ${ac_cv_prog_lex_yytext_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_prog_lex_yytext_pointer=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 +$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the lexer is flex" >&5 +$as_echo_n "checking if the lexer is flex... " >&6; } +if ${pdns_cv_prog_flex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if $LEX --version 2>/dev/null | $EGREP -q '^flex '; then : + pdns_cv_prog_flex=yes +else + pdns_cv_prog_flex=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pdns_cv_prog_flex" >&5 +$as_echo "$pdns_cv_prog_flex" >&6; } + + if test "x$pdns_cv_prog_flex" = "xno"; then : + + if test ! -f "${srcdir}/pdns/bindlexer.c"; then : + as_fn_error $? "flex is missing and you don't have ${srcdir}/pdns/bindlexer.c. Please install flex" "$LINENO" 5 + +fi + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +if test "x$CXX" = "xno" || test "x$CXX:x$GXX" = "xg++:x"; then : + as_fn_error $? "no C++ compiler found" "$LINENO" 5 + +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +$as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + +# Warn when pkg.m4 is missing + + + + + THREADFLAGS="" + + case "$host_os" in + solaris2.1*) + LIBS="-lposix4 -lpthread $LIBS" + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + have_solaris="yes" + ;; + solaris2.8 | solaris2.9 ) + +$as_echo "#define NEED_POSIX_TYPEDEF /**/" >>confdefs.h + + +$as_echo "#define NEED_INET_NTOP_PROTO /**/" >>confdefs.h + + LIBS="-lposix4 -lpthread $LIBS" + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + have_solaris="yes" + ;; + linux*) + THREADFLAGS="-pthread" + have_linux="yes" + ;; + darwin*) + CXXFLAGS="-D__APPLE_USE_RFC_3542 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + freebsd*) + THREADFLAGS="-pthread" + have_freebsd="yes" + ;; + *) + LDFLAGS="-pthread $LDFLAGS" + CXXFLAGS="-pthread $CXXFLAGS" + ;; + esac + + if test "x$have_freebsd" = "xyes"; then + HAVE_FREEBSD_TRUE= + HAVE_FREEBSD_FALSE='#' +else + HAVE_FREEBSD_TRUE='#' + HAVE_FREEBSD_FALSE= +fi + + if test "x$have_linux" = "xyes"; then + HAVE_LINUX_TRUE= + HAVE_LINUX_FALSE='#' +else + HAVE_LINUX_TRUE='#' + HAVE_LINUX_FALSE= +fi + + if test "x$have_solaris" = "xyes"; then + HAVE_SOLARIS_TRUE= + HAVE_SOLARIS_FALSE='#' +else + HAVE_SOLARIS_TRUE='#' + HAVE_SOLARIS_FALSE= +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -latomic is needed for __atomic builtins" >&5 +$as_echo_n "checking whether -latomic is needed for __atomic builtins... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + LIBS="$LIBS -latomic" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "libatomic needed, but linking with -latomic failed, cannot continue +See \`config.log' for more details" "$LINENO" 5; } + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + + DYNLINKFLAGS=-export-dynamic + + + + stored_LIBS="$LIBS" + LIBS="-lpthread" + # pthread setname (4 non-portable variants...) + for ac_header in pthread_np.h +do : + ac_fn_cxx_check_header_compile "$LINENO" "pthread_np.h" "ac_cv_header_pthread_np_h" "#include +" +if test "x$ac_cv_header_pthread_np_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_NP_H 1 +_ACEOF + +fi + +done + + + # 2-arg setname (e.g. Linux/glibc, QNX, IBM) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 2-arg pthread_setname_np" >&5 +$as_echo_n "checking for 2-arg pthread_setname_np... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + +int +main () +{ + + pthread_setname_np(pthread_self(), "foo") + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_PTHREAD_SETNAME_NP_2 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + # 2-arg set_name (e.g. FreeBSD, OpenBSD) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 2-arg pthread_set_name_np" >&5 +$as_echo_n "checking for 2-arg pthread_set_name_np... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + +int +main () +{ + + return pthread_set_name_np(pthread_self(), "foo"); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_PTHREAD_SET_NAME_NP_2 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + # 2-arg void set_name (e.g. FreeBSD, OpenBSD) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 2-arg void pthread_set_name_np" >&5 +$as_echo_n "checking for 2-arg void pthread_set_name_np... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + +int +main () +{ + + pthread_set_name_np(pthread_self(), "foo"); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_PTHREAD_SET_NAME_NP_2_VOID 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + # 1-arg setname (e.g. Darwin) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 1-arg pthread_setname_np" >&5 +$as_echo_n "checking for 1-arg pthread_setname_np... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + +int +main () +{ + + return pthread_setname_np("foo"); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_PTHREAD_SETNAME_NP_1 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + # 3-arg setname (e.g. NetBSD) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 3-arg pthread_setname_np" >&5 +$as_echo_n "checking for 3-arg pthread_setname_np... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + +int +main () +{ + + return pthread_setname_np(pthread_self(), "foo", NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_PTHREAD_SETNAME_NP_3 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$stored_LIBS + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which Lua implementation to use" >&5 +$as_echo_n "checking which Lua implementation to use... " >&6; } + +# Check whether --with-lua was given. +if test "${with_lua+set}" = set; then : + withval=$with_lua; + with_lua=$withval + +else + + with_lua=auto + +fi + + + if test "x$with_lua" = "xyes"; then : + + with_lua=auto + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_lua" >&5 +$as_echo "$with_lua" >&6; } + + if test "x$with_lua" = "xno" -a "" = "mandatory"; then : + + as_fn_error $? "--without-lua specified, but Lua is not optional" "$LINENO" 5 + +fi + + LUAPC="" + luajit_min_version='2.0.2' + lua_min_version='5.1' + + if test "x$with_lua" != "xno"; then : + + if test "x$with_lua" != "xauto"; then : + + with_lua_version=${lua_min_version} + if echo "x$with_lua" | ${GREP} 'jit' >/dev/null 2>&1; then : + with_lua_version=${luajit_min_version} +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$with_lua >= \$with_lua_version\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$with_lua >= $with_lua_version") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "$with_lua >= $with_lua_version" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$with_lua >= \$with_lua_version\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$with_lua >= $with_lua_version") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "$with_lua >= $with_lua_version" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$with_lua >= $with_lua_version" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$with_lua >= $with_lua_version" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + + as_fn_error $? "Selected Lua ($with_lua) not found" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + as_fn_error $? "Selected Lua ($with_lua) not found" "$LINENO" 5 + +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + LUAPC=$with_lua + +fi + +else + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"luajit >= \${luajit_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "luajit >= ${luajit_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "luajit >= ${luajit_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"luajit >= \${luajit_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "luajit >= ${luajit_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "luajit >= ${luajit_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "luajit >= ${luajit_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "luajit >= ${luajit_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + LUAPC=luajit + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + +fi + if test -z "$LUAPC"; then : + + found_lua=n + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.3 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.3 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua5.3 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.3 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.3 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua5.3 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua5.3 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua5.3 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua5.3 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.3 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.3 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua-5.3 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.3 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.3 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua-5.3 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua-5.3 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua-5.3 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua-5.3 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua53 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua53 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua53 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua53 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua53 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua53 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua53 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua53 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua53 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.2 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.2 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua5.2 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.2 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.2 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua5.2 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua5.2 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua5.2 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua5.2 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.2 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.2 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua-5.2 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.2 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.2 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua-5.2 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua-5.2 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua-5.2 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua-5.2 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua52 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua52 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua52 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua52 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua52 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua52 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua52 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua52 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua52 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.1 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua5.1 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.1 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua5.1 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua5.1 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua5.1 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua5.1 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.1 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.1 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua-5.1 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua-5.1 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua-5.1 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua-5.1 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua-5.1 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua-5.1 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua-5.1 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua51 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua51 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua51 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua51 >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua51 >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua51 >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua51 >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua51 >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua51 + +fi + +fi + + if test "$found_lua" != "y"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua >= \${lua_min_version}\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua >= ${lua_min_version}") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua >= ${lua_min_version}" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua >= ${lua_min_version}" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua >= ${lua_min_version}" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LUA 1" >>confdefs.h + + found_lua=y + LUAPC=lua + +fi + +fi + + +fi + +fi + +fi + + if test -z "$LUAPC" -a "" = "mandatory"; then : + + as_fn_error $? "No Lua not found, but is mandatory" "$LINENO" 5 + +fi + + if test -n "x$LUAPC"; then + LUA_TRUE= + LUA_FALSE='#' +else + LUA_TRUE='#' + LUA_FALSE= +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + if test "x$LUAPC" != "x" ; then : + + OLD_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LUA_CFLAGS" + ac_fn_cxx_check_header_mongrel "$LINENO" "lua.hpp" "ac_cv_header_lua_hpp" "$ac_includes_default" +if test "x$ac_cv_header_lua_hpp" = xyes; then : + have_lua_hpp=y +fi + + + CPPFLAGS="$OLD_CPPFLAGS" + +fi + if test x"$have_lua_hpp" = "xy" ; then + HAVE_LUA_HPP_TRUE= + HAVE_LUA_HPP_FALSE='#' +else + HAVE_LUA_HPP_TRUE='#' + HAVE_LUA_HPP_FALSE= +fi + + + + ax_cxx_compile_cxx11_required=true + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + ac_success=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } +if ${ax_cv_cxx_compile_cxx11+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + struct Base { + virtual void f() {} + }; + struct Child : public Base { + virtual void f() override {} + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + auto l = [](){}; + // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] + struct use_l { use_l() { l(); } }; + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this + namespace test_template_alias_sfinae { + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { + func(0); + } + } + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_cxx_compile_cxx11=yes +else + ax_cv_cxx_compile_cxx11=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 +$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } +if eval \${$cachevar+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + struct Base { + virtual void f() {} + }; + struct Child : public Base { + virtual void f() override {} + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + auto l = [](){}; + // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] + struct use_l { use_l() { l(); } }; + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this + namespace test_template_alias_sfinae { + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { + func(0); + } + } + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$ac_save_CXXFLAGS" +fi +eval ac_res=\$$cachevar + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi + + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } +if eval \${$cachevar+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + struct Base { + virtual void f() {} + }; + struct Child : public Base { + virtual void f() override {} + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + auto l = [](){}; + // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] + struct use_l { use_l() { l(); } }; + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this + namespace test_template_alias_sfinae { + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { + func(0); + } + } + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$ac_save_CXXFLAGS" +fi +eval ac_res=\$$cachevar + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 +$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + else + HAVE_CXX11=1 + +$as_echo "#define HAVE_CXX11 1" >>confdefs.h + + fi + + + fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will enable compiler security checks" >&5 +$as_echo_n "checking whether we will enable compiler security checks... " >&6; } +# Check whether --enable-hardening was given. +if test "${enable_hardening+set}" = set; then : + enableval=$enable_hardening; enable_hardening=$enableval +else + enable_hardening=yes + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_hardening" >&5 +$as_echo "$enable_hardening" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -Werror -Wunknown-warning-option" >&5 +$as_echo_n "checking whether C++ compiler handles -Werror -Wunknown-warning-option... " >&6; } +if ${gl_cv_warn_cxx__Werror__Wunknown_warning_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -Werror -Wunknown-warning-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__Werror__Wunknown_warning_option=yes +else + gl_cv_warn_cxx__Werror__Wunknown_warning_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__Werror__Wunknown_warning_option" >&5 +$as_echo "$gl_cv_warn_cxx__Werror__Wunknown_warning_option" >&6; } +if test "x$gl_cv_warn_cxx__Werror__Wunknown_warning_option" = xyes; then : + gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror' +else + gl_unknown_warnings_are_errors= +fi + +if test "x$enable_hardening" != "xno"; then : + + + + PIE_CFLAGS= + PIE_LDFLAGS= + OLD_CXXFLAGS=$CXXFLAGS + case "$host" in + *-*-mingw* | *-*-msvc* | *-*-cygwin* ) + ;; *) + CXXFLAGS="-fPIE -DPIE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -pie" >&5 +$as_echo_n "checking whether C++ compiler handles -pie... " >&6; } +if ${gl_cv_warn_cxx__pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +__thread unsigned int t_id; + +int +main () +{ +t_id = 1; + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__pie=yes +else + gl_cv_warn_cxx__pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__pie" >&5 +$as_echo "$gl_cv_warn_cxx__pie" >&6; } +if test "x$gl_cv_warn_cxx__pie" = xyes; then : + + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-pie" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -Wl,-pie" >&5 +$as_echo_n "checking whether C++ compiler handles -Wl,-pie... " >&6; } +if ${gl_cv_warn_cxx__Wl__pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -Wl,-pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +__thread unsigned int t_id; + +int +main () +{ +t_id = 1; + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__Wl__pie=yes +else + gl_cv_warn_cxx__Wl__pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__Wl__pie" >&5 +$as_echo "$gl_cv_warn_cxx__Wl__pie" >&6; } +if test "x$gl_cv_warn_cxx__Wl__pie" = xyes; then : + + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-Wl,-pie" + +fi + + +fi + + esac + CXXFLAGS=$OLD_CXXFLAGS + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fstack-protector" >&5 +$as_echo_n "checking whether C++ compiler handles -fstack-protector... " >&6; } +if ${gl_cv_warn_cxx__fstack_protector+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fstack-protector" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fstack_protector=yes +else + gl_cv_warn_cxx__fstack_protector=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fstack_protector" >&5 +$as_echo "$gl_cv_warn_cxx__fstack_protector" >&6; } +if test "x$gl_cv_warn_cxx__fstack_protector" = xyes; then : + + CFLAGS="-fstack-protector $CFLAGS" + CXXFLAGS="-fstack-protector $CXXFLAGS" + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles --param ssp-buffer-size=4" >&5 +$as_echo_n "checking whether C++ compiler handles --param ssp-buffer-size=4... " >&6; } +if ${gl_cv_warn_cxx___param_ssp_buffer_size_4+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors --param ssp-buffer-size=4" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx___param_ssp_buffer_size_4=yes +else + gl_cv_warn_cxx___param_ssp_buffer_size_4=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx___param_ssp_buffer_size_4" >&5 +$as_echo "$gl_cv_warn_cxx___param_ssp_buffer_size_4" >&6; } +if test "x$gl_cv_warn_cxx___param_ssp_buffer_size_4" = xyes; then : + + CFLAGS="--param ssp-buffer-size=4 $CFLAGS" + CXXFLAGS="--param ssp-buffer-size=4 $CXXFLAGS" + +fi + + + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="-Wall -W -Werror $CXXFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -D_FORTIFY_SOURCE=2" >&5 +$as_echo_n "checking whether C++ compiler handles -D_FORTIFY_SOURCE=2... " >&6; } +if ${gl_cv_warn_cxx__D_FORTIFY_SOURCE_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -D_FORTIFY_SOURCE=2" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__D_FORTIFY_SOURCE_2=yes +else + gl_cv_warn_cxx__D_FORTIFY_SOURCE_2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__D_FORTIFY_SOURCE_2" >&5 +$as_echo "$gl_cv_warn_cxx__D_FORTIFY_SOURCE_2" >&6; } +if test "x$gl_cv_warn_cxx__D_FORTIFY_SOURCE_2" = xyes; then : + + CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" + CXXFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $OLD_CXXFLAGS" + +else + CXXFLAGS="$OLD_CXXFLAGS" +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for how to force completely read-only GOT table" >&5 +$as_echo_n "checking for how to force completely read-only GOT table... " >&6; } + + RELRO_LDFLAGS= + ld_help=`$CXX -Wl,-help 2>&1` + case $ld_help in + *"-z relro"*) RELRO_LDFLAGS="-Wl,-z -Wl,relro" ;; + esac + case $ld_help in + *"-z now"*) RELRO_LDFLAGS="$RELRO_LDFLAGS -Wl,-z -Wl,now" ;; + esac + + if test "x$RELRO_LDFLAGS" != "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RELRO_LDFLAGS" >&5 +$as_echo "$RELRO_LDFLAGS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 +$as_echo "unknown" >&6; } + +fi + + +fi + + + # Check whether --enable-unsafe-rng-kiss was given. +if test "${enable_unsafe_rng_kiss+set}" = set; then : + enableval=$enable_unsafe_rng_kiss; + +$as_echo "#define HAVE_KISS_RNG 1" >>confdefs.h + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_aton" >&5 +$as_echo_n "checking for library containing inet_aton... " >&6; } +if ${ac_cv_search_inet_aton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_aton (); +int +main () +{ +return inet_aton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' resolv; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_inet_aton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_aton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_aton+:} false; then : + +else + ac_cv_search_inet_aton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_aton" >&5 +$as_echo "$ac_cv_search_inet_aton" >&6; } +ac_res=$ac_cv_search_inet_aton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : + +else + ac_cv_search_gethostbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostent" >&5 +$as_echo_n "checking for library containing gethostent... " >&6; } +if ${ac_cv_search_gethostent+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostent (); +int +main () +{ +return gethostent (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_gethostent=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostent+:} false; then : + break +fi +done +if ${ac_cv_search_gethostent+:} false; then : + +else + ac_cv_search_gethostent=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostent" >&5 +$as_echo "$ac_cv_search_gethostent" >&6; } +ac_res=$ac_cv_search_gethostent +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + for ac_func in recvmmsg sendmmsg accept4 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + +func_stripname_cnf () +{ + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; + esac +} # func_stripname_cnf + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + +enable_dlopen=yes + + + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +CC=$lt_save_CC + + if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct_CXX=no + hardcode_direct_absolute_CXX=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec_CXX='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + no_undefined_flag_CXX='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' $wl-bernotok' + allow_undefined_flag_CXX=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='$wl--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + if test yes != "$lt_cv_apple_cc_single_mod"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + os2*) + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_minus_L_CXX=yes + allow_undefined_flag_CXX=unsupported + shrext_cmds=.dll + archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes_CXX=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='$wl-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='$wl-E' + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + no_undefined_flag_CXX=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='$wl-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='$wl-z,text' + allow_undefined_flag_CXX='$wl-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test no = "$ld_shlibs_CXX" && can_build_shared=no + + GCC_CXX=$GXX + LD_CXX=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX=$prev$p + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX=$prev$p + else + postdeps_CXX="${postdeps_CXX} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX=$p + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX=$p + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + lt_prog_compiler_pic_CXX='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static_CXX='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test no = "$ld_shlibs_CXX" && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec_CXX='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test yes = "$hardcode_automatic_CXX"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct_CXX" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && + test no != "$hardcode_minus_L_CXX"; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test relink = "$hardcode_action_CXX" || + test yes = "$inherit_rpath_CXX"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tm_gmtoff in struct tm" >&5 +$as_echo_n "checking for tm_gmtoff in struct tm... " >&6; } +if ${ac_cv_struct_tm_gmtoff+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_cv_struct_tm> +int +main () +{ +struct tm tm; tm.tm_gmtoff; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_struct_tm_gmtoff=yes +else + ac_cv_struct_tm_gmtoff=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm_gmtoff" >&5 +$as_echo "$ac_cv_struct_tm_gmtoff" >&6; } +if test "$ac_cv_struct_tm_gmtoff" = yes; then + +$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h + +fi + + +# Define full_libdir to be the fully expanded (${exec_prefix}, etc.) +# "system" library path. +# We use this to search for other libraries. +eval full_libdir="\"$libdir\"" + +# detect pkg-config explicitly + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +for ac_header in sys/mman.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MMAN_H 1 +_ACEOF + ac_fn_cxx_check_func "$LINENO" "mmap" "ac_cv_func_mmap" +if test "x$ac_cv_func_mmap" = xyes; then : + +$as_echo "#define HAVE_MMAP 1" >>confdefs.h + +else + have_mmap=no + +fi + +else + have_mmap=no + +fi + +done + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will be linking in libsodium" >&5 +$as_echo_n "checking whether we will be linking in libsodium... " >&6; } + +# Check whether --with-libsodium was given. +if test "${with_libsodium+set}" = set; then : + withval=$with_libsodium; with_libsodium=$withval +else + with_libsodium=auto +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libsodium" >&5 +$as_echo "$with_libsodium" >&6; } + + if test "x$with_libsodium" != "xno"; then : + + if test "x$with_libsodium" = "xyes" -o "x$with_libsodium" = "xauto"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSODIUM" >&5 +$as_echo_n "checking for LIBSODIUM... " >&6; } + +if test -n "$LIBSODIUM_CFLAGS"; then + pkg_cv_LIBSODIUM_CFLAGS="$LIBSODIUM_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsodium\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsodium") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSODIUM_CFLAGS=`$PKG_CONFIG --cflags "libsodium" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBSODIUM_LIBS"; then + pkg_cv_LIBSODIUM_LIBS="$LIBSODIUM_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsodium\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libsodium") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSODIUM_LIBS=`$PKG_CONFIG --libs "libsodium" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsodium" 2>&1` + else + LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsodium" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBSODIUM_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + LIBSODIUM_CFLAGS=$pkg_cv_LIBSODIUM_CFLAGS + LIBSODIUM_LIBS=$pkg_cv_LIBSODIUM_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LIBSODIUM 1" >>confdefs.h + + save_CFLAGS=$CFLAGS + save_LIBS=$LIBS + CFLAGS="$LIBSODIUM_CFLAGS $CFLAGS" + LIBS="$LIBSODIUM_LIBS $LIBS" + for ac_func in crypto_box_easy_afternm crypto_box_curve25519xchacha20poly1305_easy randombytes_stir +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + CFLAGS=$save_CFLAGS + LIBS=$save_LIBS + +fi + +fi + +fi + if test "x$LIBSODIUM_LIBS" != "x"; then + LIBSODIUM_TRUE= + LIBSODIUM_FALSE='#' +else + LIBSODIUM_TRUE='#' + LIBSODIUM_FALSE= +fi + + if test "x$with_libsodium" = "xyes"; then : + + if test x"$LIBSODIUM_LIBS" = "x"; then : + + as_fn_error $? "libsodium requested but libraries were not found" "$LINENO" 5 + +fi + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will be linking in libdecaf" >&5 +$as_echo_n "checking whether we will be linking in libdecaf... " >&6; } + +# Check whether --with-libdecaf was given. +if test "${with_libdecaf+set}" = set; then : + withval=$with_libdecaf; with_libdecaf=$withval +else + with_libdecaf=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libdecaf" >&5 +$as_echo "$with_libdecaf" >&6; } + + if test "x$with_libdecaf" != "xno"; then + LIBDECAF_TRUE= + LIBDECAF_FALSE='#' +else + LIBDECAF_TRUE='#' + LIBDECAF_FALSE= +fi + + + if test "x$with_libdecaf" != "xno"; then : + + save_LIBS=$LIBS + LIBS="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing decaf_ed25519_sign" >&5 +$as_echo_n "checking for library containing decaf_ed25519_sign... " >&6; } +if ${ac_cv_search_decaf_ed25519_sign+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char decaf_ed25519_sign (); +int +main () +{ +return decaf_ed25519_sign (); + ; + return 0; +} +_ACEOF +for ac_lib in '' decaf; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_decaf_ed25519_sign=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_decaf_ed25519_sign+:} false; then : + break +fi +done +if ${ac_cv_search_decaf_ed25519_sign+:} false; then : + +else + ac_cv_search_decaf_ed25519_sign=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_decaf_ed25519_sign" >&5 +$as_echo "$ac_cv_search_decaf_ed25519_sign" >&6; } +ac_res=$ac_cv_search_decaf_ed25519_sign +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +$as_echo "#define HAVE_LIBDECAF 1" >>confdefs.h + + LIBDECAF_LIBS="$LIBS" + + +else + + as_fn_error $? "Could not find libdecaf" "$LINENO" 5 + +fi + + LIBS="$save_LIBS" + +fi + + + found=false + +# Check whether --with-libcrypto was given. +if test "${with_libcrypto+set}" = set; then : + withval=$with_libcrypto; + case "$withval" in + "" | y | ye | yes | n | no) + as_fn_error $? "Invalid --with-libcrypto value" "$LINENO" 5 + ;; + *) ssldirs="$withval" + ;; + esac + +else + + # if pkg-config is installed and openssl has installed a .pc file, + # then use that information and don't search ssldirs + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PKG_CONFIG"; then + ac_cv_prog_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PKG_CONFIG="${ac_tool_prefix}pkg-config" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PKG_CONFIG=$ac_cv_prog_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_PKG_CONFIG"; then + ac_ct_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_PKG_CONFIG"; then + ac_cv_prog_ac_ct_PKG_CONFIG="$ac_ct_PKG_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_PKG_CONFIG="pkg-config" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_PKG_CONFIG=$ac_cv_prog_ac_ct_PKG_CONFIG +if test -n "$ac_ct_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PKG_CONFIG" >&5 +$as_echo "$ac_ct_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_ct_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_prog_PKG_CONFIG" +fi + + if test x"$PKG_CONFIG" != x""; then + LIBCRYPTO_LDFLAGS=`$PKG_CONFIG libcrypto --libs-only-L 2>/dev/null` + if test $? = 0; then + LIBCRYPTO_LIBS=`$PKG_CONFIG libcrypto --libs-only-l 2>/dev/null` + LIBCRYPTO_INCLUDES=`$PKG_CONFIG libcrypto --cflags-only-I 2>/dev/null` + ssldir=`$PKG_CONFIG libcrypto --variable=prefix 2>/dev/null` + found=true + fi + fi + + # no such luck; use some default ssldirs + if ! $found; then + ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" + fi + + +fi + + + + # note that we #include , so the OpenSSL headers have to be in + # an 'openssl' subdirectory + + if ! $found; then + LIBCRYPTO_INCLUDES= + for ssldir in $ssldirs; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/crypto.h in $ssldir" >&5 +$as_echo_n "checking for openssl/crypto.h in $ssldir... " >&6; } + if test -f "$ssldir/include/openssl/crypto.h"; then + LIBCRYPTO_INCLUDES="-I$ssldir/include" + LIBCRYPTO_LDFLAGS="-L$ssldir/lib" + LIBCRYPTO_LIBS="-lcrypto" + found=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + break + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + done + + # if the file wasn't found, well, go ahead and try the link anyway -- maybe + # it will just work! + fi + + if $found; then + +$as_echo "#define HAVE_LIBCRYPTO 1" >>confdefs.h + + fi + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL's libcrypto works" >&5 +$as_echo_n "checking whether compiling and linking against OpenSSL's libcrypto works... " >&6; } + echo "Trying link with LIBCRYPTO_LDFLAGS=$LIBCRYPTO_LDFLAGS;" \ + "LIBCRYPTO_LIBS=$LIBCRYPTO_LIBS; LIBCRYPTO_INCLUDES=$LIBCRYPTO_INCLUDES" >&5 + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS $LIBCRYPTO_LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +ERR_load_CRYPTO_strings() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + for ac_func in RAND_bytes RAND_pseudo_bytes +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + as_fn_error $? "OpenSSL/libcrypto not found" "$LINENO" 5 + + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + + + + if test "x$LIBCRYPTO_LIBS" != "x"; then + HAVE_LIBCRYPTO_TRUE= + HAVE_LIBCRYPTO_FALSE='#' +else + HAVE_LIBCRYPTO_TRUE='#' + HAVE_LIBCRYPTO_FALSE= +fi + + + + + + # Set the environment correctly for a possibly non-default OpenSSL path that was found by/supplied to PDNS_CHECK_LIBCRYPTO + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + LDFLAGS="$LIBCRYPTO_LDFLAGS $LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + + # Find the headers we need for ECDSA + libcrypto_ecdsa=yes + as_ac_Header=`$as_echo "ac_cv_header_$ssldir/include/openssl/ecdsa.h" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ssldir/include/openssl/ecdsa.h" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + + ac_fn_cxx_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default +#include <$ssldir/include/openssl/evp.h> + +" +if test "x$ac_cv_have_decl_NID_X9_62_prime256v1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_X9_62_PRIME256V1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + : +else + + libcrypto_ecdsa=no + +fi +ac_fn_cxx_check_decl "$LINENO" "NID_secp384r1" "ac_cv_have_decl_NID_secp384r1" "$ac_includes_default +#include <$ssldir/include/openssl/evp.h> + +" +if test "x$ac_cv_have_decl_NID_secp384r1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_SECP384R1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + : +else + + libcrypto_ecdsa=no + +fi + + +else + + libcrypto_ecdsa=no + +fi + + + + if test "x$libcrypto_ecdsa" = "xyes"; then : + + +$as_echo "#define HAVE_LIBCRYPTO_ECDSA 1" >>confdefs.h + + +fi + + # Restore variables + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + + + + # Set the environment correctly for a possibly non-default OpenSSL path that was found by/supplied to PDNS_CHECK_LIBCRYPTO + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + LDFLAGS="$LIBCRYPTO_LDFLAGS $LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + + libcrypto_ed25519=no + libcrypto_ed448=no + ac_fn_cxx_check_decl "$LINENO" "NID_ED25519" "ac_cv_have_decl_NID_ED25519" "$ac_includes_default + #include <$ssldir/include/openssl/evp.h> +" +if test "x$ac_cv_have_decl_NID_ED25519" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_ED25519 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + + libcrypto_ed25519=yes + +$as_echo "#define HAVE_LIBCRYPTO_ED25519 1" >>confdefs.h + + +else + : +fi + + ac_fn_cxx_check_decl "$LINENO" "NID_ED448" "ac_cv_have_decl_NID_ED448" "$ac_includes_default + #include <$ssldir/include/openssl/evp.h> +" +if test "x$ac_cv_have_decl_NID_ED448" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_ED448 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + + libcrypto_ed448=yes + +$as_echo "#define HAVE_LIBCRYPTO_ED448 1" >>confdefs.h + + +else + : +fi + + + if test "$libcrypto_ed25519" = "yes" -o "$libcrypto_ed448" = "yes"; then : + + +$as_echo "#define HAVE_LIBCRYPTO_EDDSA 1" >>confdefs.h + + +else + : +fi + + # Restore variables + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + + + # Extract the first word of "ragel", so it can be a program name with args. +set dummy ragel; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RAGEL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RAGEL"; then + ac_cv_prog_RAGEL="$RAGEL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RAGEL="ragel" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RAGEL=$ac_cv_prog_RAGEL +if test -n "$RAGEL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RAGEL" >&5 +$as_echo "$RAGEL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$RAGEL" = "x"; then + if test ! -f "${srcdir}/pdns/dnslabeltext.cc"; then + as_fn_error $? "ragel is missing and you don't have ${srcdir}/pdns/dnslabeltext.cc. Install ragel or download sources from www.powerdns.com" "$LINENO" 5 + fi + fi + + + OLD_LIBS="$LIBS"; LIBS="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h + +fi + + RT_LIBS=$LIBS + + LIBS="$OLD_LIBS" + + +echo "$as_me: this is boost.m4 serial 30" >&5 +boost_save_IFS=$IFS +boost_version_req=1.42 +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$1" '*' 100000 + "$2" '*' 100 + "$3"` +boost_version_req_string=$1.$2.$3 + +# Check whether --with-boost was given. +if test "${with_boost+set}" = set; then : + withval=$with_boost; +fi +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT" >&5 +$as_echo "$as_me: Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT" >&6;} + with_boost=$BOOST_ROOT + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost" >&5 +$as_echo "$as_me: Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost" >&6;} + fi +fi +DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'" +boost_save_CPPFLAGS=$CPPFLAGS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boost headers version >= $boost_version_req_string" >&5 +$as_echo_n "checking for Boost headers version >= $boost_version_req_string... " >&6; } +if ${boost_cv_inc_path+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_inc_path=no +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # + # Any ${boost_dir}/boost-x_xx directories are searched in reverse version + # order followed by ${boost_dir}. The final '.' is a sentinel for + # searching $boost_dir" itself. Entries are whitespace separated. + # + # I didn't indent this loop on purpose (to avoid over-indented code) + boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ + && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ + && echo .` + for boost_inc in $boost_layout_system_search_list + do + if test x"$boost_inc" != x.; then + boost_inc="$boost_dir/$boost_inc" + else + boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list + fi + if test x"$boost_inc" != x; then + # We are going to check whether the version of Boost installed + # in $boost_inc is usable by running a compilation that + # #includes it. But if we pass a -I/some/path in which Boost + # is not installed, the compiler will just skip this -I and + # use other locations (either from CPPFLAGS, or from its list + # of system include directories). As a result we would use + # header installed on the machine instead of the /some/path + # specified by the user. So in that precise case (trying + # $boost_inc), make sure the version.hpp exists. + # + # Use test -e as there can be symlinks. + test -e "$boost_inc/boost/version.hpp" || continue + CPPFLAGS="$CPPFLAGS -I$boost_inc" + fi + if ac_fn_cxx_try_compile "$LINENO"; then : + boost_cv_inc_path=yes +else + boost_cv_version=no +fi +rm -f core conftest.err conftest.$ac_objext + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_inc_path" >&5 +$as_echo "$boost_cv_inc_path" >&6; } + case $boost_cv_inc_path in #( + no) + boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" + as_fn_error $? "$boost_errmsg" "$LINENO" 5 + + ;;#( + yes) + BOOST_CPPFLAGS= + ;;#( + *) + BOOST_CPPFLAGS="-I$boost_cv_inc_path" + ;; + esac + if test x"$boost_cv_inc_path" != xno; then + +$as_echo "#define HAVE_BOOST 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Boost's header version" >&5 +$as_echo_n "checking for Boost's header version... " >&6; } +if ${boost_cv_lib_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +boost-lib-version = BOOST_LIB_VERSION +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + grep -v '#' | + grep -v '^[[:space:]]*$' | + tr -d '\r' | + tr -s '\n' ' ' | + $SED -n -e "/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}" >conftest.i 2>&1; then : + boost_cv_lib_version=`cat conftest.i` +fi +rm -rf conftest* +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_version" >&5 +$as_echo "$boost_cv_lib_version" >&6; } + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[!0-9]*) + as_fn_error $? "invalid value: boost_major_version='$boost_major_version'" "$LINENO" 5 + ;; + esac +fi +CPPFLAGS=$boost_save_CPPFLAGS + +# Boost accumulators, as used by dnsbulktest and dnstcpbench, need 1.48+ +# to be compatible with C++11 + if test "$boost_major_version" -ge 148; then + HAVE_BOOST_GE_148_TRUE= + HAVE_BOOST_GE_148_FALSE='#' +else + HAVE_BOOST_GE_148_TRUE='#' + HAVE_BOOST_GE_148_FALSE= +fi + +if test "$boost_major_version" -ge 148; then : + + +$as_echo "#define HAVE_BOOST_GE_148 1" >>confdefs.h + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the toolset name used by Boost for $CXX" >&5 +$as_echo_n "checking for the toolset name used by Boost for $CXX... " >&6; } +if ${boost_cv_lib_tag+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_lib_tag=unknown +if test x$boost_cv_inc_path != xno; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + for i in \ + "defined __clang__ && __clang_major__ == 8 && __clang_minor__ == 0 @ clang80" \ + "defined __clang__ && __clang_major__ == 7 && __clang_minor__ == 0 @ clang70" \ + "defined __clang__ && __clang_major__ == 6 && __clang_minor__ == 0 @ clang60" \ + "defined __clang__ && __clang_major__ == 5 && __clang_minor__ == 0 @ clang50" \ + "defined __clang__ && __clang_major__ == 4 && __clang_minor__ == 0 @ clang40" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 9 @ clang39" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 @ clang38" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 7 @ clang37" \ + "defined __GNUC__ && __GNUC__ == 9 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw91" \ + "defined __GNUC__ && __GNUC__ == 9 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc91" \ + "defined __GNUC__ && __GNUC__ == 9 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw90" \ + "defined __GNUC__ && __GNUC__ == 9 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc90" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 3 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw83" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc83" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw82" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc82" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw81" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc81" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw80" \ + "defined __GNUC__ && __GNUC__ == 8 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc80" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 3 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw73" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc73" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw72" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc72" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw71" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc71" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw70" \ + "defined __GNUC__ && __GNUC__ == 7 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc70" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 4 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw64" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 4 && !defined __ICC @ gcc64" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 3 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw63" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc63" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw62" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc62" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw61" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc61" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw60" \ + "defined __GNUC__ && __GNUC__ == 6 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc60" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 5 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw55" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 5 && !defined __ICC @ gcc55" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 4 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw54" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 4 && !defined __ICC @ gcc54" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 3 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw53" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc53" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw52" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc52" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw51" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc51" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw50" \ + "defined __GNUC__ && __GNUC__ == 5 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc50" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 10 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw410" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 10 && !defined __ICC @ gcc410" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 9 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw49" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 9 && !defined __ICC @ gcc49" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 8 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw48" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 8 && !defined __ICC @ gcc48" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 7 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw47" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 7 && !defined __ICC @ gcc47" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 6 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw46" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 6 && !defined __ICC @ gcc46" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 5 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw45" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 5 && !defined __ICC @ gcc45" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 4 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw44" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 4 && !defined __ICC @ gcc44" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw43" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc43" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw42" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc42" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 1 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw41" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc41" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw40" \ + "defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc40" \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + "defined __GNUC__ && __GNUC__ == 3 && __GNUC_MINOR__ == 4 && !defined __ICC @ gcc34" \ + "defined __GNUC__ && __GNUC__ == 3 && __GNUC_MINOR__ == 3 && !defined __ICC @ gcc33" \ + "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ + "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ + "defined __GNUC__ && __GNUC__ == 3 && __GNUC_MINOR__ == 2 && !defined __ICC @ gcc32" \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + "defined __GNUC__ && __GNUC__ == 3 && __GNUC_MINOR__ == 1 && !defined __ICC @ gcc31" \ + "defined __GNUC__ && __GNUC__ == 3 && __GNUC_MINOR__ == 0 && !defined __ICC @ gcc30" \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined ) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + "defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ == 95 && !defined __ICC @ gcc295" \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([^@]*\) @ '` + boost_tag=`expr "X$i" : 'X[^@]* @ \(.*\)'` + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + boost_cv_lib_tag=$boost_tag; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + boost_tag_x= + case $host_os in #( + darwin*) + if test $boost_major_version -ge 136; then + # The `x' added in r46793 of Boost. + boost_tag_x=x + fi;; + esac + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" + ;; #( + unknown) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not figure out which toolset name to use for $CXX" >&5 +$as_echo "$as_me: WARNING: could not figure out which toolset name to use for $CXX" >&2;} + boost_cv_lib_tag= + ;; + esac +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_tag" >&5 +$as_echo "$boost_cv_lib_tag" >&6; } +# Check whether --enable-static-boost was given. +if test "${enable_static_boost+set}" = set; then : + enableval=$enable_static_boost; enable_static_boost=yes +else + enable_static_boost=no +fi + +# Check whether we do better use `mt' even though we weren't ask to. +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + boost_guess_use_mt=: +else + boost_guess_use_mt=false +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +if test x"$boost_cv_inc_path" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost program_options library" >&5 +$as_echo "$as_me: Boost not available, not searching for the Boost program_options library" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test x"" = "xno"; then : + not_found_header='true' +fi +if test x"$boost_cv_inc_path" = xno; then + $not_found_header +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_mongrel "$LINENO" "boost/program_options.hpp" "ac_cv_header_boost_program_options_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_program_options_hpp" = xyes; then : + +$as_echo "#define HAVE_BOOST_PROGRAM_OPTIONS_HPP 1" >>confdefs.h + +else + $not_found_header +fi + + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Boost program_options library" >&5 +$as_echo_n "checking for the Boost program_options library... " >&6; } +if ${boost_cv_lib_program_options+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_lib_program_options=no + case "mt" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "Xmt" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=mt;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[sgpn]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + as_fn_error $? "the libext variable is empty, did you invoke Libtool?" "$LINENO" 5 + boost_save_ac_objext=$ac_objext + # Generate the test file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +boost::program_options::options_description d("test"); + ; + return 0; +} +_ACEOF + if ac_fn_cxx_try_compile "$LINENO"; then : + ac_objext=do_not_rm_me_plz +else + if test x"" != x"no"; then : + + as_fn_error $? "cannot compile a test that uses Boost program_options" "$LINENO" 5 + +fi + +fi +rm -f core conftest.err conftest.$ac_objext + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in program_options; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_full_suffix in \ + $boost_last_suffix \ + x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_mt_$boost_ver_ \ + x$boost_tag_$boost_ver_ + do + boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` + boost_lib="boost_$boost_lib_$boost_real_suffix" + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + boost_cv_lib_program_options_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$boost_cv_lib_program_options_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + boost_cv_lib_program_options_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$boost_cv_lib_program_options_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_cv_lib_program_options=yes +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_cv_lib_program_options=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$boost_cv_lib_program_options" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + if ${boost_cv_rpath_link_ldflag+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_cv_lib_program_options_LIBS $boost_save_LIBS" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_rpath_link_ldflag_found=yes + break +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_rpath_link_ldflag_found=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + done + ;; + esac + if test "x$boost_rpath_link_ldflag_found" != "xyes"; then : + as_fn_error $? "Unable to determine whether to use -R or -rpath" "$LINENO" 5 +fi + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + +fi + + test x"$boost_ldpath" != x && + boost_cv_lib_program_options_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + boost_cv_lib_program_options_LDPATH="$boost_ldpath" + boost_last_suffix="$boost_full_suffix" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_program_options" >&5 +$as_echo "$boost_cv_lib_program_options" >&6; } +case $boost_cv_lib_program_options in #( + (yes) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +$as_echo "#define HAVE_BOOST_PROGRAM_OPTIONS 1" >>confdefs.h + BOOST_PROGRAM_OPTIONS_LDFLAGS=$boost_cv_lib_program_options_LDFLAGS + BOOST_PROGRAM_OPTIONS_LDPATH=$boost_cv_lib_program_options_LDPATH + BOOST_LDPATH=$boost_cv_lib_program_options_LDPATH + BOOST_PROGRAM_OPTIONS_LIBS=$boost_cv_lib_program_options_LIBS + ;; + (no) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + if test x"" != "xno"; then : + + as_fn_error $? "cannot find flags to link with the Boost program_options library (libboost-program_options)" "$LINENO" 5 + +fi + ;; +esac +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + + + +if test "$boost_cv_lib_program_options" = "no"; then : + + as_fn_error $? "Boost Program Options library not found" "$LINENO" 5 + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable unit test building" >&5 +$as_echo_n "checking whether to enable unit test building... " >&6; } + # Check whether --enable-unit-tests was given. +if test "${enable_unit_tests+set}" = set; then : + enableval=$enable_unit_tests; enable_unit_tests=$enableval +else + enable_unit_tests=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_unit_tests" >&5 +$as_echo "$enable_unit_tests" >&6; } + if test "x$enable_unit_tests" != "xno"; then + UNIT_TESTS_TRUE= + UNIT_TESTS_FALSE='#' +else + UNIT_TESTS_TRUE='#' + UNIT_TESTS_FALSE= +fi + + + if test "x$enable_unit_tests" != "xno"; then : + + if test x"$boost_cv_inc_path" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost unit_test_framework library" >&5 +$as_echo "$as_me: Boost not available, not searching for the Boost unit_test_framework library" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test x"" = "xno"; then : + not_found_header='true' +fi +if test x"$boost_cv_inc_path" = xno; then + $not_found_header +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_mongrel "$LINENO" "boost/test/unit_test.hpp" "ac_cv_header_boost_test_unit_test_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_test_unit_test_hpp" = xyes; then : + +$as_echo "#define HAVE_BOOST_TEST_UNIT_TEST_HPP 1" >>confdefs.h + +else + $not_found_header +fi + + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Boost unit_test_framework library" >&5 +$as_echo_n "checking for the Boost unit_test_framework library... " >&6; } +if ${boost_cv_lib_unit_test_framework+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_lib_unit_test_framework=no + case "mt" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "Xmt" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=mt;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[sgpn]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + as_fn_error $? "the libext variable is empty, did you invoke Libtool?" "$LINENO" 5 + boost_save_ac_objext=$ac_objext + # Generate the test file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; } +int +main () +{ +BOOST_CHECK(2 == 2); + ; + return 0; +} +_ACEOF + if ac_fn_cxx_try_compile "$LINENO"; then : + ac_objext=do_not_rm_me_plz +else + if test x"" != x"no"; then : + + as_fn_error $? "cannot compile a test that uses Boost unit_test_framework" "$LINENO" 5 + +fi + +fi +rm -f core conftest.err conftest.$ac_objext + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in unit_test_framework; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_full_suffix in \ + $boost_last_suffix \ + x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_mt_$boost_ver_ \ + x$boost_tag_$boost_ver_ + do + boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` + boost_lib="boost_$boost_lib_$boost_real_suffix" + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + boost_cv_lib_unit_test_framework_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$boost_cv_lib_unit_test_framework_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + boost_cv_lib_unit_test_framework_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$boost_cv_lib_unit_test_framework_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_cv_lib_unit_test_framework=yes +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_cv_lib_unit_test_framework=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$boost_cv_lib_unit_test_framework" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + if ${boost_cv_rpath_link_ldflag+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_cv_lib_unit_test_framework_LIBS $boost_save_LIBS" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_rpath_link_ldflag_found=yes + break +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_rpath_link_ldflag_found=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + done + ;; + esac + if test "x$boost_rpath_link_ldflag_found" != "xyes"; then : + as_fn_error $? "Unable to determine whether to use -R or -rpath" "$LINENO" 5 +fi + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + +fi + + test x"$boost_ldpath" != x && + boost_cv_lib_unit_test_framework_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + boost_cv_lib_unit_test_framework_LDPATH="$boost_ldpath" + boost_last_suffix="$boost_full_suffix" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_unit_test_framework" >&5 +$as_echo "$boost_cv_lib_unit_test_framework" >&6; } +case $boost_cv_lib_unit_test_framework in #( + (yes) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +$as_echo "#define HAVE_BOOST_UNIT_TEST_FRAMEWORK 1" >>confdefs.h + BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS=$boost_cv_lib_unit_test_framework_LDFLAGS + BOOST_UNIT_TEST_FRAMEWORK_LDPATH=$boost_cv_lib_unit_test_framework_LDPATH + BOOST_LDPATH=$boost_cv_lib_unit_test_framework_LDPATH + BOOST_UNIT_TEST_FRAMEWORK_LIBS=$boost_cv_lib_unit_test_framework_LIBS + ;; + (no) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + if test x"" != "xno"; then : + + as_fn_error $? "cannot find flags to link with the Boost unit_test_framework library (libboost-unit_test_framework)" "$LINENO" 5 + +fi + ;; +esac +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + + + + if test "$boost_cv_lib_unit_test_framework" = "no"; then : + + as_fn_error $? "Boost Unit Test library not found" "$LINENO" 5 + +fi + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable backend unit test building" >&5 +$as_echo_n "checking whether to enable backend unit test building... " >&6; } + # Check whether --enable-backend-unit-tests was given. +if test "${enable_backend_unit_tests+set}" = set; then : + enableval=$enable_backend_unit_tests; enable_backend_unit_tests=$enableval +else + enable_backend_unit_tests=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_backend_unit_tests" >&5 +$as_echo "$enable_backend_unit_tests" >&6; } + if test "x$enable_backend_unit_tests" != "xno"; then + BACKEND_UNIT_TESTS_TRUE= + BACKEND_UNIT_TESTS_FALSE='#' +else + BACKEND_UNIT_TESTS_TRUE='#' + BACKEND_UNIT_TESTS_FALSE= +fi + + + if test "x$enable_backend_unit_tests" != "xno"; then : + + if test x"$boost_cv_inc_path" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost unit_test_framework library" >&5 +$as_echo "$as_me: Boost not available, not searching for the Boost unit_test_framework library" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test x"" = "xno"; then : + not_found_header='true' +fi +if test x"$boost_cv_inc_path" = xno; then + $not_found_header +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_mongrel "$LINENO" "boost/test/unit_test.hpp" "ac_cv_header_boost_test_unit_test_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_test_unit_test_hpp" = xyes; then : + +$as_echo "#define HAVE_BOOST_TEST_UNIT_TEST_HPP 1" >>confdefs.h + +else + $not_found_header +fi + + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Boost unit_test_framework library" >&5 +$as_echo_n "checking for the Boost unit_test_framework library... " >&6; } +if ${boost_cv_lib_unit_test_framework+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_lib_unit_test_framework=no + case "mt" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "Xmt" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=mt;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[sgpn]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + as_fn_error $? "the libext variable is empty, did you invoke Libtool?" "$LINENO" 5 + boost_save_ac_objext=$ac_objext + # Generate the test file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; } +int +main () +{ +BOOST_CHECK(2 == 2); + ; + return 0; +} +_ACEOF + if ac_fn_cxx_try_compile "$LINENO"; then : + ac_objext=do_not_rm_me_plz +else + if test x"" != x"no"; then : + + as_fn_error $? "cannot compile a test that uses Boost unit_test_framework" "$LINENO" 5 + +fi + +fi +rm -f core conftest.err conftest.$ac_objext + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in unit_test_framework; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_full_suffix in \ + $boost_last_suffix \ + x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_mt_$boost_ver_ \ + x$boost_tag_$boost_ver_ + do + boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` + boost_lib="boost_$boost_lib_$boost_real_suffix" + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + boost_cv_lib_unit_test_framework_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$boost_cv_lib_unit_test_framework_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + boost_cv_lib_unit_test_framework_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$boost_cv_lib_unit_test_framework_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_cv_lib_unit_test_framework=yes +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_cv_lib_unit_test_framework=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$boost_cv_lib_unit_test_framework" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + if ${boost_cv_rpath_link_ldflag+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_cv_lib_unit_test_framework_LIBS $boost_save_LIBS" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_rpath_link_ldflag_found=yes + break +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_rpath_link_ldflag_found=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + done + ;; + esac + if test "x$boost_rpath_link_ldflag_found" != "xyes"; then : + as_fn_error $? "Unable to determine whether to use -R or -rpath" "$LINENO" 5 +fi + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + +fi + + test x"$boost_ldpath" != x && + boost_cv_lib_unit_test_framework_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + boost_cv_lib_unit_test_framework_LDPATH="$boost_ldpath" + boost_last_suffix="$boost_full_suffix" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_unit_test_framework" >&5 +$as_echo "$boost_cv_lib_unit_test_framework" >&6; } +case $boost_cv_lib_unit_test_framework in #( + (yes) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +$as_echo "#define HAVE_BOOST_UNIT_TEST_FRAMEWORK 1" >>confdefs.h + BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS=$boost_cv_lib_unit_test_framework_LDFLAGS + BOOST_UNIT_TEST_FRAMEWORK_LDPATH=$boost_cv_lib_unit_test_framework_LDPATH + BOOST_LDPATH=$boost_cv_lib_unit_test_framework_LDPATH + BOOST_UNIT_TEST_FRAMEWORK_LIBS=$boost_cv_lib_unit_test_framework_LIBS + ;; + (no) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + if test x"" != "xno"; then : + + as_fn_error $? "cannot find flags to link with the Boost unit_test_framework library (libboost-unit_test_framework)" "$LINENO" 5 + +fi + ;; +esac +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + + + + if test "$boost_cv_lib_unit_test_framework" = "no"; then : + + as_fn_error $? "Boost Unit Test library not found" "$LINENO" 5 + +fi + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable reproducible builds." >&5 +$as_echo_n "checking whether to enable reproducible builds.... " >&6; } + # Check whether --enable-reproducible was given. +if test "${enable_reproducible+set}" = set; then : + enableval=$enable_reproducible; enable_reproducible=$enableval +else + enable_reproducible=no +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_reproducible" >&5 +$as_echo "$enable_reproducible" >&6; } + + if test x"$enable_reproducible" = "xyes"; then : + + +$as_echo "#define REPRODUCIBLE 1" >>confdefs.h + + +else + + build_user=$(id -u -n) + + case "$host_os" in + solaris2.1* | SunOS | openbsd*) + build_host_host=$(hostname) + build_host_domain=$(domainname) + build_host="$build_host_host.$build_host_domain" + ;; + *) + build_host=$(hostname -f || hostname || echo 'localhost') + ;; + esac + +cat >>confdefs.h <<_ACEOF +#define BUILD_HOST "$build_user@$build_host" +_ACEOF + + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable fuzzing targets" >&5 +$as_echo_n "checking whether to enable fuzzing targets... " >&6; } + # Check whether --enable-fuzz_targets was given. +if test "${enable_fuzz_targets+set}" = set; then : + enableval=$enable_fuzz_targets; enable_fuzz_targets=$enableval +else + enable_fuzz_targets=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_fuzz_targets" >&5 +$as_echo "$enable_fuzz_targets" >&6; } + if test "x$enable_fuzz_targets" != "xno"; then + FUZZ_TARGETS_TRUE= + FUZZ_TARGETS_FALSE='#' +else + FUZZ_TARGETS_TRUE='#' + FUZZ_TARGETS_FALSE= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether user requires sqlite3" >&5 +$as_echo_n "checking whether user requires sqlite3... " >&6; } + +# Check whether --with-sqlite3 was given. +if test "${with_sqlite3+set}" = set; then : + withval=$with_sqlite3; with_sqlite3=$withval +else + with_sqlite3=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sqlite3" >&5 +$as_echo "$with_sqlite3" >&6; } + + if test "x$with_sqlite3" != "xno"; then : + + needsqlite3=yes + +fi + + + + # Extract the first word of "virtualenv", so it can be a program name with args. +set dummy virtualenv; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_VIRTUALENV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$VIRTUALENV"; then + ac_cv_prog_VIRTUALENV="$VIRTUALENV" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_VIRTUALENV="virtualenv" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_VIRTUALENV" && ac_cv_prog_VIRTUALENV="no" +fi +fi +VIRTUALENV=$ac_cv_prog_VIRTUALENV +if test -n "$VIRTUALENV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VIRTUALENV" >&5 +$as_echo "$VIRTUALENV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "x$VIRTUALENV" = "xno"; then : + + if test ! -f "$srcdir/pdns_server.1"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: virtualenv is missing, unable to build manpages." >&5 +$as_echo "$as_me: WARNING: virtualenv is missing, unable to build manpages." >&2;} + +fi + +fi + if test "x$VIRTUALENV" != "xno"; then + HAVE_VIRTUALENV_TRUE= + HAVE_VIRTUALENV_FALSE='#' +else + HAVE_VIRTUALENV_TRUE='#' + HAVE_VIRTUALENV_FALSE= +fi + + if test -e "$srcdir/docs/pdns_server.1"; then + HAVE_MANPAGES_TRUE= + HAVE_MANPAGES_FALSE='#' +else + HAVE_MANPAGES_TRUE='#' + HAVE_MANPAGES_FALSE= +fi + + + + if test -d "$srcdir/.git"; then + FROM_GIT_TRUE= + FROM_GIT_FALSE='#' +else + FROM_GIT_TRUE='#' + FROM_GIT_FALSE= +fi + + + + + + + for ac_func in $ac_func_list +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + if test "x$ac_cv_func_recvmmsg" = "xyes"; then + HAVE_RECVMMSG_TRUE= + HAVE_RECVMMSG_FALSE='#' +else + HAVE_RECVMMSG_TRUE='#' + HAVE_RECVMMSG_FALSE= +fi + + +if test "x$lt_cv_dlopen" = "xno"; then : + as_fn_error $? "Your system does not support dlopen" "$LINENO" 5 + +fi + +LIBDL=$lt_cv_dlopen_libs + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable verbose logging" >&5 +$as_echo_n "checking whether to enable verbose logging... " >&6; } + + # Check whether --enable-verbose-logging was given. +if test "${enable_verbose_logging+set}" = set; then : + enableval=$enable_verbose_logging; enable_verbose_logging=$enableval +else + enable_verbose_logging=no + +fi + + + if test "x$enable_verbose_logging" != "xno"; then : + +$as_echo "#define VERBOSELOG 1" >>confdefs.h + + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_verbose_logging" >&5 +$as_echo "$enable_verbose_logging" >&6; } + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable PKCS11 support" >&5 +$as_echo_n "checking whether to enable PKCS11 support... " >&6; } + # Check whether --enable-experimental-pkcs11 was given. +if test "${enable_experimental_pkcs11+set}" = set; then : + enableval=$enable_experimental_pkcs11; enable_pkcs11=$enableval +else + enable_pkcs11=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_pkcs11" >&5 +$as_echo "$enable_pkcs11" >&6; } + if test "x$enable_pkcs11" != "xno"; then + PKCS11_TRUE= + PKCS11_FALSE='#' +else + PKCS11_TRUE='#' + PKCS11_FALSE= +fi + + + if test "x$enable_pkcs11" != "xno"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for P11KIT1" >&5 +$as_echo_n "checking for P11KIT1... " >&6; } + +if test -n "$P11KIT1_CFLAGS"; then + pkg_cv_P11KIT1_CFLAGS="$P11KIT1_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"p11-kit-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "p11-kit-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_P11KIT1_CFLAGS=`$PKG_CONFIG --cflags "p11-kit-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$P11KIT1_LIBS"; then + pkg_cv_P11KIT1_LIBS="$P11KIT1_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"p11-kit-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "p11-kit-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_P11KIT1_LIBS=`$PKG_CONFIG --libs "p11-kit-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + P11KIT1_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "p11-kit-1" 2>&1` + else + P11KIT1_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "p11-kit-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$P11KIT1_PKG_ERRORS" >&5 + + as_fn_error $? "Could not find p11-kit-1" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Could not find p11-kit-1" "$LINENO" 5 + +else + P11KIT1_CFLAGS=$pkg_cv_P11KIT1_CFLAGS + P11KIT1_LIBS=$pkg_cv_P11KIT1_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_P11KIT1 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for p11_kit_module_for_name in -lp11-kit" >&5 +$as_echo_n "checking for p11_kit_module_for_name in -lp11-kit... " >&6; } +if ${ac_cv_lib_p11_kit_p11_kit_module_for_name+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lp11-kit $P11KIT1_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char p11_kit_module_for_name (); +int +main () +{ +return p11_kit_module_for_name (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_p11_kit_p11_kit_module_for_name=yes +else + ac_cv_lib_p11_kit_p11_kit_module_for_name=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_p11_kit_p11_kit_module_for_name" >&5 +$as_echo "$ac_cv_lib_p11_kit_p11_kit_module_for_name" >&6; } +if test "x$ac_cv_lib_p11_kit_p11_kit_module_for_name" = xyes; then : + +$as_echo "#define HAVE_P11KIT1_V2 1" >>confdefs.h + +fi + + +fi + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable experimental GSS-TSIG support" >&5 +$as_echo_n "checking whether to enable experimental GSS-TSIG support... " >&6; } + # Check whether --enable-experimental_gss_tsig was given. +if test "${enable_experimental_gss_tsig+set}" = set; then : + enableval=$enable_experimental_gss_tsig; enable_experimental_gss_tsig=$enableval +else + enable_experimental_gss_tsig=no + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_experimental_gss_tsig" >&5 +$as_echo "$enable_experimental_gss_tsig" >&6; } + + if test "x$enable_experimental_gss_tsig" != "xno"; then + GSS_TSIG_TRUE= + GSS_TSIG_FALSE='#' +else + GSS_TSIG_TRUE='#' + GSS_TSIG_FALSE= +fi + + + if test "x$enable_experimental_gss_tsig" != "xno"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSS" >&5 +$as_echo_n "checking for GSS... " >&6; } + +if test -n "$GSS_CFLAGS"; then + pkg_cv_GSS_CFLAGS="$GSS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"krb5 krb5-gssapi gss\""; } >&5 + ($PKG_CONFIG --exists --print-errors "krb5 krb5-gssapi gss") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSS_CFLAGS=`$PKG_CONFIG --cflags "krb5 krb5-gssapi gss" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GSS_LIBS"; then + pkg_cv_GSS_LIBS="$GSS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"krb5 krb5-gssapi gss\""; } >&5 + ($PKG_CONFIG --exists --print-errors "krb5 krb5-gssapi gss") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GSS_LIBS=`$PKG_CONFIG --libs "krb5 krb5-gssapi gss" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GSS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "krb5 krb5-gssapi gss" 2>&1` + else + GSS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "krb5 krb5-gssapi gss" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GSS_PKG_ERRORS" >&5 + + as_fn_error $? "Required libraries for GSS-TSIG not found" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Required libraries for GSS-TSIG not found" "$LINENO" 5 + +else + GSS_CFLAGS=$pkg_cv_GSS_CFLAGS + GSS_LIBS=$pkg_cv_GSS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define ENABLE_GSS_TSIG 1" >>confdefs.h + + GSS_TSIG=yes + +fi +else + GSS_TSIG=no +fi + + + +socketdir="/var/run" + +# Check whether --with-socketdir was given. +if test "${with_socketdir+set}" = set; then : + withval=$with_socketdir; socketdir="$withval" + +fi + + +modules="bind gmysql random" + +# Check whether --with-modules was given. +if test "${with_modules+set}" = set; then : + withval=$with_modules; modules="$withval" + +fi + + +dynmodules="pipe" + +# Check whether --with-dynmodules was given. +if test "${with_dynmodules+set}" = set; then : + withval=$with_dynmodules; dynmodules="$withval" + +fi + + + + + + +cat >>confdefs.h <<_ACEOF +#define PDNS_MODULES "$modules" +_ACEOF + + +if test x"$modules" = "xno"; then : + modules="" +fi +if test x"$dynmodules" = "xno"; then : + dynmodules="" +fi + +for a in $modules $dynmodules; do + case "$a" in + oracle|goracle) + + +# Check whether --with-oracle_includes was given. +if test "${with_oracle_includes+set}" = set; then : + withval=$with_oracle_includes; +fi + + +# Check whether --with-oracle_libs was given. +if test "${with_oracle_libs+set}" = set; then : + withval=$with_oracle_libs; +fi + + + if test x"$with_oracle_includes" = "x"; then + # check possible locations + for p1 in /usr/include/oracle /usr/local/include/oracle; do + for p2 in $p1/*/client*; do + if test -d "$p2"; then + with_oracle_includes=$p2 + fi + done + done + fi + + if test x"$with_oracle_includes" = x && test "$ORACLE_HOME/rdbms/public" != "/rdbms/public"; then + if test -d $ORACLE_HOME/rdbms/public; then + with_oracle_includes=$ORACLE_HOME/rdbms/public + fi + fi + + # test header + old_CXXFLAGS="$CXXFLAGS" + old_CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS -I$with_oracle_includes" + CPPFLAGS="$CPPFLAGS -I$with_oracle_includes" + ac_fn_cxx_check_header_mongrel "$LINENO" "oci.h" "ac_cv_header_oci_h" "$ac_includes_default" +if test "x$ac_cv_header_oci_h" = xyes; then : + ORACLE_CFLAGS="-I$with_oracle_includes" +else + as_fn_error $? "Could not find oci.h" "$LINENO" 5 +fi + + + CXXFLAGS="$old_CXXFLAGS" + CPPFLAGS="$old_CPPFLAGS" + + + + if test x"$with_oracle_libs" = "x"; then + # check possible locations + for p1 in /usr/lib/oracle /usr/local/lib/oracle; do + for p2 in $p1/*/client*/lib; do + if test -d "$p2"; then + with_oracle_libs=$p2 + fi + done + done + fi + + if test x"$with_oracle_libs" = x && test "$ORACLE_HOME/lib" != "/lib"; then + if test -d $ORACLE_HOME/lib; then + with_oracle_libs=$ORACLE_HOME/lib + fi + fi + + # we have to check for client9 as well... + # test -lclntsh + old_LDFLAGS="$LDFLAGS" + LDFLAGS="-L$with_oracle_libs -locci" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OCIEnvInit in -lclntsh" >&5 +$as_echo_n "checking for OCIEnvInit in -lclntsh... " >&6; } +if ${ac_cv_lib_clntsh_OCIEnvInit+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lclntsh $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OCIEnvInit (); +int +main () +{ +return OCIEnvInit (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_clntsh_OCIEnvInit=yes +else + ac_cv_lib_clntsh_OCIEnvInit=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_clntsh_OCIEnvInit" >&5 +$as_echo "$ac_cv_lib_clntsh_OCIEnvInit" >&6; } +if test "x$ac_cv_lib_clntsh_OCIEnvInit" = xyes; then : + ORACLE_LIBS="-L$with_oracle_libs -lclntsh -locci" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OCIEnvInit in -lclient9" >&5 +$as_echo_n "checking for OCIEnvInit in -lclient9... " >&6; } +if ${ac_cv_lib_client9_OCIEnvInit+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lclient9 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OCIEnvInit (); +int +main () +{ +return OCIEnvInit (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_client9_OCIEnvInit=yes +else + ac_cv_lib_client9_OCIEnvInit=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_client9_OCIEnvInit" >&5 +$as_echo "$ac_cv_lib_client9_OCIEnvInit" >&6; } +if test "x$ac_cv_lib_client9_OCIEnvInit" = xyes; then : + ORACLE_LIBS="-L$with_oracle_libs -lclient9 -lclntsh9" +else + as_fn_error $? "Could not find client libraries" "$LINENO" 5 + +fi + + +fi + + LDFLAGS="$old_LDFLAGS" + + needoracle=yes + ;; + godbc) + + +# Check whether --with-unixodbc was given. +if test "${with_unixodbc+set}" = set; then : + withval=$with_unixodbc; + UNIXODBC_LIBS_check="$withval/lib/unixodbc $with_unixodbc/lib" + UNIXODBC_CFLAGS_check="$withval/include/unixodbc" + UNIXODBC_config_check="$withval/bin/odbc_config" + +else + + UNIXODBC_LIBS_check="/usr/local/unixodbc/lib/unixodbc /usr/local/lib/unixodbc /opt/unixodbc/lib/unixodbc \ + /usr/lib/unixodbc /usr/lib64/unixodbc /usr/local/unixodbc/lib /usr/local/lib /opt/unixodbc/lib /usr/lib \ + /usr/sfw/lib/ /usr/lib/odbc /usr/lib/x86_64-linux-gnu $full_libdir" + UNIXODBC_CFLAGS_check="/usr/local/unixodbc/include/unixodbc /usr/local/include/unixodbc \ + /opt/unixodbc/include/unixodbc /opt/unixodbc/include /usr/include/unixodbc /usr/sfw/include/unixodbc \ + /usr/include /usr/local/include" + + +fi + + + +# Check whether --with-odbc-config was given. +if test "${with_odbc_config+set}" = set; then : + withval=$with_odbc_config; UNIXODBC_config_check=$withval + +fi + + + +# Check whether --with-unixodbc-lib was given. +if test "${with_unixodbc_lib+set}" = set; then : + withval=$with_unixodbc_lib; + UNIXODBC_LIBS_check="$withval/lib/unixodbc $withval/unixodbc $withval" + UNIXODBC_config_check="skip" + + +fi + + + +# Check whether --with-unixodbc-includes was given. +if test "${with_unixodbc_includes+set}" = set; then : + withval=$with_unixodbc_includes; + UNIXODBC_CFLAGS_check="$withval/include/unixodbc $withval/unixodbc $withval" + UNIXODBC_config_check="skip" + + +fi + + + UNIXODBC_config="" + if test "x$UNIXODBC_config_check" != "xskip"; then + if test "x$UNIXODBC_config_check" = "x"; then + # Extract the first word of "odbc_config", so it can be a program name with args. +set dummy odbc_config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_UNIXODBC_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $UNIXODBC_config in + [\\/]* | ?:[\\/]*) + ac_cv_path_UNIXODBC_config="$UNIXODBC_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_UNIXODBC_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +UNIXODBC_config=$ac_cv_path_UNIXODBC_config +if test -n "$UNIXODBC_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNIXODBC_config" >&5 +$as_echo "$UNIXODBC_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $UNIXODBC_config_check" >&5 +$as_echo_n "checking for $UNIXODBC_config_check... " >&6; } + if test -x $UNIXODBC_config_check; then + UNIXODBC_config="$UNIXODBC_config_check" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + UNIXODBC_config="" + as_fn_error $? "not found" "$LINENO" 5 + fi + fi + fi + + if test "x$UNIXODBC_config" != "x"; then + # use this to configure everything + UNIXODBC_LIBS=`$UNIXODBC_config --libs` + UNIXODBC_CFLAGS=-I`$UNIXODBC_config --include-prefix` + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unixODBC library directory" >&5 +$as_echo_n "checking for unixODBC library directory... " >&6; } + UNIXODBC_libdir= + for m in $UNIXODBC_LIBS_check; do + if test -d "$m" && \ + (test -f "$m/libodbc.so" || test -f "$m/libodbc.a") + then + UNIXODBC_libdir=$m + break + fi + done + if test -z "$UNIXODBC_libdir"; then + as_fn_error $? "Did not find the unixodbc library dir in '$UNIXODBC_LIBS_check'" "$LINENO" 5 + fi + case "$UNIXODBC_libdir" in + /*) UNIXODBC_LIBS="-L$UNIXODBC_libdir -lodbc" + ;; + *) as_fn_error $? "The unixODBC library directory ($UNIXODBC_libdir) must be an absolute path." "$LINENO" 5 + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNIXODBC_libdir" >&5 +$as_echo "$UNIXODBC_libdir" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unixODBC include directory" >&5 +$as_echo_n "checking for unixODBC include directory... " >&6; } + UNIXODBC_CFLAGS= + for m in $UNIXODBC_CFLAGS_check; do + if test -d "$m" && test -f "$m/sql.h" + then + UNIXODBC_CFLAGS="$m" + break + fi + done + if test -z "$UNIXODBC_CFLAGS"; then + as_fn_error $? "Did not find the unixodbc include dir in '$UNIXODBC_CFLAGS_check'" "$LINENO" 5 + fi + + case "$UNIXODBC_CFLAGS" in + /*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNIXODBC_CFLAGS" >&5 +$as_echo "$UNIXODBC_CFLAGS" >&6; } + ;; + *) as_fn_error $? "The unixODBC include directory ($UNIXODBC_CFLAGS) must be an absolute path." "$LINENO" 5 + ;; + esac + UNIXODBC_CFLAGS="-I$UNIXODBC_CFLAGS" + fi + + + + + ;; + mydns|gmysql) + + +# Check whether --with-mysql was given. +if test "${with_mysql+set}" = set; then : + withval=$with_mysql; + if test "$withval" = "no"; then + modules_without_gmysql=$(echo $modules|sed -e 's/gmysql//;s/ */ /g;') + dynmodules_without_gmysql=$(echo $dynmodules|sed -e 's/gmysql//;s/ */ /g;') + as_fn_error $? "instead of --without-mysql try --with-modules=\"$modules_without_gmysql\" --with-dyn-modules=\"$dynmodules_without_gmysql\"" "$LINENO" 5 + fi + + MYSQL_LIBS_check="$withval/lib/mysql $with_mysql/lib" + MYSQL_CFLAGS_check="$withval/include/mysql" + MYSQL_config_check="$withval/bin/mysql_config" + +else + + MYSQL_LIBS_check="/usr/local/mysql/lib/mysql /usr/local/lib/mysql /opt/mysql/lib/mysql \ + /usr/lib/mysql /usr/lib64/mysql /usr/local/mysql/lib /usr/local/lib /opt/mysql/lib /usr/lib \ + /usr/sfw/lib/ $full_libdir" + MYSQL_CFLAGS_check="/usr/local/mysql/include/mysql /usr/local/include/mysql \ + /opt/mysql/include/mysql /opt/mysql/include /usr/include/mysql /usr/sfw/include/mysql" + + +fi + + + +# Check whether --with-mysql-config was given. +if test "${with_mysql_config+set}" = set; then : + withval=$with_mysql_config; MYSQL_config_check=$withval + +fi + + + +# Check whether --with-mysql-lib was given. +if test "${with_mysql_lib+set}" = set; then : + withval=$with_mysql_lib; + MYSQL_LIBS_check="$withval/lib/mysql $withval/mysql $withval" + MYSQL_config_check="skip" + + +fi + + + +# Check whether --with-mysql-includes was given. +if test "${with_mysql_includes+set}" = set; then : + withval=$with_mysql_includes; + MYSQL_CFLAGS_check="$withval/include/mysql $withval/mysql $withval" + MYSQL_config_check="skip" + + +fi + + + MYSQL_config="" + if test "x$MYSQL_config_check" != "xskip"; then + if test "x$MYSQL_config_check" = "x"; then + # Extract the first word of "mysql_config", so it can be a program name with args. +set dummy mysql_config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MYSQL_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MYSQL_config in + [\\/]* | ?:[\\/]*) + ac_cv_path_MYSQL_config="$MYSQL_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MYSQL_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MYSQL_config=$ac_cv_path_MYSQL_config +if test -n "$MYSQL_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_config" >&5 +$as_echo "$MYSQL_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $MYSQL_config_check" >&5 +$as_echo_n "checking for $MYSQL_config_check... " >&6; } + if test -x $MYSQL_config_check; then + MYSQL_config="$MYSQL_config_check" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + MYSQL_config="" + as_fn_error $? "not found" "$LINENO" 5 + fi + fi + fi + + if test "x$MYSQL_config" != "x"; then + # use this to configure everything + MYSQL_LIBS=`$MYSQL_config --libs` + MYSQL_CFLAGS=`$MYSQL_config --include` + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MySQL library directory" >&5 +$as_echo_n "checking for MySQL library directory... " >&6; } + MYSQL_libdir= + for m in $MYSQL_LIBS_check; do + if test -d "$m" && \ + (test -f "$m/libmysqlclient.so" || test -f "$m/libmysqlclient.a") + then + MYSQL_libdir=$m + break + fi + done + if test -z "$MYSQL_libdir"; then + as_fn_error $? "Did not find the mysql library dir in '$MYSQL_LIBS_check'" "$LINENO" 5 + fi + case "$MYSQL_libdir" in + /*) MYSQL_LIBS="-L$MYSQL_libdir -lmysqlclient" + ;; + *) as_fn_error $? "The MySQL library directory ($MYSQL_libdir) must be an absolute path." "$LINENO" 5 + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_libdir" >&5 +$as_echo "$MYSQL_libdir" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MySQL include directory" >&5 +$as_echo_n "checking for MySQL include directory... " >&6; } + MYSQL_CFLAGS= + for m in $MYSQL_CFLAGS_check; do + if test -d "$m" && test -f "$m/mysql.h" + then + MYSQL_CFLAGS="$m" + break + fi + done + if test -z "$MYSQL_CFLAGS"; then + as_fn_error $? "Did not find the mysql include dir in '$MYSQL_CFLAGS_check'" "$LINENO" 5 + fi + + case "$MYSQL_CFLAGS" in + /*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MYSQL_CFLAGS" >&5 +$as_echo "$MYSQL_CFLAGS" >&6; } + ;; + *) as_fn_error $? "The MySQL include directory ($MYSQL_CFLAGS) must be an absolute path." "$LINENO" 5 + ;; + esac + MYSQL_CFLAGS="-I$MYSQL_CFLAGS" + fi + + + + ;; + gpgsql) + + PG_CONFIG="" + +# Check whether --with-pg-config was given. +if test "${with_pg_config+set}" = set; then : + withval=$with_pg_config; + PG_CONFIG="$withval" + if test "x$PG_CONFIG" = "xyes" -o ! -x "$PG_CONFIG"; then : + + as_fn_error $? "--with-pg-config must provide a valid path to the pg_config executable" "$LINENO" 5 + +fi + +fi + + + if test "x$PG_CONFIG" = "x"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PGSQL" >&5 +$as_echo_n "checking for PGSQL... " >&6; } + +if test -n "$PGSQL_CFLAGS"; then + pkg_cv_PGSQL_CFLAGS="$PGSQL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpq") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PGSQL_CFLAGS=`$PKG_CONFIG --cflags "libpq" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PGSQL_LIBS"; then + pkg_cv_PGSQL_LIBS="$PGSQL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpq\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpq") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PGSQL_LIBS=`$PKG_CONFIG --libs "libpq" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PGSQL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpq" 2>&1` + else + PGSQL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpq" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PGSQL_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + PGSQL_CFLAGS=$pkg_cv_PGSQL_CFLAGS + PGSQL_LIBS=$pkg_cv_PGSQL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +fi + + if test "x$PG_CONFIG" != "x" -o "x$PGSQL_LIBS" = "x"; then : + + if test "x$PG_CONFIG" == "x"; then : + + # Extract the first word of "pg_config", so it can be a program name with args. +set dummy pg_config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PG_CONFIG=$ac_cv_path_PG_CONFIG +if test -n "$PG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5 +$as_echo "$PG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +fi + if test "x$PG_CONFIG" == "x"; then : + + as_fn_error $? "Can not find pg_config, use --with-pg-config to specify the path to pg_config" "$LINENO" 5 + +fi + PGSQL_LIBS="-L$($PG_CONFIG --libdir) -lpq" + PGSQL_CFLAGS="-I$($PG_CONFIG --includedir)" + +fi + + + + ;; + gsqlite3) + needsqlite3=yes + ;; + ldap) + + for ac_header in ldap.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "ldap.h" "ac_cv_header_ldap_h" "$ac_includes_default" +if test "x$ac_cv_header_ldap_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LDAP_H 1 +_ACEOF + +else + as_fn_error $? "ldap header (ldap.h) not found" "$LINENO" 5 + +fi + +done + + + for ac_header in lber.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "lber.h" "ac_cv_header_lber_h" "$ac_includes_default" +if test "x$ac_cv_header_lber_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LBER_H 1 +_ACEOF + +else + as_fn_error $? "ldap header (lber.h) not found" "$LINENO" 5 + +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_set_option in -lldap_r" >&5 +$as_echo_n "checking for ldap_set_option in -lldap_r... " >&6; } +if ${ac_cv_lib_ldap_r_ldap_set_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap_r $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_set_option (); +int +main () +{ +return ldap_set_option (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ldap_r_ldap_set_option=yes +else + ac_cv_lib_ldap_r_ldap_set_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_r_ldap_set_option" >&5 +$as_echo "$ac_cv_lib_ldap_r_ldap_set_option" >&6; } +if test "x$ac_cv_lib_ldap_r_ldap_set_option" = xyes; then : + + +$as_echo "#define HAVE_LIBLDAP_R 1" >>confdefs.h + + LIBLDAP="ldap_r" + LDAP_LIBS="-lldap_r -llber" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_set_option in -lldap" >&5 +$as_echo_n "checking for ldap_set_option in -lldap... " >&6; } +if ${ac_cv_lib_ldap_ldap_set_option+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_set_option (); +int +main () +{ +return ldap_set_option (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_ldap_ldap_set_option=yes +else + ac_cv_lib_ldap_ldap_set_option=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_set_option" >&5 +$as_echo "$ac_cv_lib_ldap_ldap_set_option" >&6; } +if test "x$ac_cv_lib_ldap_ldap_set_option" = xyes; then : + + +$as_echo "#define HAVE_LIBLDAP 1" >>confdefs.h + + LIBLDAP="ldap" + LDAP_LIBS="-lldap -llber" + +else + as_fn_error $? "ldap library (libldap) not found" "$LINENO" 5 + +fi + + + +fi + + + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBLDAP''_ldap_initialize" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_initialize in -l$LIBLDAP" >&5 +$as_echo_n "checking for ldap_initialize in -l$LIBLDAP... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$LIBLDAP $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_initialize (); +int +main () +{ +return ldap_initialize (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + +$as_echo "#define HAVE_LDAP_INITIALIZE 1" >>confdefs.h + + +fi + + + as_ac_Lib=`$as_echo "ac_cv_lib_$LIBLDAP''_ldap_sasl_bind" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_sasl_bind in -l$LIBLDAP" >&5 +$as_echo_n "checking for ldap_sasl_bind in -l$LIBLDAP... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$LIBLDAP $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_sasl_bind (); +int +main () +{ +return ldap_sasl_bind (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + +$as_echo "#define HAVE_LDAP_SASL_BIND 1" >>confdefs.h + + +fi + + + + + for ac_header in krb5.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "krb5.h" "ac_cv_header_krb5_h" "$ac_includes_default" +if test "x$ac_cv_header_krb5_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_KRB5_H 1 +_ACEOF + +else + as_fn_error $? "Kerberos header (krb5.h) not found" "$LINENO" 5 + +fi + +done + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for krb5_init_context in -lkrb5" >&5 +$as_echo_n "checking for krb5_init_context in -lkrb5... " >&6; } +if ${ac_cv_lib_krb5_krb5_init_context+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkrb5 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char krb5_init_context (); +int +main () +{ +return krb5_init_context (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_krb5_krb5_init_context=yes +else + ac_cv_lib_krb5_krb5_init_context=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_krb5_krb5_init_context" >&5 +$as_echo "$ac_cv_lib_krb5_krb5_init_context" >&6; } +if test "x$ac_cv_lib_krb5_krb5_init_context" = xyes; then : + + KRB5_LIBS="-lkrb5" + + +fi + + + for ac_func in krb5_get_init_creds_opt_set_default_flags +do : + ac_fn_cxx_check_func "$LINENO" "krb5_get_init_creds_opt_set_default_flags" "ac_cv_func_krb5_get_init_creds_opt_set_default_flags" +if test "x$ac_cv_func_krb5_get_init_creds_opt_set_default_flags" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS 1 +_ACEOF + +fi +done + + + needldap=yes + ;; + opendbx) + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENDBX" >&5 +$as_echo_n "checking for OPENDBX... " >&6; } + +if test -n "$OPENDBX_CFLAGS"; then + pkg_cv_OPENDBX_CFLAGS="$OPENDBX_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opendbx\""; } >&5 + ($PKG_CONFIG --exists --print-errors "opendbx") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENDBX_CFLAGS=`$PKG_CONFIG --cflags "opendbx" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OPENDBX_LIBS"; then + pkg_cv_OPENDBX_LIBS="$OPENDBX_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opendbx\""; } >&5 + ($PKG_CONFIG --exists --print-errors "opendbx") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENDBX_LIBS=`$PKG_CONFIG --libs "opendbx" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + OPENDBX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "opendbx" 2>&1` + else + OPENDBX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "opendbx" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OPENDBX_PKG_ERRORS" >&5 + + + for ac_header in odbx.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "odbx.h" "ac_cv_header_odbx_h" "$ac_includes_default" +if test "x$ac_cv_header_odbx_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ODBX_H 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for odbx_init in -lopendbx" >&5 +$as_echo_n "checking for odbx_init in -lopendbx... " >&6; } +if ${ac_cv_lib_opendbx_odbx_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopendbx $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char odbx_init (); +int +main () +{ +return odbx_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_opendbx_odbx_init=yes +else + ac_cv_lib_opendbx_odbx_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opendbx_odbx_init" >&5 +$as_echo "$ac_cv_lib_opendbx_odbx_init" >&6; } +if test "x$ac_cv_lib_opendbx_odbx_init" = xyes; then : + OPENDBX_LIBS="-lopendbx" +else + as_fn_error $? "libopendbx not found" "$LINENO" 5 + +fi + +else + + as_fn_error $? "opendbx header (odbx.h) not found" "$LINENO" 5 + + +fi + +done + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + for ac_header in odbx.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "odbx.h" "ac_cv_header_odbx_h" "$ac_includes_default" +if test "x$ac_cv_header_odbx_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ODBX_H 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for odbx_init in -lopendbx" >&5 +$as_echo_n "checking for odbx_init in -lopendbx... " >&6; } +if ${ac_cv_lib_opendbx_odbx_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopendbx $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char odbx_init (); +int +main () +{ +return odbx_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_opendbx_odbx_init=yes +else + ac_cv_lib_opendbx_odbx_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opendbx_odbx_init" >&5 +$as_echo "$ac_cv_lib_opendbx_odbx_init" >&6; } +if test "x$ac_cv_lib_opendbx_odbx_init" = xyes; then : + OPENDBX_LIBS="-lopendbx" +else + as_fn_error $? "libopendbx not found" "$LINENO" 5 + +fi + +else + + as_fn_error $? "opendbx header (odbx.h) not found" "$LINENO" 5 + + +fi + +done + + +else + OPENDBX_CFLAGS=$pkg_cv_OPENDBX_CFLAGS + OPENDBX_LIBS=$pkg_cv_OPENDBX_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + ;; + remote) + if test "x$enable_unit_tests" = "xyes"; then : + + # Extract the first word of "curl", so it can be a program name with args. +set dummy curl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CURL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CURL"; then + ac_cv_prog_CURL="$CURL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CURL="curl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CURL" && ac_cv_prog_CURL="no" +fi +fi +CURL=$ac_cv_prog_CURL +if test -n "$CURL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CURL" >&5 +$as_echo "$CURL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "x$CURL" = "xno"; then : + + as_fn_error $? "curl program is missing, required for running remotebackend unit tests" "$LINENO" 5 + +fi + + +fi + have_remotebackend=yes + ;; + tinydns) + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CDB" >&5 +$as_echo_n "checking for CDB... " >&6; } + +if test -n "$CDB_CFLAGS"; then + pkg_cv_CDB_CFLAGS="$CDB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CDB_CFLAGS=`$PKG_CONFIG --cflags "libcdb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CDB_LIBS"; then + pkg_cv_CDB_LIBS="$CDB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CDB_LIBS=`$PKG_CONFIG --libs "libcdb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CDB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcdb" 2>&1` + else + CDB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcdb" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CDB_PKG_ERRORS" >&5 + + for ac_header in cdb.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cdb.h" "ac_cv_header_cdb_h" "$ac_includes_default" +if test "x$ac_cv_header_cdb_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CDB_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cdb_find in -lcdb" >&5 +$as_echo_n "checking for cdb_find in -lcdb... " >&6; } +if ${ac_cv_lib_cdb_cdb_find+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcdb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cdb_find (); +int +main () +{ +return cdb_find (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_cdb_cdb_find=yes +else + ac_cv_lib_cdb_cdb_find=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cdb_cdb_find" >&5 +$as_echo "$ac_cv_lib_cdb_cdb_find" >&6; } +if test "x$ac_cv_lib_cdb_cdb_find" = xyes; then : + CDB_LIBS="-lcdb" +else + as_fn_error $? "Could not find libcdb" "$LINENO" 5 + +fi + +else + as_fn_error $? "Could not find cdb.h" "$LINENO" 5 + +fi + +done + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + for ac_header in cdb.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cdb.h" "ac_cv_header_cdb_h" "$ac_includes_default" +if test "x$ac_cv_header_cdb_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CDB_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cdb_find in -lcdb" >&5 +$as_echo_n "checking for cdb_find in -lcdb... " >&6; } +if ${ac_cv_lib_cdb_cdb_find+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcdb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cdb_find (); +int +main () +{ +return cdb_find (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_cdb_cdb_find=yes +else + ac_cv_lib_cdb_cdb_find=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cdb_cdb_find" >&5 +$as_echo "$ac_cv_lib_cdb_cdb_find" >&6; } +if test "x$ac_cv_lib_cdb_cdb_find" = xyes; then : + CDB_LIBS="-lcdb" +else + as_fn_error $? "Could not find libcdb" "$LINENO" 5 + +fi + +else + as_fn_error $? "Could not find cdb.h" "$LINENO" 5 + +fi + +done + + +else + CDB_CFLAGS=$pkg_cv_CDB_CFLAGS + CDB_LIBS=$pkg_cv_CDB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + ;; + geoip) + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GEOIP" >&5 +$as_echo_n "checking for GEOIP... " >&6; } + +if test -n "$GEOIP_CFLAGS"; then + pkg_cv_GEOIP_CFLAGS="$GEOIP_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip\""; } >&5 + ($PKG_CONFIG --exists --print-errors "geoip") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GEOIP_CFLAGS=`$PKG_CONFIG --cflags "geoip" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GEOIP_LIBS"; then + pkg_cv_GEOIP_LIBS="$GEOIP_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"geoip\""; } >&5 + ($PKG_CONFIG --exists --print-errors "geoip") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GEOIP_LIBS=`$PKG_CONFIG --libs "geoip" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GEOIP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "geoip" 2>&1` + else + GEOIP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "geoip" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GEOIP_PKG_ERRORS" >&5 + + have_geoip=0 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_geoip=0 +else + GEOIP_CFLAGS=$pkg_cv_GEOIP_CFLAGS + GEOIP_LIBS=$pkg_cv_GEOIP_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GEOIP 1" >>confdefs.h + +fi + +# Check whether --with-maxminddb_incdir was given. +if test "${with_maxminddb_incdir+set}" = set; then : + withval=$with_maxminddb_incdir; with_maxminddb_incdir=$withval +else + with_maxminddb_incdir=auto + +fi + + +# Check whether --with-maxminddb_libdir was given. +if test "${with_maxminddb_libdir+set}" = set; then : + withval=$with_maxminddb_libdir; with_maxminddb_libdir=$withval +else + with_maxminddb_libdir=auto +fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB" >&5 +$as_echo_n "checking for MMDB... " >&6; } + +if test -n "$MMDB_CFLAGS"; then + pkg_cv_MMDB_CFLAGS="$MMDB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libmaxminddb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MMDB_CFLAGS=`$PKG_CONFIG --cflags "libmaxminddb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$MMDB_LIBS"; then + pkg_cv_MMDB_LIBS="$MMDB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmaxminddb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libmaxminddb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MMDB_LIBS=`$PKG_CONFIG --libs "libmaxminddb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + MMDB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libmaxminddb" 2>&1` + else + MMDB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libmaxminddb" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$MMDB_PKG_ERRORS" >&5 + + + if test "x$with_maxminddb_incdir" = "xauto"; then : + + ac_fn_cxx_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default" +if test "x$ac_cv_header_maxminddb_h" = xyes; then : + have_mmdb=1 +else + have_mmdb=0 +fi + + + +else + + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -I$with_maxminddb_incdir" + ac_fn_cxx_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default" +if test "x$ac_cv_header_maxminddb_h" = xyes; then : + have_mmdb=1 +else + have_mmdb=0 +fi + + + CFLAGS="$OLD_CFLAGS" + +fi + + if test "$have_mmdb" = "1"; then : + + if test "x$with_maxminddb_libdir" = "xauto"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB_open in -lmaxminddb" >&5 +$as_echo_n "checking for MMDB_open in -lmaxminddb... " >&6; } +if ${ac_cv_lib_maxminddb_MMDB_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmaxminddb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MMDB_open (); +int +main () +{ +return MMDB_open (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_maxminddb_MMDB_open=yes +else + ac_cv_lib_maxminddb_MMDB_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_maxminddb_MMDB_open" >&5 +$as_echo "$ac_cv_lib_maxminddb_MMDB_open" >&6; } +if test "x$ac_cv_lib_maxminddb_MMDB_open" = xyes; then : + + +$as_echo "#define HAVE_MMDB 1" >>confdefs.h + + MMDB_LIBS="-lmaxminddb" + +fi + + +else + + OLD_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$with_maxminddb_libdir" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB_open in -lmaxminddb" >&5 +$as_echo_n "checking for MMDB_open in -lmaxminddb... " >&6; } +if ${ac_cv_lib_maxminddb_MMDB_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmaxminddb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MMDB_open (); +int +main () +{ +return MMDB_open (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_maxminddb_MMDB_open=yes +else + ac_cv_lib_maxminddb_MMDB_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_maxminddb_MMDB_open" >&5 +$as_echo "$ac_cv_lib_maxminddb_MMDB_open" >&6; } +if test "x$ac_cv_lib_maxminddb_MMDB_open" = xyes; then : + + +$as_echo "#define HAVE_MMDB 1" >>confdefs.h + + MMDB_CFLAGS="-I$with_maxminddb_incdir" + MMDB_LIBS="-L$with_maxminddb_libdir -lmaxminddb" + +fi + + +fi + +fi + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + if test "x$with_maxminddb_incdir" = "xauto"; then : + + ac_fn_cxx_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default" +if test "x$ac_cv_header_maxminddb_h" = xyes; then : + have_mmdb=1 +else + have_mmdb=0 +fi + + + +else + + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -I$with_maxminddb_incdir" + ac_fn_cxx_check_header_mongrel "$LINENO" "maxminddb.h" "ac_cv_header_maxminddb_h" "$ac_includes_default" +if test "x$ac_cv_header_maxminddb_h" = xyes; then : + have_mmdb=1 +else + have_mmdb=0 +fi + + + CFLAGS="$OLD_CFLAGS" + +fi + + if test "$have_mmdb" = "1"; then : + + if test "x$with_maxminddb_libdir" = "xauto"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB_open in -lmaxminddb" >&5 +$as_echo_n "checking for MMDB_open in -lmaxminddb... " >&6; } +if ${ac_cv_lib_maxminddb_MMDB_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmaxminddb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MMDB_open (); +int +main () +{ +return MMDB_open (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_maxminddb_MMDB_open=yes +else + ac_cv_lib_maxminddb_MMDB_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_maxminddb_MMDB_open" >&5 +$as_echo "$ac_cv_lib_maxminddb_MMDB_open" >&6; } +if test "x$ac_cv_lib_maxminddb_MMDB_open" = xyes; then : + + +$as_echo "#define HAVE_MMDB 1" >>confdefs.h + + MMDB_LIBS="-lmaxminddb" + +fi + + +else + + OLD_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$with_maxminddb_libdir" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MMDB_open in -lmaxminddb" >&5 +$as_echo_n "checking for MMDB_open in -lmaxminddb... " >&6; } +if ${ac_cv_lib_maxminddb_MMDB_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmaxminddb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MMDB_open (); +int +main () +{ +return MMDB_open (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_maxminddb_MMDB_open=yes +else + ac_cv_lib_maxminddb_MMDB_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_maxminddb_MMDB_open" >&5 +$as_echo "$ac_cv_lib_maxminddb_MMDB_open" >&6; } +if test "x$ac_cv_lib_maxminddb_MMDB_open" = xyes; then : + + +$as_echo "#define HAVE_MMDB 1" >>confdefs.h + + MMDB_CFLAGS="-I$with_maxminddb_incdir" + MMDB_LIBS="-L$with_maxminddb_libdir -lmaxminddb" + +fi + + +fi + +fi + +else + MMDB_CFLAGS=$pkg_cv_MMDB_CFLAGS + MMDB_LIBS=$pkg_cv_MMDB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_MMDB 1" >>confdefs.h + + +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for YAML" >&5 +$as_echo_n "checking for YAML... " >&6; } + +if test -n "$YAML_CFLAGS"; then + pkg_cv_YAML_CFLAGS="$YAML_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yaml-cpp >= 0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "yaml-cpp >= 0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_YAML_CFLAGS=`$PKG_CONFIG --cflags "yaml-cpp >= 0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$YAML_LIBS"; then + pkg_cv_YAML_LIBS="$YAML_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yaml-cpp >= 0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "yaml-cpp >= 0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_YAML_LIBS=`$PKG_CONFIG --libs "yaml-cpp >= 0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + YAML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "yaml-cpp >= 0.5" 2>&1` + else + YAML_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "yaml-cpp >= 0.5" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$YAML_PKG_ERRORS" >&5 + + as_fn_error $? "Could not find yaml-cpp" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Could not find yaml-cpp" "$LINENO" 5 + +else + YAML_CFLAGS=$pkg_cv_YAML_CFLAGS + YAML_LIBS=$pkg_cv_YAML_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + ;; + lua*) + if test "x$with_lua" = "xno"; then : + as_fn_error $? "${a} backend needs lua, run ./configure --with-lua" "$LINENO" 5 + +fi + if test "x$LUAPC" = "x"; then : + as_fn_error $? "${a} backend needs lua but we cannot find it" "$LINENO" 5 + +fi + ;; + lmdb) + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the lmdb library and headers" >&5 +$as_echo_n "checking where to find the lmdb library and headers... " >&6; } + +# Check whether --with-lmdb was given. +if test "${with_lmdb+set}" = set; then : + withval=$with_lmdb; + with_lmdb=$withval + +else + + with_lmdb=auto + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_lmdb" >&5 +$as_echo "$with_lmdb" >&6; } + + if test "$with_lmdb" != "no"; then : + + if test "x$with_lmdb" = "xyes" -o "x$with_lmdb" = "xauto"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LMDB" >&5 +$as_echo_n "checking for LMDB... " >&6; } + +if test -n "$LMDB_CFLAGS"; then + pkg_cv_LMDB_CFLAGS="$LMDB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lmdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lmdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LMDB_CFLAGS=`$PKG_CONFIG --cflags "lmdb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LMDB_LIBS"; then + pkg_cv_LMDB_LIBS="$LMDB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lmdb\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lmdb") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LMDB_LIBS=`$PKG_CONFIG --libs "lmdb" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LMDB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lmdb" 2>&1` + else + LMDB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lmdb" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LMDB_PKG_ERRORS" >&5 + + + as_fn_error $? "lmdb not found via pkg-config, please install lmdb or set --with-lmdb to your lmdb installation directory" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + as_fn_error $? "lmdb not found via pkg-config, please install lmdb or set --with-lmdb to your lmdb installation directory" "$LINENO" 5 + +else + LMDB_CFLAGS=$pkg_cv_LMDB_CFLAGS + LMDB_LIBS=$pkg_cv_LMDB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +else + + save_CPPFLAGS=$CPPFLAGS + save_LIBS=$LIBS + if test -d "$with_lmdb/include"; then : + + LMDB_CFLAGS="-I$with_lmdb/include" + LMDB_LIBS="-L$with_lmdb/lib" + +else + + LMDB_CFLAGS="-I$with_lmdb" + LMDB_LIBS="-L$with_lmdb" + +fi + CPPFLAGS="$LMDB_CFLAGS" + LIBS="$LMDB_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing mdb_env_open" >&5 +$as_echo_n "checking for library containing mdb_env_open... " >&6; } +if ${ac_cv_search_mdb_env_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mdb_env_open (); +int +main () +{ +return mdb_env_open (); + ; + return 0; +} +_ACEOF +for ac_lib in '' lmdb; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_mdb_env_open=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_mdb_env_open+:} false; then : + break +fi +done +if ${ac_cv_search_mdb_env_open+:} false; then : + +else + ac_cv_search_mdb_env_open=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_mdb_env_open" >&5 +$as_echo "$ac_cv_search_mdb_env_open" >&6; } +ac_res=$ac_cv_search_mdb_env_open +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + for ac_header in lmdb.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "lmdb.h" "ac_cv_header_lmdb_h" "$ac_includes_default" +if test "x$ac_cv_header_lmdb_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LMDB_H 1 +_ACEOF + + LMDB_LIBS="$LMDB_LIBS $ac_cv_search_mdb_env_open" + +else + + as_fn_error $? "lmdb headers not found in $with_lmdb" "$LINENO" 5 + +fi + +done + + CPPFLAGS="$save_CPPFLAGS" + LIBS="$save_LIBS" + + + +fi + + +fi + +else + + as_fn_error $? "--with-lmdb is set to 'no', but lmdb support is required" "$LINENO" 5 + +fi + + if test x"$boost_cv_inc_path" = xno; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost serialization library" >&5 +$as_echo "$as_me: Boost not available, not searching for the Boost serialization library" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test x"" = "xno"; then : + not_found_header='true' +fi +if test x"$boost_cv_inc_path" = xno; then + $not_found_header +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_mongrel "$LINENO" "boost/archive/text_oarchive.hpp" "ac_cv_header_boost_archive_text_oarchive_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_archive_text_oarchive_hpp" = xyes; then : + +$as_echo "#define HAVE_BOOST_ARCHIVE_TEXT_OARCHIVE_HPP 1" >>confdefs.h + +else + $not_found_header +fi + + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Boost serialization library" >&5 +$as_echo_n "checking for the Boost serialization library... " >&6; } +if ${boost_cv_lib_serialization+:} false; then : + $as_echo_n "(cached) " >&6 +else + boost_cv_lib_serialization=no + case "" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[sgpn]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + as_fn_error $? "the libext variable is empty, did you invoke Libtool?" "$LINENO" 5 + boost_save_ac_objext=$ac_objext + # Generate the test file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o); + ; + return 0; +} +_ACEOF + if ac_fn_cxx_try_compile "$LINENO"; then : + ac_objext=do_not_rm_me_plz +else + if test x"" != x"no"; then : + + as_fn_error $? "cannot compile a test that uses Boost serialization" "$LINENO" 5 + +fi + +fi +rm -f core conftest.err conftest.$ac_objext + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in serialization; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_full_suffix in \ + $boost_last_suffix \ + x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_mt_$boost_ver_ \ + x$boost_tag_$boost_ver_ + do + boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` + boost_lib="boost_$boost_lib_$boost_real_suffix" + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + boost_cv_lib_serialization_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$boost_cv_lib_serialization_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + boost_cv_lib_serialization_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$boost_cv_lib_serialization_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_cv_lib_serialization=yes +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_cv_lib_serialization=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$boost_cv_lib_serialization" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + if ${boost_cv_rpath_link_ldflag+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_cv_lib_serialization_LIBS $boost_save_LIBS" + rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + $as_echo "$as_me:${as_lineno-$LINENO}: re-using the existing conftest.$ac_objext" >&5 +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext + }; then : + boost_rpath_link_ldflag_found=yes + break +else + if $boost_use_source; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + fi + boost_rpath_link_ldflag_found=no +fi +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext + done + ;; + esac + if test "x$boost_rpath_link_ldflag_found" != "xyes"; then : + as_fn_error $? "Unable to determine whether to use -R or -rpath" "$LINENO" 5 +fi + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + +fi + + test x"$boost_ldpath" != x && + boost_cv_lib_serialization_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + boost_cv_lib_serialization_LDPATH="$boost_ldpath" + boost_last_suffix="$boost_full_suffix" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $boost_cv_lib_serialization" >&5 +$as_echo "$boost_cv_lib_serialization" >&6; } +case $boost_cv_lib_serialization in #( + (yes) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +$as_echo "#define HAVE_BOOST_SERIALIZATION 1" >>confdefs.h + BOOST_SERIALIZATION_LDFLAGS=$boost_cv_lib_serialization_LDFLAGS + BOOST_SERIALIZATION_LDPATH=$boost_cv_lib_serialization_LDPATH + BOOST_LDPATH=$boost_cv_lib_serialization_LDPATH + BOOST_SERIALIZATION_LIBS=$boost_cv_lib_serialization_LIBS + ;; + (no) $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + if test x"" != "xno"; then : + + as_fn_error $? "cannot find flags to link with the Boost serialization library (libboost-serialization)" "$LINENO" 5 + +fi + ;; +esac +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + + + + ;; + esac +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ZeroMQ connector in remotebackend" >&5 +$as_echo_n "checking whether to enable ZeroMQ connector in remotebackend... " >&6; } + # Check whether --enable-remotebackend_zeromq was given. +if test "${enable_remotebackend_zeromq+set}" = set; then : + enableval=$enable_remotebackend_zeromq; enable_remotebackend_zeromq=$enableval +else + enable_remotebackend_zeromq=no + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_remotebackend_zeromq" >&5 +$as_echo "$enable_remotebackend_zeromq" >&6; } + + if test "x$enable_remotebackend_zeromq" != "xno"; then + REMOTEBACKEND_ZEROMQ_TRUE= + REMOTEBACKEND_ZEROMQ_FALSE='#' +else + REMOTEBACKEND_ZEROMQ_TRUE='#' + REMOTEBACKEND_ZEROMQ_FALSE= +fi + + + + if test "x$enable_remotebackend_zeromq" != "xno"; then : + + if test "x$have_remotebackend" = "xyes"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBZMQ" >&5 +$as_echo_n "checking for LIBZMQ... " >&6; } + +if test -n "$LIBZMQ_CFLAGS"; then + pkg_cv_LIBZMQ_CFLAGS="$LIBZMQ_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzmq\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libzmq") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBZMQ_CFLAGS=`$PKG_CONFIG --cflags "libzmq" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBZMQ_LIBS"; then + pkg_cv_LIBZMQ_LIBS="$LIBZMQ_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzmq\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libzmq") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBZMQ_LIBS=`$PKG_CONFIG --libs "libzmq" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBZMQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzmq" 2>&1` + else + LIBZMQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzmq" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBZMQ_PKG_ERRORS" >&5 + + as_fn_error $? "Could not find libzmq" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Could not find libzmq" "$LINENO" 5 + +else + LIBZMQ_CFLAGS=$pkg_cv_LIBZMQ_CFLAGS + LIBZMQ_LIBS=$pkg_cv_LIBZMQ_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +$as_echo "#define HAVE_LIBZMQ 1" >>confdefs.h + + +$as_echo "#define REMOTEBACKEND_ZEROMQ 1" >>confdefs.h + + REMOTEBACKEND_ZEROMQ=yes + +fi + + old_CXXFLAGS="$CXXFLAGS" + old_LDFLAGS="$LDFLAGS" + CXXFLAGS="$CFLAGS $LIBZMQ_CFLAGS" + LDFLAGS="$LDFLAGS $LIBZMQ_LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zmq_msg_send in -lzmq" >&5 +$as_echo_n "checking for zmq_msg_send in -lzmq... " >&6; } +if ${ac_cv_lib_zmq_zmq_msg_send+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lzmq $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zmq_msg_send (); +int +main () +{ +return zmq_msg_send (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_zmq_zmq_msg_send=yes +else + ac_cv_lib_zmq_zmq_msg_send=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zmq_zmq_msg_send" >&5 +$as_echo "$ac_cv_lib_zmq_zmq_msg_send" >&6; } +if test "x$ac_cv_lib_zmq_zmq_msg_send" = xyes; then : + + +$as_echo "#define HAVE_ZMQ_MSG_SEND 1" >>confdefs.h + + + +fi + + CXXFLAGS="$old_CXXFLAGS" + LDFLAGS="$old_LDFLAGS" + +else + as_fn_error $? "remotebackend \"zeromq\" selected but the \"remote\" backend itself is not selected. Please add \"remote\" to your modules or dynmodules list and re-run configure!" "$LINENO" 5 + +fi + + +fi + + + + if test -n "$HAVE_LIBCURL"; then : + : +else + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --with-libcurl was given. +if test "${with_libcurl+set}" = set; then : + withval=$with_libcurl; _libcurl_with=$withval +else + _libcurl_with="yes" +fi + + + if test "$_libcurl_with" != "no" ; then + + for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[1]+256*A[2]+A[3]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + # Extract the first word of "curl-config", so it can be a program name with args. +set dummy curl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path__libcurl_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $_libcurl_config in + [\\/]* | ?:[\\/]*) + ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in "$withval/bin" +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path__libcurl_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +_libcurl_config=$ac_cv_path__libcurl_config +if test -n "$_libcurl_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 +$as_echo "$_libcurl_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + # Extract the first word of "curl-config", so it can be a program name with args. +set dummy curl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path__libcurl_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $_libcurl_config in + [\\/]* | ?:[\\/]*) + ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path__libcurl_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +_libcurl_config=$ac_cv_path__libcurl_config +if test -n "$_libcurl_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 +$as_echo "$_libcurl_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi + + if test x$_libcurl_config != "x" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the version of libcurl" >&5 +$as_echo_n "checking for the version of libcurl... " >&6; } +if ${libcurl_cv_lib_curl_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $2}'` +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_version" >&5 +$as_echo "$libcurl_cv_lib_curl_version" >&6; } + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo "7.21.3" | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcurl >= version \"7.21.3\"" >&5 +$as_echo_n "checking for libcurl >= version \"7.21.3\"... " >&6; } +if ${libcurl_cv_lib_version_ok+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_version_ok" >&5 +$as_echo "$libcurl_cv_lib_version_ok" >&6; } + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libcurl is usable" >&5 +$as_echo_n "checking whether libcurl is usable... " >&6; } +if ${libcurl_cv_lib_curl_usable+:} false; then : + $as_echo_n "(cached) " >&6 +else + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_WRITEDATA; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +if (x) {;} + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + libcurl_cv_lib_curl_usable=yes +else + libcurl_cv_lib_curl_usable=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_usable" >&5 +$as_echo "$libcurl_cv_lib_curl_usable" >&6; } + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + ac_fn_cxx_check_func "$LINENO" "curl_free" "ac_cv_func_curl_free" +if test "x$ac_cv_func_curl_free" = xyes; then : + +else + +$as_echo "#define curl_free free" >>confdefs.h + +fi + + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + +$as_echo "#define HAVE_LIBCURL 1" >>confdefs.h + + + + + for _libcurl_feature in $_libcurl_features ; do + cat >>confdefs.h <<_ACEOF +#define `$as_echo "libcurl_feature_$_libcurl_feature" | $as_tr_cpp` 1 +_ACEOF + + eval `$as_echo "libcurl_feature_$_libcurl_feature" | $as_tr_sh`=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 (0x070b00 == 461568) + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + + # RTSP, IMAP, POP3 and SMTP were added in + # 7.20.0 (0x071400 == 463872) + if test $_libcurl_version -ge 463872; then + _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + cat >>confdefs.h <<_ACEOF +#define `$as_echo "libcurl_protocol_$_libcurl_protocol" | $as_tr_cpp` 1 +_ACEOF + + eval `$as_echo "libcurl_protocol_$_libcurl_protocol" | $as_tr_sh`=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + HAVE_LIBCURL=n + else + # This is the IF-YES path + HAVE_LIBCURL=y + fi + + unset _libcurl_with + + +fi + if test "$HAVE_LIBCURL" = "y"; then + HAVE_LIBCURL_TRUE= + HAVE_LIBCURL_FALSE='#' +else + HAVE_LIBCURL_TRUE='#' + HAVE_LIBCURL_FALSE= +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will be building and installing the extra tools" >&5 +$as_echo_n "checking whether we will be building and installing the extra tools... " >&6; } + # Check whether --enable-tools was given. +if test "${enable_tools+set}" = set; then : + enableval=$enable_tools; enable_tools=$enableval +else + enable_tools=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_tools" >&5 +$as_echo "$enable_tools" >&6; } + + if test "x$enable_tools" != "xno"; then + TOOLS_TRUE= + TOOLS_FALSE='#' +else + TOOLS_TRUE='#' + TOOLS_FALSE= +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will be building ixfrdist" >&5 +$as_echo_n "checking whether we will be building ixfrdist... " >&6; } + # Check whether --enable-ixfrdist was given. +if test "${enable_ixfrdist+set}" = set; then : + enableval=$enable_ixfrdist; + enable_ixfrdist=$enableval + +else + + enable_ixfrdist=no + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ixfrdist" >&5 +$as_echo "$enable_ixfrdist" >&6; } + if test "x$enable_ixfrdist" != "xno"; then + IXFRDIST_TRUE= + IXFRDIST_FALSE='#' +else + IXFRDIST_TRUE='#' + IXFRDIST_FALSE= +fi + + if test "x$enable_ixfrdist" != "xno"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for YAML" >&5 +$as_echo_n "checking for YAML... " >&6; } + +if test -n "$YAML_CFLAGS"; then + pkg_cv_YAML_CFLAGS="$YAML_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yaml-cpp >= 0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "yaml-cpp >= 0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_YAML_CFLAGS=`$PKG_CONFIG --cflags "yaml-cpp >= 0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$YAML_LIBS"; then + pkg_cv_YAML_LIBS="$YAML_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"yaml-cpp >= 0.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "yaml-cpp >= 0.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_YAML_LIBS=`$PKG_CONFIG --libs "yaml-cpp >= 0.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + YAML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "yaml-cpp >= 0.5" 2>&1` + else + YAML_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "yaml-cpp >= 0.5" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$YAML_PKG_ERRORS" >&5 + + + as_fn_error $? "Could not find yaml-cpp >= 0.5, required for ixfrdist" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + as_fn_error $? "Could not find yaml-cpp >= 0.5, required for ixfrdist" "$LINENO" 5 + +else + YAML_CFLAGS=$pkg_cv_YAML_CFLAGS + YAML_LIBS=$pkg_cv_YAML_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we need to link in protobuf" >&5 +$as_echo_n "checking if we need to link in protobuf... " >&6; } + +# Check whether --with-protobuf was given. +if test "${with_protobuf+set}" = set; then : + withval=$with_protobuf; with_protobuf=$withval +else + with_protobuf=auto +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_protobuf" >&5 +$as_echo "$with_protobuf" >&6; } + + if test "x$with_protobuf" != "xno"; then : + + if test "x$with_protobuf" = "xyes" -o "x$with_protobuf" = "xauto"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTOBUF" >&5 +$as_echo_n "checking for PROTOBUF... " >&6; } + +if test -n "$PROTOBUF_CFLAGS"; then + pkg_cv_PROTOBUF_CFLAGS="$PROTOBUF_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "protobuf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PROTOBUF_CFLAGS=`$PKG_CONFIG --cflags "protobuf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PROTOBUF_LIBS"; then + pkg_cv_PROTOBUF_LIBS="$PROTOBUF_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf\""; } >&5 + ($PKG_CONFIG --exists --print-errors "protobuf") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PROTOBUF_LIBS=`$PKG_CONFIG --libs "protobuf" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PROTOBUF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "protobuf" 2>&1` + else + PROTOBUF_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "protobuf" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PROTOBUF_PKG_ERRORS" >&5 + + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +else + PROTOBUF_CFLAGS=$pkg_cv_PROTOBUF_CFLAGS + PROTOBUF_LIBS=$pkg_cv_PROTOBUF_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + # Extract the first word of "protoc", so it can be a program name with args. +set dummy protoc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PROTOC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PROTOC"; then + ac_cv_prog_PROTOC="$PROTOC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PROTOC="protoc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PROTOC=$ac_cv_prog_PROTOC +if test -n "$PROTOC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROTOC" >&5 +$as_echo "$PROTOC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +fi + +fi + if test "x$with_protobuf" = "xyes"; then : + + if test x"$PROTOBUF_LIBS" = "x"; then : + + as_fn_error $? "Protobuf requested but libraries were not found" "$LINENO" 5 + +fi + if test x"$PROTOC" = "x"; then : + + as_fn_error $? "Protobuf requested but the protobuf compiler was not found" "$LINENO" 5 + +fi + +fi + if test x"$PROTOBUF_LIBS" != "x"; then + HAVE_PROTOBUF_TRUE= + HAVE_PROTOBUF_FALSE='#' +else + HAVE_PROTOBUF_TRUE='#' + HAVE_PROTOBUF_FALSE= +fi + + if test x"$PROTOC" != "x"; then + HAVE_PROTOC_TRUE= + HAVE_PROTOC_FALSE='#' +else + HAVE_PROTOC_TRUE='#' + HAVE_PROTOC_FALSE= +fi + + if test x"$PROTOBUF_LIBS" != "x"; then : + +$as_echo "#define HAVE_PROTOBUF 1" >>confdefs.h + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we will enable LUA records" >&5 +$as_echo_n "checking whether we will enable LUA records... " >&6; } + + # Check whether --enable-lua-records was given. +if test "${enable_lua_records+set}" = set; then : + enableval=$enable_lua_records; enable_lua_records=$enableval +else + enable_lua_records=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_lua_records" >&5 +$as_echo "$enable_lua_records" >&6; } + + if test "x$enable_lua_records" != "xno"; then : + + if test "x$LUAPC" = "x"; then : + as_fn_error $? "LUA records need LUA. You can disable this feature with the --disable-lua-records switch or configure a proper LUA installation." "$LINENO" 5 + +fi + if test "$HAVE_LIBCURL" != "y"; then : + + as_fn_error $? "libcurl minimum version requirement not met. This is required for LUA records. You can disable it with the --disable-lua-records switch or use --with-libcurl to select another curl installation." "$LINENO" 5 + +fi + + +$as_echo "#define HAVE_LUA_RECORDS 1" >>confdefs.h + + +fi + if test "x$enable_lua_records" != "xno"; then + HAVE_LUA_RECORDS_TRUE= + HAVE_LUA_RECORDS_FALSE='#' +else + HAVE_LUA_RECORDS_TRUE='#' + HAVE_LUA_RECORDS_FALSE= +fi + + + + if test "x$needoracle" = "xyes"; then + ORACLE_TRUE= + ORACLE_FALSE='#' +else + ORACLE_TRUE='#' + ORACLE_FALSE= +fi + + + if test "x$needldap" = "xyes"; then + LDAP_TRUE= + LDAP_FALSE='#' +else + LDAP_TRUE='#' + LDAP_FALSE= +fi + + + + if test "x$needsqlite3" = "xyes"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLITE3" >&5 +$as_echo_n "checking for SQLITE3... " >&6; } + +if test -n "$SQLITE3_CFLAGS"; then + pkg_cv_SQLITE3_CFLAGS="$SQLITE3_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SQLITE3_CFLAGS=`$PKG_CONFIG --cflags "sqlite3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SQLITE3_LIBS"; then + pkg_cv_SQLITE3_LIBS="$SQLITE3_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SQLITE3_LIBS=`$PKG_CONFIG --libs "sqlite3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SQLITE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3" 2>&1` + else + SQLITE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SQLITE3_PKG_ERRORS" >&5 + + as_fn_error $? "Could not find libsqlite3" "$LINENO" 5 + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Could not find libsqlite3" "$LINENO" 5 + +else + SQLITE3_CFLAGS=$pkg_cv_SQLITE3_CFLAGS + SQLITE3_LIBS=$pkg_cv_SQLITE3_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SQLITE3 1" >>confdefs.h + +fi + +fi + + if test "x$needsqlite3" = "xyes"; then + SQLITE3_TRUE= + SQLITE3_FALSE='#' +else + SQLITE3_TRUE='#' + SQLITE3_FALSE= +fi + + +for a in $modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can build module \"${a}\"" >&5 +$as_echo_n "checking whether we can build module \"${a}\"... " >&6; } + if [ -d "$srcdir/modules/${a}backend" ]; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + moduledirs="$moduledirs ${a}backend" + + for b in `cat $srcdir/modules/${a}backend/OBJECTFILES`; do + moduleobjects="$moduleobjects ../modules/${a}backend/$b" + done + modulelibs="$modulelibs `cat $srcdir/modules/${a}backend/OBJECTLIBS`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Do not know how to build module \"$a\", \"$srcdir/modules/${a}backend\" does not exist! Please review --with-modules parameter for supported values." "$LINENO" 5 + fi +done + +for a in $dynmodules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can build dynamic module \"${a}\"" >&5 +$as_echo_n "checking whether we can build dynamic module \"${a}\"... " >&6; } + if [ -d "$srcdir/modules/${a}backend" ]; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + moduledirs="$moduledirs ${a}backend" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "Do not know how to build module \"$a\", \"$srcdir/modules/${a}backend\" does not exist! Please review --with-dynmodules parameter for supported values." "$LINENO" 5 + fi +done + + + + +# Check whether --enable-systemd was given. +if test "${enable_systemd+set}" = set; then : + enableval=$enable_systemd; +fi + + +if test "x$enable_systemd" = "xno"; then : + + ax_cv_systemd="n" + +elif test "x$enable_systemd" = "xyes"; then : + + ax_cv_systemd="y" + +elif test -z $ax_cv_systemd; then : + + ax_cv_systemd="n" + +fi +systemd=$ax_cv_systemd + + + + +# Check whether --with-systemd was given. +if test "${with_systemd+set}" = set; then : + withval=$with_systemd; SYSTEMD_DIR="$withval" +else + SYSTEMD_DIR="" +fi + + + + +# Check whether --with-systemd was given. +if test "${with_systemd+set}" = set; then : + withval=$with_systemd; SYSTEMD_MODULES_LOAD="$withval" +else + SYSTEMD_MODULES_LOAD="" +fi + + + + + + ac_fn_cxx_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default" +if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then : + + for libname in systemd-daemon systemd; do + as_ac_Lib=`$as_echo "ac_cv_lib_$libname''_sd_listen_fds" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sd_listen_fds in -l$libname" >&5 +$as_echo_n "checking for sd_listen_fds in -l$libname... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$libname $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sd_listen_fds (); +int +main () +{ +return sd_listen_fds (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + + libsystemd_daemon="lib$libname" + systemd=y + libsystemd=y + +fi + + done + +fi + + + + + if test "x$enable_systemd" != "xno"; then : + + if test "x$systemd" = "xy" ; then : + + +$as_echo "#define HAVE_SYSTEMD 1" >>confdefs.h + + systemd=y + + + if test "x$libsystemd" = x; then : + + as_fn_error $? "Unable to find a suitable libsystemd library" "$LINENO" 5 + +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5 +$as_echo_n "checking for SYSTEMD... " >&6; } + +if test -n "$SYSTEMD_CFLAGS"; then + pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libsystemd_daemon\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$libsystemd_daemon") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "$libsystemd_daemon" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SYSTEMD_LIBS"; then + pkg_cv_SYSTEMD_LIBS="$SYSTEMD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$libsystemd_daemon\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$libsystemd_daemon") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SYSTEMD_LIBS=`$PKG_CONFIG --libs "$libsystemd_daemon" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$libsystemd_daemon" 2>&1` + else + SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$libsystemd_daemon" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SYSTEMD_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($libsystemd_daemon) were not met: + +$SYSTEMD_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables SYSTEMD_CFLAGS +and SYSTEMD_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables SYSTEMD_CFLAGS +and SYSTEMD_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + SYSTEMD_CFLAGS=$pkg_cv_SYSTEMD_CFLAGS + SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + + if test "x$SYSTEMD_DIR" = x; then : + + SYSTEMD_DIR="\$(prefix)/lib/systemd/system/" + +fi + + if test "x$SYSTEMD_DIR" = x; then : + + as_fn_error $? "SYSTEMD_DIR is unset" "$LINENO" 5 + +fi + + if test "x$SYSTEMD_MODULES_LOAD" = x; then : + + SYSTEMD_MODULES_LOAD="\$(prefix)/lib/modules-load.d/" + +fi + + if test "x$SYSTEMD_MODULES_LOAD" = x; then : + + as_fn_error $? "SYSTEMD_MODULES_LOAD is unset" "$LINENO" 5 + +fi + + +else + systemd=n +fi + +else + systemd=n +fi + + + + if test x"$systemd" = "xy"; then : + + # Extract the first word of "systemctl", so it can be a program name with args. +set dummy systemctl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SYSTEMCTL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SYSTEMCTL in + [\\/]* | ?:[\\/]*) + ac_cv_path_SYSTEMCTL="$SYSTEMCTL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SYSTEMCTL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SYSTEMCTL" && ac_cv_path_SYSTEMCTL="no" + ;; +esac +fi +SYSTEMCTL=$ac_cv_path_SYSTEMCTL +if test -n "$SYSTEMCTL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYSTEMCTL" >&5 +$as_echo "$SYSTEMCTL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$SYSTEMCTL" = "no"; then : + as_fn_error $? "systemctl not found" "$LINENO" 5 +else + + _systemd_version=`${SYSTEMCTL} --version|head -1 |cut -d" " -f 2` + if test $_systemd_version -ge 183; then + systemd_private_tmp=y + fi + if test $_systemd_version -ge 209; then + systemd_system_call_architectures=y + systemd_private_devices=y + fi + if test $_systemd_version -ge 211; then + systemd_restrict_address_families=y + fi + if test $_systemd_version -ge 214; then + systemd_protect_system=y + systemd_protect_home=y + fi + if test $_systemd_version -ge 231; then + systemd_restrict_realtime=y + systemd_memory_deny_write_execute=y + fi + if test $_systemd_version -ge 232; then + systemd_protect_control_groups=y + systemd_protect_kernel_modules=y + systemd_protect_kernel_tunables=y + systemd_remove_ipc=y + systemd_dynamic_user=y + systemd_private_users=y + systemd_protect_system_strict=y + fi + if test $_systemd_version -ge 233; then + systemd_restrict_namespaces=y + fi + if test $_systemd_version -ge 235; then + systemd_lock_personality=y + # while SystemCallFilter is technically available starting with 187, + # we use the pre-defined call filter sets that have been introduced later. + # Initial support for these landed in 231 + # @filesystem @reboot @swap in 233 + # @aio, @sync, @chown, @setuid, @memlock, @signal and @timer in 235 + systemd_system_call_filter=y + fi + +fi + +fi + if test x"$systemd_dynamic_user" = "xy" ; then + HAVE_SYSTEMD_DYNAMIC_USER_TRUE= + HAVE_SYSTEMD_DYNAMIC_USER_FALSE='#' +else + HAVE_SYSTEMD_DYNAMIC_USER_TRUE='#' + HAVE_SYSTEMD_DYNAMIC_USER_FALSE= +fi + + if test x"$systemd_lock_personality" = "xy" ; then + HAVE_SYSTEMD_LOCK_PERSONALITY_TRUE= + HAVE_SYSTEMD_LOCK_PERSONALITY_FALSE='#' +else + HAVE_SYSTEMD_LOCK_PERSONALITY_TRUE='#' + HAVE_SYSTEMD_LOCK_PERSONALITY_FALSE= +fi + + if test x"$systemd_memory_deny_write_execute" = "xy" ; then + HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_TRUE= + HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_FALSE='#' +else + HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_TRUE='#' + HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_FALSE= +fi + + if test x"$systemd_private_devices" = "xy" ; then + HAVE_SYSTEMD_PRIVATE_DEVICES_TRUE= + HAVE_SYSTEMD_PRIVATE_DEVICES_FALSE='#' +else + HAVE_SYSTEMD_PRIVATE_DEVICES_TRUE='#' + HAVE_SYSTEMD_PRIVATE_DEVICES_FALSE= +fi + + if test x"$systemd_private_tmp" = "xy" ; then + HAVE_SYSTEMD_PRIVATE_TMP_TRUE= + HAVE_SYSTEMD_PRIVATE_TMP_FALSE='#' +else + HAVE_SYSTEMD_PRIVATE_TMP_TRUE='#' + HAVE_SYSTEMD_PRIVATE_TMP_FALSE= +fi + + if test x"$systemd_private_users" = "xy" ; then + HAVE_SYSTEMD_PRIVATE_USERS_TRUE= + HAVE_SYSTEMD_PRIVATE_USERS_FALSE='#' +else + HAVE_SYSTEMD_PRIVATE_USERS_TRUE='#' + HAVE_SYSTEMD_PRIVATE_USERS_FALSE= +fi + + if test x"$systemd_protect_control_groups" = "xy" ; then + HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_TRUE= + HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_TRUE='#' + HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_FALSE= +fi + + if test x"$systemd_protect_home" = "xy" ; then + HAVE_SYSTEMD_PROTECT_HOME_TRUE= + HAVE_SYSTEMD_PROTECT_HOME_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_HOME_TRUE='#' + HAVE_SYSTEMD_PROTECT_HOME_FALSE= +fi + + if test x"$systemd_protect_kernel_modules" = "xy" ; then + HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_TRUE= + HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_TRUE='#' + HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_FALSE= +fi + + if test x"$systemd_protect_kernel_tunables" = "xy" ; then + HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_TRUE= + HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_TRUE='#' + HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_FALSE= +fi + + if test x"$systemd_protect_system" = "xy" ; then + HAVE_SYSTEMD_PROTECT_SYSTEM_TRUE= + HAVE_SYSTEMD_PROTECT_SYSTEM_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_SYSTEM_TRUE='#' + HAVE_SYSTEMD_PROTECT_SYSTEM_FALSE= +fi + + if test x"$systemd_protect_system_strict" = "xy" ; then + HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_TRUE= + HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_FALSE='#' +else + HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_TRUE='#' + HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_FALSE= +fi + + if test x"$systemd_remove_ipc" = "xy" ; then + HAVE_SYSTEMD_REMOVE_IPC_TRUE= + HAVE_SYSTEMD_REMOVE_IPC_FALSE='#' +else + HAVE_SYSTEMD_REMOVE_IPC_TRUE='#' + HAVE_SYSTEMD_REMOVE_IPC_FALSE= +fi + + if test x"$systemd_restrict_address_families" = "xy" ; then + HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_TRUE= + HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_FALSE='#' +else + HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_TRUE='#' + HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_FALSE= +fi + + if test x"$systemd_restrict_namespaces" = "xy" ; then + HAVE_SYSTEMD_RESTRICT_NAMESPACES_TRUE= + HAVE_SYSTEMD_RESTRICT_NAMESPACES_FALSE='#' +else + HAVE_SYSTEMD_RESTRICT_NAMESPACES_TRUE='#' + HAVE_SYSTEMD_RESTRICT_NAMESPACES_FALSE= +fi + + if test x"$systemd_restrict_realtime" = "xy" ; then + HAVE_SYSTEMD_RESTRICT_REALTIME_TRUE= + HAVE_SYSTEMD_RESTRICT_REALTIME_FALSE='#' +else + HAVE_SYSTEMD_RESTRICT_REALTIME_TRUE='#' + HAVE_SYSTEMD_RESTRICT_REALTIME_FALSE= +fi + + if test x"$systemd_system_call_architectures" = "xy" ; then + HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_TRUE= + HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_FALSE='#' +else + HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_TRUE='#' + HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_FALSE= +fi + + if test x"$systemd_system_call_filter" = "xy" ; then + HAVE_SYSTEMD_SYSTEM_CALL_FILTER_TRUE= + HAVE_SYSTEMD_SYSTEM_CALL_FILTER_FALSE='#' +else + HAVE_SYSTEMD_SYSTEM_CALL_FILTER_TRUE='#' + HAVE_SYSTEMD_SYSTEM_CALL_FILTER_FALSE= +fi + + + if test x"$systemd" = "xy" ; then + HAVE_SYSTEMD_TRUE= + HAVE_SYSTEMD_FALSE='#' +else + HAVE_SYSTEMD_TRUE='#' + HAVE_SYSTEMD_FALSE= +fi + + +LDFLAGS="$RELRO_LDFLAGS $LDFLAGS" + +CFLAGS="$PIE_CFLAGS $CFLAGS" +CXXFLAGS="$PIE_CFLAGS $CXXFLAGS" +PROGRAM_LDFLAGS="$PIE_LDFLAGS $PROGRAM_LDFLAGS" + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable code coverage" >&5 +$as_echo_n "checking whether to enable code coverage... " >&6; } + # Check whether --enable-coverage was given. +if test "${enable_coverage+set}" = set; then : + enableval=$enable_coverage; enable_coverage=$enableval +else + enable_coverage=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_coverage" >&5 +$as_echo "$enable_coverage" >&6; } + if test "x$enable_coverage" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fprofile-arcs -ftest-coverage" >&5 +$as_echo_n "checking whether C++ compiler handles -fprofile-arcs -ftest-coverage... " >&6; } +if ${gl_cv_warn_cxx__fprofile_arcs__ftest_coverage+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fprofile-arcs -ftest-coverage" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fprofile_arcs__ftest_coverage=yes +else + gl_cv_warn_cxx__fprofile_arcs__ftest_coverage=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fprofile_arcs__ftest_coverage" >&5 +$as_echo "$gl_cv_warn_cxx__fprofile_arcs__ftest_coverage" >&6; } +if test "x$gl_cv_warn_cxx__fprofile_arcs__ftest_coverage" = xyes; then : + + CXXFLAGS="$CXXFLAGS -U_FORTIFY_SOURCE -g -O0 -fprofile-arcs -ftest-coverage" + +else + + as_fn_error $? "$CXX does not support gathering coverage data" "$LINENO" 5 + +fi + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable AddressSanitizer" >&5 +$as_echo_n "checking whether to enable AddressSanitizer... " >&6; } + # Check whether --enable-asan was given. +if test "${enable_asan+set}" = set; then : + enableval=$enable_asan; enable_asan=$enableval +else + enable_asan=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_asan" >&5 +$as_echo "$enable_asan" >&6; } + + if test "x$enable_asan" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fsanitize=address" >&5 +$as_echo_n "checking whether C++ compiler handles -fsanitize=address... " >&6; } +if ${gl_cv_warn_cxx__fsanitize_address+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fsanitize=address" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fsanitize_address=yes +else + gl_cv_warn_cxx__fsanitize_address=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fsanitize_address" >&5 +$as_echo "$gl_cv_warn_cxx__fsanitize_address" >&6; } +if test "x$gl_cv_warn_cxx__fsanitize_address" = xyes; then : + + SANITIZER_FLAGS="-fsanitize=address $SANITIZER_FLAGS" + for ac_header in sanitizer/common_interface_defs.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sanitizer/common_interface_defs.h" "ac_cv_header_sanitizer_common_interface_defs_h" "$ac_includes_default" +if test "x$ac_cv_header_sanitizer_common_interface_defs_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H 1 +_ACEOF + asan_headers=yes +else + asan_headers=no +fi + +done + + if test x"$asan_headers" = "xyes" ; then : + ac_fn_cxx_check_decl "$LINENO" "__sanitizer_start_switch_fiber" "ac_cv_have_decl___sanitizer_start_switch_fiber" "#include + +" +if test "x$ac_cv_have_decl___sanitizer_start_switch_fiber" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the exact signature of __sanitizer_finish_switch_fiber" >&5 +$as_echo_n "checking for the exact signature of __sanitizer_finish_switch_fiber... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ + + __sanitizer_finish_switch_fiber(nullptr); + + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: a single pointer" >&5 +$as_echo "a single pointer" >&6; } + +$as_echo "#define HAVE_FIBER_SANITIZER 1" >>confdefs.h + + +$as_echo "#define HAVE_SANITIZER_FINISH_SWITCH_FIBER_SINGLE_PTR 1" >>confdefs.h + + +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ + + __sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr); + + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: three pointers" >&5 +$as_echo "three pointers" >&6; } + +$as_echo "#define HAVE_FIBER_SANITIZER 1" >>confdefs.h + + +$as_echo "#define HAVE_SANITIZER_FINISH_SWITCH_FIBER_THREE_PTRS 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 +$as_echo "unknown" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: ASAN fiber switching is not available due to an unknown API version" >&5 +$as_echo "$as_me: ASAN fiber switching is not available due to an unknown API version" >&6;} + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: ASAN fiber switching is not available" >&5 +$as_echo "$as_me: ASAN fiber switching is not available" >&6;} + +fi + + +fi + +else + as_fn_error $? "Cannot enable AddressSanitizer" "$LINENO" 5 + +fi + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MemorySanitizer" >&5 +$as_echo_n "checking whether to enable MemorySanitizer... " >&6; } + # Check whether --enable-msan was given. +if test "${enable_msan+set}" = set; then : + enableval=$enable_msan; enable_msan=$enableval +else + enable_msan=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_msan" >&5 +$as_echo "$enable_msan" >&6; } + + if test "x$enable_msan" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fsanitize=memory" >&5 +$as_echo_n "checking whether C++ compiler handles -fsanitize=memory... " >&6; } +if ${gl_cv_warn_cxx__fsanitize_memory+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fsanitize=memory" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fsanitize_memory=yes +else + gl_cv_warn_cxx__fsanitize_memory=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fsanitize_memory" >&5 +$as_echo "$gl_cv_warn_cxx__fsanitize_memory" >&6; } +if test "x$gl_cv_warn_cxx__fsanitize_memory" = xyes; then : + SANITIZER_FLAGS="-fsanitize=memory $SANITIZER_FLAGS" +else + as_fn_error $? "Cannot enable MemorySanitizer" "$LINENO" 5 + +fi + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ThreadSanitizer" >&5 +$as_echo_n "checking whether to enable ThreadSanitizer... " >&6; } + # Check whether --enable-tsan was given. +if test "${enable_tsan+set}" = set; then : + enableval=$enable_tsan; enable_tsan=$enableval +else + enable_tsan=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_tsan" >&5 +$as_echo "$enable_tsan" >&6; } + + if test "x$enable_tsan" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fsanitize=thread" >&5 +$as_echo_n "checking whether C++ compiler handles -fsanitize=thread... " >&6; } +if ${gl_cv_warn_cxx__fsanitize_thread+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fsanitize=thread" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fsanitize_thread=yes +else + gl_cv_warn_cxx__fsanitize_thread=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fsanitize_thread" >&5 +$as_echo "$gl_cv_warn_cxx__fsanitize_thread" >&6; } +if test "x$gl_cv_warn_cxx__fsanitize_thread" = xyes; then : + SANITIZER_FLAGS="-fsanitize=thread $SANITIZER_FLAGS" +else + as_fn_error $? "Cannot enable ThreadSanitizer" "$LINENO" 5 + +fi + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable LeakSanitizer" >&5 +$as_echo_n "checking whether to enable LeakSanitizer... " >&6; } + # Check whether --enable-lsan was given. +if test "${enable_lsan+set}" = set; then : + enableval=$enable_lsan; enable_lsan=$enableval +else + enable_lsan=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_lsan" >&5 +$as_echo "$enable_lsan" >&6; } + + if test "x$enable_lsan" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fsanitize=leak" >&5 +$as_echo_n "checking whether C++ compiler handles -fsanitize=leak... " >&6; } +if ${gl_cv_warn_cxx__fsanitize_leak+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fsanitize=leak" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fsanitize_leak=yes +else + gl_cv_warn_cxx__fsanitize_leak=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fsanitize_leak" >&5 +$as_echo "$gl_cv_warn_cxx__fsanitize_leak" >&6; } +if test "x$gl_cv_warn_cxx__fsanitize_leak" = xyes; then : + SANITIZER_FLAGS="-fsanitize=leak $SANITIZER_FLAGS" +else + as_fn_error $? "Cannot enable LeakSanitizer" "$LINENO" 5 + +fi + + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Undefined Behaviour Sanitizer" >&5 +$as_echo_n "checking whether to enable Undefined Behaviour Sanitizer... " >&6; } + # Check whether --enable-ubsan was given. +if test "${enable_ubsan+set}" = set; then : + enableval=$enable_ubsan; enable_ubsan=$enableval +else + enable_ubsan=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ubsan" >&5 +$as_echo "$enable_ubsan" >&6; } + + if test "x$enable_ubsan" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fsanitize=undefined" >&5 +$as_echo_n "checking whether C++ compiler handles -fsanitize=undefined... " >&6; } +if ${gl_cv_warn_cxx__fsanitize_undefined+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fsanitize=undefined" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fsanitize_undefined=yes +else + gl_cv_warn_cxx__fsanitize_undefined=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fsanitize_undefined" >&5 +$as_echo "$gl_cv_warn_cxx__fsanitize_undefined" >&6; } +if test "x$gl_cv_warn_cxx__fsanitize_undefined" = xyes; then : + SANITIZER_FLAGS="-fsanitize=undefined $SANITIZER_FLAGS" +else + as_fn_error $? "Cannot enable Undefined Behaviour Sanitizer" "$LINENO" 5 + +fi + + +fi + + + + if test "x$enable_asan" != "xno" -a "x$enable_tsan" != "xno"; then : + + as_fn_error $? "Address Sanitizer is not compatible with Thread Sanitizer" "$LINENO" 5 + +fi + + if test "x$enable_msan" != "xno" -a "x$enable_asan" != "xno"; then : + + as_fn_error $? "Memory Sanitizer is not compatible with Address Sanitizer" "$LINENO" 5 + +fi + + if test "x$enable_msan" != "xno" -a "x$enable_lsan" != "xno"; then : + + as_fn_error $? "Memory Sanitizer is not compatible with Leak Sanitizer" "$LINENO" 5 + +fi + + if test "x$enable_msan" != "xno" -a "x$enable_tsan" != "xno"; then : + + as_fn_error $? "Memory Sanitizer is not compatible with Thread Sanitizer" "$LINENO" 5 + +fi + + if test "x$enable_asan" != "xno" -o "x$enable_tsan" != "xno" -o "x$enable_lsan" != "xno" -o "x$enable_ubsan" != "xno" -o "x$enable_msan" != "xno"; then : + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler handles -fno-omit-frame-pointer" >&5 +$as_echo_n "checking whether C++ compiler handles -fno-omit-frame-pointer... " >&6; } +if ${gl_cv_warn_cxx__fno_omit_frame_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_compiler_FLAGS="$CXXFLAGS" + as_fn_append CXXFLAGS " $gl_unknown_warnings_are_errors -fno-omit-frame-pointer" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gl_cv_warn_cxx__fno_omit_frame_pointer=yes +else + gl_cv_warn_cxx__fno_omit_frame_pointer=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CXXFLAGS="$gl_save_compiler_FLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_warn_cxx__fno_omit_frame_pointer" >&5 +$as_echo "$gl_cv_warn_cxx__fno_omit_frame_pointer" >&6; } +if test "x$gl_cv_warn_cxx__fno_omit_frame_pointer" = xyes; then : + as_fn_append WARN_CFLAGS " -fno-omit-frame-pointer" +fi + + + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable code malloc-trace" >&5 +$as_echo_n "checking whether to enable code malloc-trace... " >&6; } + # Check whether --enable-malloc-trace was given. +if test "${enable_malloc_trace+set}" = set; then : + enableval=$enable_malloc_trace; enable_malloc_trace=$enableval +else + enable_malloc_trace=no + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_malloc_trace" >&5 +$as_echo "$enable_malloc_trace" >&6; } + if test "x$enable_malloc_trace" = "xyes"; then + MALLOC_TRACE_TRUE= + MALLOC_TRACE_FALSE='#' +else + MALLOC_TRACE_TRUE='#' + MALLOC_TRACE_FALSE= +fi + + if test "x$enable_malloc_trace" = "xyes"; then : + +$as_echo "#define MALLOC_TRACE 1" >>confdefs.h + +fi + + + + +AM_CPPFLAGS="-I\$(top_builddir) -I\$(top_srcdir) $THREADFLAGS $BOOST_CPPFLAGS" + + + +YAHTTP_CFLAGS='-I$(top_srcdir)/ext/yahttp' + +YAHTTP_LIBS='$(top_builddir)/ext/yahttp/yahttp/libyahttp.la' + +IPCRYPT_CFLAGS='-I$(top_srcdir)/ext/ipcrypt' + +IPCRYPT_LIBS='$(top_builddir)/ext/ipcrypt/libipcrypt.la' + + +CXXFLAGS="$SANITIZER_FLAGS $CXXFLAGS" + + +if test "x$PACKAGEVERSION" != "x"; then : + +cat >>confdefs.h <<_ACEOF +#define PACKAGEVERSION "$PACKAGEVERSION" +_ACEOF + + +fi + +export moduledirs moduleobjects modulelibs + +ac_config_files="$ac_config_files Makefile modules/Makefile pdns/Makefile codedocs/Makefile docs/Makefile pdns/pdns.init ext/Makefile ext/ipcrypt/Makefile ext/yahttp/Makefile ext/yahttp/yahttp/Makefile ext/json11/Makefile modules/bindbackend/Makefile modules/geoipbackend/Makefile modules/gmysqlbackend/Makefile modules/godbcbackend/Makefile modules/goraclebackend/Makefile modules/gpgsqlbackend/Makefile modules/gsqlite3backend/Makefile modules/ldapbackend/Makefile modules/lmdbbackend/Makefile modules/luabackend/Makefile modules/lua2backend/Makefile modules/mydnsbackend/Makefile modules/opendbxbackend/Makefile modules/oraclebackend/Makefile modules/pipebackend/Makefile modules/randombackend/Makefile modules/remotebackend/Makefile modules/tinydnsbackend/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_FREEBSD_TRUE}" && test -z "${HAVE_FREEBSD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_FREEBSD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LINUX_TRUE}" && test -z "${HAVE_LINUX_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SOLARIS_TRUE}" && test -z "${HAVE_SOLARIS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SOLARIS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LUA_TRUE}" && test -z "${LUA_FALSE}"; then + as_fn_error $? "conditional \"LUA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LUA_HPP_TRUE}" && test -z "${HAVE_LUA_HPP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LUA_HPP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LIBSODIUM_TRUE}" && test -z "${LIBSODIUM_FALSE}"; then + as_fn_error $? "conditional \"LIBSODIUM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LIBDECAF_TRUE}" && test -z "${LIBDECAF_FALSE}"; then + as_fn_error $? "conditional \"LIBDECAF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBCRYPTO_TRUE}" && test -z "${HAVE_LIBCRYPTO_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBCRYPTO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_BOOST_GE_148_TRUE}" && test -z "${HAVE_BOOST_GE_148_FALSE}"; then + as_fn_error $? "conditional \"HAVE_BOOST_GE_148\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${UNIT_TESTS_TRUE}" && test -z "${UNIT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"UNIT_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BACKEND_UNIT_TESTS_TRUE}" && test -z "${BACKEND_UNIT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BACKEND_UNIT_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${FUZZ_TARGETS_TRUE}" && test -z "${FUZZ_TARGETS_FALSE}"; then + as_fn_error $? "conditional \"FUZZ_TARGETS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_VIRTUALENV_TRUE}" && test -z "${HAVE_VIRTUALENV_FALSE}"; then + as_fn_error $? "conditional \"HAVE_VIRTUALENV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_MANPAGES_TRUE}" && test -z "${HAVE_MANPAGES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_MANPAGES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${FROM_GIT_TRUE}" && test -z "${FROM_GIT_FALSE}"; then + as_fn_error $? "conditional \"FROM_GIT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_RECVMMSG_TRUE}" && test -z "${HAVE_RECVMMSG_FALSE}"; then + as_fn_error $? "conditional \"HAVE_RECVMMSG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PKCS11_TRUE}" && test -z "${PKCS11_FALSE}"; then + as_fn_error $? "conditional \"PKCS11\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${GSS_TSIG_TRUE}" && test -z "${GSS_TSIG_FALSE}"; then + as_fn_error $? "conditional \"GSS_TSIG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${REMOTEBACKEND_ZEROMQ_TRUE}" && test -z "${REMOTEBACKEND_ZEROMQ_FALSE}"; then + as_fn_error $? "conditional \"REMOTEBACKEND_ZEROMQ\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBCURL_TRUE}" && test -z "${HAVE_LIBCURL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBCURL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${TOOLS_TRUE}" && test -z "${TOOLS_FALSE}"; then + as_fn_error $? "conditional \"TOOLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${IXFRDIST_TRUE}" && test -z "${IXFRDIST_FALSE}"; then + as_fn_error $? "conditional \"IXFRDIST\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PROTOBUF_TRUE}" && test -z "${HAVE_PROTOBUF_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PROTOBUF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PROTOC_TRUE}" && test -z "${HAVE_PROTOC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PROTOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LUA_RECORDS_TRUE}" && test -z "${HAVE_LUA_RECORDS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LUA_RECORDS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ORACLE_TRUE}" && test -z "${ORACLE_FALSE}"; then + as_fn_error $? "conditional \"ORACLE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LDAP_TRUE}" && test -z "${LDAP_FALSE}"; then + as_fn_error $? "conditional \"LDAP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SQLITE3_TRUE}" && test -z "${SQLITE3_FALSE}"; then + as_fn_error $? "conditional \"SQLITE3\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_DYNAMIC_USER_TRUE}" && test -z "${HAVE_SYSTEMD_DYNAMIC_USER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_DYNAMIC_USER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_LOCK_PERSONALITY_TRUE}" && test -z "${HAVE_SYSTEMD_LOCK_PERSONALITY_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_LOCK_PERSONALITY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_TRUE}" && test -z "${HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PRIVATE_DEVICES_TRUE}" && test -z "${HAVE_SYSTEMD_PRIVATE_DEVICES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PRIVATE_DEVICES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PRIVATE_TMP_TRUE}" && test -z "${HAVE_SYSTEMD_PRIVATE_TMP_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PRIVATE_TMP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PRIVATE_USERS_TRUE}" && test -z "${HAVE_SYSTEMD_PRIVATE_USERS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PRIVATE_USERS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_HOME_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_HOME_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_HOME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_KERNEL_MODULES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_SYSTEM_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_SYSTEM_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_SYSTEM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_TRUE}" && test -z "${HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_REMOVE_IPC_TRUE}" && test -z "${HAVE_SYSTEMD_REMOVE_IPC_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_REMOVE_IPC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_TRUE}" && test -z "${HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_RESTRICT_NAMESPACES_TRUE}" && test -z "${HAVE_SYSTEMD_RESTRICT_NAMESPACES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_RESTRICT_NAMESPACES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_RESTRICT_REALTIME_TRUE}" && test -z "${HAVE_SYSTEMD_RESTRICT_REALTIME_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_RESTRICT_REALTIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_TRUE}" && test -z "${HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_SYSTEM_CALL_FILTER_TRUE}" && test -z "${HAVE_SYSTEMD_SYSTEM_CALL_FILTER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD_SYSTEM_CALL_FILTER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SYSTEMD_TRUE}" && test -z "${HAVE_SYSTEMD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SYSTEMD\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MALLOC_TRACE_TRUE}" && test -z "${MALLOC_TRACE_FALSE}"; then + as_fn_error $? "conditional \"MALLOC_TRACE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by pdns $as_me 4.2.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +pdns config.status 4.2.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;; + "pdns/Makefile") CONFIG_FILES="$CONFIG_FILES pdns/Makefile" ;; + "codedocs/Makefile") CONFIG_FILES="$CONFIG_FILES codedocs/Makefile" ;; + "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; + "pdns/pdns.init") CONFIG_FILES="$CONFIG_FILES pdns/pdns.init" ;; + "ext/Makefile") CONFIG_FILES="$CONFIG_FILES ext/Makefile" ;; + "ext/ipcrypt/Makefile") CONFIG_FILES="$CONFIG_FILES ext/ipcrypt/Makefile" ;; + "ext/yahttp/Makefile") CONFIG_FILES="$CONFIG_FILES ext/yahttp/Makefile" ;; + "ext/yahttp/yahttp/Makefile") CONFIG_FILES="$CONFIG_FILES ext/yahttp/yahttp/Makefile" ;; + "ext/json11/Makefile") CONFIG_FILES="$CONFIG_FILES ext/json11/Makefile" ;; + "modules/bindbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/bindbackend/Makefile" ;; + "modules/geoipbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/geoipbackend/Makefile" ;; + "modules/gmysqlbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/gmysqlbackend/Makefile" ;; + "modules/godbcbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/godbcbackend/Makefile" ;; + "modules/goraclebackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/goraclebackend/Makefile" ;; + "modules/gpgsqlbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/gpgsqlbackend/Makefile" ;; + "modules/gsqlite3backend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/gsqlite3backend/Makefile" ;; + "modules/ldapbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/ldapbackend/Makefile" ;; + "modules/lmdbbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/lmdbbackend/Makefile" ;; + "modules/luabackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/luabackend/Makefile" ;; + "modules/lua2backend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/lua2backend/Makefile" ;; + "modules/mydnsbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/mydnsbackend/Makefile" ;; + "modules/opendbxbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/opendbxbackend/Makefile" ;; + "modules/oraclebackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/oraclebackend/Makefile" ;; + "modules/pipebackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/pipebackend/Makefile" ;; + "modules/randombackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/randombackend/Makefile" ;; + "modules/remotebackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/remotebackend/Makefile" ;; + "modules/tinydnsbackend/Makefile") CONFIG_FILES="$CONFIG_FILES modules/tinydnsbackend/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuration summary" >&5 +$as_echo "$as_me: Configuration summary" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: =====================" >&5 +$as_echo "$as_me: =====================" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configured with: $pdns_configure_args" >&5 +$as_echo "$as_me: Configured with: $pdns_configure_args" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: CC: $CC" >&5 +$as_echo "$as_me: CC: $CC" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: CXX: $CXX" >&5 +$as_echo "$as_me: CXX: $CXX" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: LD: $LD" >&5 +$as_echo "$as_me: LD: $LD" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: CFLAGS: $CFLAGS" >&5 +$as_echo "$as_me: CFLAGS: $CFLAGS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: CPPFLAGS: $CPPFLAGS" >&5 +$as_echo "$as_me: CPPFLAGS: $CPPFLAGS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: CXXFLAGS: $CXXFLAGS" >&5 +$as_echo "$as_me: CXXFLAGS: $CXXFLAGS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: LDFLAGS: $LDFLAGS" >&5 +$as_echo "$as_me: LDFLAGS: $LDFLAGS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: LIBS: $LIBS" >&5 +$as_echo "$as_me: LIBS: $LIBS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: BOOST_CPPFLAGS: $BOOST_CPPFLAGS" >&5 +$as_echo "$as_me: BOOST_CPPFLAGS: $BOOST_CPPFLAGS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Extras enabled" >&5 +$as_echo "$as_me: Extras enabled" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: --------------" >&5 +$as_echo "$as_me: --------------" >&6;} +if test "x$enable_tools" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: Tools: yes" >&5 +$as_echo "$as_me: Tools: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: Tools: no" >&5 +$as_echo "$as_me: Tools: no" >&6;} + +fi +if test "x$enable_ixfrdist" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: ixfrdist: yes" >&5 +$as_echo "$as_me: ixfrdist: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: ixfrdist: no" >&5 +$as_echo "$as_me: ixfrdist: no" >&6;} + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Server Features enabled" >&5 +$as_echo "$as_me: Server Features enabled" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: -----------------------" >&5 +$as_echo "$as_me: -----------------------" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Built-in modules: $modules" >&5 +$as_echo "$as_me: Built-in modules: $modules" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Dynamic modules: $dynmodules" >&5 +$as_echo "$as_me: Dynamic modules: $dynmodules" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} +if test "x$libcrypto_ecdsa" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: OpenSSL ecdsa: yes" >&5 +$as_echo "$as_me: OpenSSL ecdsa: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: OpenSSL ecdsa: no" >&5 +$as_echo "$as_me: OpenSSL ecdsa: no" >&6;} + +fi +if test "x$LIBSODIUM_LIBS" != "x" || test "x$LIBDECAF_LIBS" != "x" || test "x$libcrypto_ed25519" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: ed25519: yes" >&5 +$as_echo "$as_me: ed25519: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: ed25519: no" >&5 +$as_echo "$as_me: ed25519: no" >&6;} + +fi +if test "x$LIBDECAF_LIBS" != "x" || test "x$libcrypto_ed448" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: ed448: yes" >&5 +$as_echo "$as_me: ed448: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: ed448: no" >&5 +$as_echo "$as_me: ed448: no" >&6;} + +fi +if test "x$needsqlite3" != "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: SQLite3: yes" >&5 +$as_echo "$as_me: SQLite3: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: SQLite3: no" >&5 +$as_echo "$as_me: SQLite3: no" >&6;} + +fi +if test "x$LUAPC" != "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: Lua: $LUAPC" >&5 +$as_echo "$as_me: Lua: $LUAPC" >&6;} +else + if test "x$LUAJITPC" != "x"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: LuaJit: $LUAJITPC" >&5 +$as_echo "$as_me: LuaJit: $LUAJITPC" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: Lua/LuaJit: no" >&5 +$as_echo "$as_me: Lua/LuaJit: no" >&6;} +fi + +fi +if test "x$enable_experimental_pkcs11" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: PKCS-11: yes" >&5 +$as_echo "$as_me: PKCS-11: yes" >&6;} + +fi +if test "x$enable_experimental_gss_tsig" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: GSS-TSIG: yes" >&5 +$as_echo "$as_me: GSS-TSIG: yes" >&6;} + +fi +if test "x$enable_lua_records" = "xyes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: LUA records: yes" >&5 +$as_echo "$as_me: LUA records: yes" >&6;} + +fi +if test "x$systemd" != "xn"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: systemd: yes" >&5 +$as_echo "$as_me: systemd: yes" >&6;} +else + { $as_echo "$as_me:${as_lineno-$LINENO}: systemd: no" >&5 +$as_echo "$as_me: systemd: no" >&6;} + +fi +if test "x$enable_remotebackend_zeromq" != "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: ZeroMQ connector for remotebackend: yes" >&5 +$as_echo "$as_me: ZeroMQ connector for remotebackend: yes" >&6;} + +fi +if test -n "$GEOIP_LIBS"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: libgeoip for geoipbackend: yes" >&5 +$as_echo "$as_me: libgeoip for geoipbackend: yes" >&6;} + +fi +if test -n "$MMDB_LIBS"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: libmaxminddb for geoipbackend: yes" >&5 +$as_echo "$as_me: libmaxminddb for geoipbackend: yes" >&6;} + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 +$as_echo "$as_me: " >&6;} diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..aca44b9 --- /dev/null +++ b/configure.ac @@ -0,0 +1,413 @@ +AC_PREREQ([2.61]) + +AC_INIT([pdns], [4.2.1]) + +AC_CONFIG_SRCDIR([pdns/receiver.cc]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([build-aux]) + +AC_SUBST([pdns_configure_args], ["$ac_configure_args"]) +AC_DEFINE_UNQUOTED([PDNS_CONFIG_ARGS], + ["$pdns_configure_args"], + [pdns configure arguments] +) + +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip tar-ustar -Wno-portability subdir-objects parallel-tests 1.11]) +AM_SILENT_RULES([yes]) + +AC_CANONICAL_HOST +# Add some default CFLAGS and CXXFLAGS, can be appended to using the environment variables +CFLAGS="-Wall -g -O2 $CFLAGS" +CXXFLAGS="-Wall -g -O2 $CXXFLAGS" + +AC_PROG_CC +AM_PROG_CC_C_O +PDNS_CHECK_BISON +PDNS_CHECK_FLEX +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +AC_PROG_CXX +AS_IF([test "x$CXX" = "xno" || test "x$CXX:x$GXX" = "xg++:x"], + [AC_MSG_ERROR([no C++ compiler found])] +) + +AC_LANG([C++]) + +AC_DEFINE([_GNU_SOURCE], [1], + [Define _GNU_SOURCE so that we get all necessary prototypes] +) + +# Warn when pkg.m4 is missing +m4_pattern_forbid([^_?PKG_[A-Z_]+$], [*** pkg.m4 missing, please install pkg-config]) + +PDNS_CHECK_OS +PTHREAD_SET_NAME + +PDNS_WITH_LUA +PDNS_CHECK_LUA_HPP + +AX_CXX_COMPILE_STDCXX_11 + +AC_MSG_CHECKING([whether we will enable compiler security checks]) +AC_ARG_ENABLE([hardening], + [AS_HELP_STRING([--disable-hardening], [disable compiler security checks @<:@default=no@:>@])], + [enable_hardening=$enableval], + [enable_hardening=yes] +) +AC_MSG_RESULT([$enable_hardening]) + +AS_IF([test "x$enable_hardening" != "xno"], [ + AC_CC_PIE + AC_CC_STACK_PROTECTOR + AC_CC_PARAM_SSP_BUFFER_SIZE([4]) + AC_CC_D_FORTIFY_SOURCE + AC_LD_RELRO +]) + +PDNS_ENABLE_KISS + +PDNS_CHECK_NETWORK_LIBS + +LT_PREREQ([2.2.2]) +LT_INIT([disable-static dlopen]) + + +MC_TM_GMTOFF + +# Define full_libdir to be the fully expanded (${exec_prefix}, etc.) +# "system" library path. +# We use this to search for other libraries. +eval full_libdir="\"$libdir\"" + +# detect pkg-config explicitly +PKG_PROG_PKG_CONFIG + +AC_CHECK_HEADERS( + [sys/mman.h], + [AC_CHECK_FUNC( + [mmap], + [AC_DEFINE(HAVE_MMAP, [1], [Define to 1 if you have mmap])], + [have_mmap=no] + )], + [have_mmap=no] +) + +PDNS_WITH_LIBSODIUM +PDNS_WITH_LIBDECAF +PDNS_CHECK_LIBCRYPTO([ +],[ + AC_MSG_ERROR([OpenSSL/libcrypto not found]) + ] +) +PDNS_CHECK_LIBCRYPTO_ECDSA +PDNS_CHECK_LIBCRYPTO_EDDSA + +PDNS_CHECK_RAGEL([pdns/dnslabeltext.cc], [www.powerdns.com]) +PDNS_CHECK_CLOCK_GETTIME + +BOOST_REQUIRE([1.42]) +# Boost accumulators, as used by dnsbulktest and dnstcpbench, need 1.48+ +# to be compatible with C++11 +AM_CONDITIONAL([HAVE_BOOST_GE_148], [test "$boost_major_version" -ge 148]) +AS_IF([test "$boost_major_version" -ge 148], [ + AC_DEFINE(HAVE_BOOST_GE_148, [1], [Define to 1 if you have boost >= 1.48]) +]) + +BOOST_PROGRAM_OPTIONS([mt]) +AS_IF([test "$boost_cv_lib_program_options" = "no"], [ + AC_MSG_ERROR([Boost Program Options library not found]) +]) +PDNS_ENABLE_UNIT_TESTS +PDNS_ENABLE_BACKEND_UNIT_TESTS +PDNS_ENABLE_REPRODUCIBLE +PDNS_ENABLE_FUZZ_TARGETS + +PDNS_WITH_SQLITE3 + +PDNS_CHECK_VIRTUALENV +PDNS_FROM_GIT + +dnl Checks for library functions. +AC_CHECK_FUNCS_ONCE([strcasestr localtime_r recvmmsg sched_setscheduler getrandom arc4random]) + +AM_CONDITIONAL([HAVE_RECVMMSG], [test "x$ac_cv_func_recvmmsg" = "xyes"]) + +AS_IF([test "x$lt_cv_dlopen" = "xno"], + [AC_MSG_ERROR([Your system does not support dlopen])] +) + +AC_SUBST([LIBDL], [$lt_cv_dlopen_libs]) + +PDNS_ENABLE_VERBOSE_LOGGING +PDNS_ENABLE_PKCS11 +PDNS_ENABLE_GSS_TSIG + +AC_SUBST([socketdir]) +socketdir="/var/run" +AC_ARG_WITH([socketdir], + [AS_HELP_STRING([--with-socketdir], [where the controlsocket lives @<:@default=/var/run@:>@])], + [socketdir="$withval"] +) + +modules="bind gmysql random" +AC_ARG_WITH([modules], + [AS_HELP_STRING([--with-modules], [which backends to compile with @<:@default=bind gmysql random@:>@])], + [modules="$withval"] +) + +dynmodules="pipe" +AC_ARG_WITH([dynmodules], + [AS_HELP_STRING([--with-dynmodules], [which backends to build for dynamic loading @<:@default=pipe@:>@])], + [dynmodules="$withval"] +) + +AC_SUBST([moduledirs]) +AC_SUBST([moduleobjects]) +AC_SUBST([modulelibs]) +AC_DEFINE_UNQUOTED([PDNS_MODULES], "$modules", [Built-in modules]) + +AS_IF([test x"$modules" = "xno"], [modules=""]) +AS_IF([test x"$dynmodules" = "xno"], [dynmodules=""]) + +for a in $modules $dynmodules; do + case "$a" in + oracle|goracle) + PDNS_WITH_ORACLE + needoracle=yes + ;; + godbc) + PDNS_WITH_UNIXODBC + ;; + mydns|gmysql) + PDNS_WITH_MYSQL + ;; + gpgsql) + PDNS_WITH_POSTGRESQL + ;; + gsqlite3) + needsqlite3=yes + ;; + ldap) + PDNS_CHECK_LDAP + needldap=yes + ;; + opendbx) + PDNS_CHECK_OPENDBX + ;; + remote) + AS_IF([test "x$enable_unit_tests" = "xyes"], + [PDNS_CHECK_CURL_PROGRAM] + ) + have_remotebackend=yes + ;; + tinydns) + PDNS_CHECK_CDB + ;; + geoip) + PDNS_CHECK_GEOIP + ;; + lua*) + AS_IF([test "x$with_lua" = "xno"], + [AC_MSG_ERROR([${a} backend needs lua, run ./configure --with-lua])] + ) + AS_IF([test "x$LUAPC" = "x"], + [AC_MSG_ERROR([${a} backend needs lua but we cannot find it])] + ) + ;; + lmdb) + PDNS_CHECK_LMDB + BOOST_SERIALIZATION + ;; + esac +done + +PDNS_ENABLE_REMOTEBACKEND_ZEROMQ + +PDNS_ENABLE_TOOLS +PDNS_ENABLE_IXFRDIST + +PDNS_WITH_PROTOBUF + +PDNS_WITH_LUA_RECORDS + +AM_CONDITIONAL([ORACLE], [test "x$needoracle" = "xyes"]) + +AM_CONDITIONAL([LDAP], [test "x$needldap" = "xyes"]) + +PDNS_CHECK_SQLITE3 +AM_CONDITIONAL([SQLITE3], [test "x$needsqlite3" = "xyes"]) + +for a in $modules; do + AC_MSG_CHECKING([whether we can build module "${a}"]) + if [[ -d "$srcdir/modules/${a}backend" ]]; then + AC_MSG_RESULT([yes]) + moduledirs="$moduledirs ${a}backend" + + for b in `cat $srcdir/modules/${a}backend/OBJECTFILES`; do + moduleobjects="$moduleobjects ../modules/${a}backend/$b" + done + modulelibs="$modulelibs `cat $srcdir/modules/${a}backend/OBJECTLIBS`" + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([Do not know how to build module "$a", "$srcdir/modules/${a}backend" does not exist! Please review --with-modules parameter for supported values.]) + fi +done + +for a in $dynmodules; do + AC_MSG_CHECKING([whether we can build dynamic module "${a}"]) + if [[ -d "$srcdir/modules/${a}backend" ]]; then + AC_MSG_RESULT([yes]) + moduledirs="$moduledirs ${a}backend" + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([Do not know how to build module "$a", "$srcdir/modules/${a}backend" does not exist! Please review --with-dynmodules parameter for supported values.]) + fi +done + +AX_AVAILABLE_SYSTEMD +AX_CHECK_SYSTEMD_FEATURES +AM_CONDITIONAL([HAVE_SYSTEMD], [ test x"$systemd" = "xy" ]) + +LDFLAGS="$RELRO_LDFLAGS $LDFLAGS" + +CFLAGS="$PIE_CFLAGS $CFLAGS" +CXXFLAGS="$PIE_CFLAGS $CXXFLAGS" +PROGRAM_LDFLAGS="$PIE_LDFLAGS $PROGRAM_LDFLAGS" +AC_SUBST([PROGRAM_LDFLAGS]) + +PDNS_ENABLE_COVERAGE +PDNS_ENABLE_SANITIZERS +PDNS_ENABLE_MALLOC_TRACE + +AC_SUBST(LIBS) + +AC_SUBST([AM_CPPFLAGS], + ["AS_ESCAPE([-I$(top_builddir) -I$(top_srcdir)]) $THREADFLAGS $BOOST_CPPFLAGS"] +) + +AC_SUBST([YAHTTP_CFLAGS], ['-I$(top_srcdir)/ext/yahttp']) +AC_SUBST([YAHTTP_LIBS], ['$(top_builddir)/ext/yahttp/yahttp/libyahttp.la']) +AC_SUBST([IPCRYPT_CFLAGS], ['-I$(top_srcdir)/ext/ipcrypt']) +AC_SUBST([IPCRYPT_LIBS], ['$(top_builddir)/ext/ipcrypt/libipcrypt.la']) + +CXXFLAGS="$SANITIZER_FLAGS $CXXFLAGS" + +AC_ARG_VAR(PACKAGEVERSION, [The version used in secpoll queries]) +AS_IF([test "x$PACKAGEVERSION" != "x"], + [AC_DEFINE_UNQUOTED([PACKAGEVERSION], "$PACKAGEVERSION", [Set to the package version used for secpoll])] +) + +export moduledirs moduleobjects modulelibs + +AC_CONFIG_FILES([ + Makefile + modules/Makefile + pdns/Makefile + codedocs/Makefile + docs/Makefile + pdns/pdns.init + ext/Makefile + ext/ipcrypt/Makefile + ext/yahttp/Makefile + ext/yahttp/yahttp/Makefile + ext/json11/Makefile + modules/bindbackend/Makefile + modules/geoipbackend/Makefile + modules/gmysqlbackend/Makefile + modules/godbcbackend/Makefile + modules/goraclebackend/Makefile + modules/gpgsqlbackend/Makefile + modules/gsqlite3backend/Makefile + modules/ldapbackend/Makefile + modules/lmdbbackend/Makefile + modules/luabackend/Makefile + modules/lua2backend/Makefile + modules/mydnsbackend/Makefile + modules/opendbxbackend/Makefile + modules/oraclebackend/Makefile + modules/pipebackend/Makefile + modules/randombackend/Makefile + modules/remotebackend/Makefile + modules/tinydnsbackend/Makefile +]) +AC_OUTPUT + +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Configuration summary]) +AC_MSG_NOTICE([=====================]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Configured with: $pdns_configure_args]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([CC: $CC]) +AC_MSG_NOTICE([CXX: $CXX]) +AC_MSG_NOTICE([LD: $LD]) +AC_MSG_NOTICE([CFLAGS: $CFLAGS]) +AC_MSG_NOTICE([CPPFLAGS: $CPPFLAGS]) +AC_MSG_NOTICE([CXXFLAGS: $CXXFLAGS]) +AC_MSG_NOTICE([LDFLAGS: $LDFLAGS]) +AC_MSG_NOTICE([LIBS: $LIBS]) +AC_MSG_NOTICE([BOOST_CPPFLAGS: $BOOST_CPPFLAGS]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Extras enabled]) +AC_MSG_NOTICE([--------------]) +AS_IF([test "x$enable_tools" = "xyes"], + [AC_MSG_NOTICE([Tools: yes])], + [AC_MSG_NOTICE([Tools: no])] +) +AS_IF([test "x$enable_ixfrdist" = "xyes"], + [AC_MSG_NOTICE([ixfrdist: yes])], + [AC_MSG_NOTICE([ixfrdist: no])] +) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Server Features enabled]) +AC_MSG_NOTICE([-----------------------]) +AC_MSG_NOTICE([Built-in modules: $modules]) +AC_MSG_NOTICE([Dynamic modules: $dynmodules]) +AC_MSG_NOTICE([]) +AS_IF([test "x$libcrypto_ecdsa" = "xyes"], + [AC_MSG_NOTICE([OpenSSL ecdsa: yes])], + [AC_MSG_NOTICE([OpenSSL ecdsa: no])] +) +AS_IF([test "x$LIBSODIUM_LIBS" != "x" || test "x$LIBDECAF_LIBS" != "x" || test "x$libcrypto_ed25519" = "xyes"], + [AC_MSG_NOTICE([ed25519: yes])], + [AC_MSG_NOTICE([ed25519: no])] +) +AS_IF([test "x$LIBDECAF_LIBS" != "x" || test "x$libcrypto_ed448" = "xyes"], + [AC_MSG_NOTICE([ed448: yes])], + [AC_MSG_NOTICE([ed448: no])] +) +AS_IF([test "x$needsqlite3" != "x"], + [AC_MSG_NOTICE([SQLite3: yes])], + [AC_MSG_NOTICE([SQLite3: no])] +) +AS_IF([test "x$LUAPC" != "x"], + [AC_MSG_NOTICE([Lua: $LUAPC])], + [AS_IF([test "x$LUAJITPC" != "x"], + [AC_MSG_NOTICE([LuaJit: $LUAJITPC])], + [AC_MSG_NOTICE([Lua/LuaJit: no])]) +]) +AS_IF([test "x$enable_experimental_pkcs11" = "xyes"], + [AC_MSG_NOTICE([PKCS-11: yes])] +) +AS_IF([test "x$enable_experimental_gss_tsig" = "xyes"], + [AC_MSG_NOTICE([GSS-TSIG: yes])] +) +AS_IF([test "x$enable_lua_records" = "xyes"], + [AC_MSG_NOTICE([LUA records: yes])] +) +AS_IF([test "x$systemd" != "xn"], + [AC_MSG_NOTICE([systemd: yes])], + [AC_MSG_NOTICE([systemd: no])] +) +AS_IF([test "x$enable_remotebackend_zeromq" != "xno"], + [AC_MSG_NOTICE([ZeroMQ connector for remotebackend: yes])] +) +AS_IF([test -n "$GEOIP_LIBS"], + [AC_MSG_NOTICE([libgeoip for geoipbackend: yes])] +) +AS_IF([test -n "$MMDB_LIBS"], + [AC_MSG_NOTICE([libmaxminddb for geoipbackend: yes])] +) +AC_MSG_NOTICE([]) diff --git a/contrib/powerdns.solaris.init.d b/contrib/powerdns.solaris.init.d new file mode 100644 index 0000000..030f606 --- /dev/null +++ b/contrib/powerdns.solaris.init.d @@ -0,0 +1,187 @@ +#!/bin/sh +################################################################################ +# rc script for PowerDNS, Solaris-style | fernando@secret.org # +################################################################################ + +prefix=/usr/local +exec_prefix=${prefix} +BINARYPATH=${exec_prefix}/bin +SBINARYPATH=${exec_prefix}/sbin +SOCKETPATH=/var/run + +cd $SOCKETPATH + +suffix=`/bin/basename $0 | /bin/awk -F- '{print $2}'` + +if [ $suffix ] +then + EXTRAOPTS=--config-name=$suffix + PROGNAME=pdns-$suffix +else + PROGNAME=$0 +fi + +pdns_server="$SBINARYPATH/pdns_server $EXTRAOPTS" + +doPC() +{ + ret=`$BINARYPATH/pdns_control $EXTRAOPTS $1 $2 2> /dev/null` +} + +doPC ping +NOTRUNNING=$? + +case "$1" in + status) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + doPC status + /bin/echo $ret + else + /bin/echo "not running" + fi + ;; + + stop) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + doPC quit + /bin/echo $ret + else + /bin/echo "not running" + fi + ;; + + force-stop) + /bin/echo "$PROGNAME: \c" + + /bin/pkill -v -9 pdns_server + + /bin/echo "force-stopped" + ;; + + start) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + /bin/echo "already running" + else + $pdns_server --daemon --guardian=yes + if test "$?" = "0" + then + /bin/echo "started" + fi + fi + ;; + + force-reload | restart) + /bin/echo "$PROGNAME: \c" + + /bin/echo "stopping and waiting\c" + doPC quit + sleep 3 + /bin/echo + $0 start + ;; + + reload) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + doPC cycle + /bin/echo requested reload + else + /bin/echo not running yet + $0 start + fi + ;; + + monitor) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + /bin/echo "already running" + else + $pdns_server --daemon=no --guardian=no --control-console --loglevel=9 + fi + ;; + + dump) + /bin/echo "$PROGNAME: \c" + + if test "$NOTRUNNING" = "0" + then + doPC list + /bin/echo $ret + else + /bin/echo "not running" + fi + ;; + + show) + /bin/echo "$PROGNAME: \c" + + if [ $# -lt 2 ] + then + /bin/echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + /bin/echo -n "$2=" + doPC show $2 ; /bin/echo $ret + else + /bin/echo "not running" + fi + ;; + + mrtg) + if [ $# -lt 2 ] + then + /bin/echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + doPC show $2 ; /bin/echo $ret + if [ "$3x" != "x" ] + then + doPC show $3 ; /bin/echo $ret + else + /bin/echo 0 + fi + doPC uptime ; /bin/echo $ret + /bin/echo PowerDNS daemon + else + /bin/echo "not running" + fi + + ;; + + cricket) + if [ $# -lt 2 ] + then + /bin/echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + doPC show $2 ; /bin/echo $ret + else + /bin/echo "not running" + fi + ;; + + *) + /bin/echo "Usage: $0 { start | stop | force-reload | restart | status | dump | show | mrtg | cricket | monitor }" + exit 1 + ;; +esac +exit 0 diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..af10ac7 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,120 @@ +MAIN_MANS = pdns_server.1 \ + pdns_control.1 \ + pdnsutil.1 \ + zone2json.1 \ + zone2sql.1 + +MANPAGES_INSTALL = $(MAIN_MANS) + +MANPAGES_DIST = $(MAIN_MANS) zone2ldap.1 + +if LDAP +MANPAGES_INSTALL += zone2ldap.1 +endif + +MANPAGES_TARGET_TOOLS = calidns.1 \ + dnspcap2calidns.1 \ + dnsgram.1 \ + dnsreplay.1 \ + dnsscan.1 \ + dnsscope.1 \ + dnswasher.1 \ + dumresp.1 \ + ixplore.1 \ + nproxy.1 \ + nsec3dig.1 \ + pdns_notify.1 \ + saxfr.1 \ + sdig.1 + +MANPAGES_TARGET_IXFRDIST = ixfrdist.1 \ + ixfrdist.yml.5 + +MANPAGES_DIST += $(MANPAGES_TARGET_TOOLS) \ + $(MANPAGES_TARGET_IXFRDIST) \ + dnsbulktest.1 \ + dnstcpbench.1 \ + dnspcap2protobuf.1 + +if HAVE_BOOST_GE_148 +MANPAGES_INSTALL += dnsbulktest.1 \ + dnstcpbench.1 +endif + +if HAVE_PROTOBUF +if HAVE_PROTOC +MANPAGES_INSTALL += dnspcap2protobuf.1 +endif +endif + +if TOOLS +MANPAGES_INSTALL += $(MANPAGES_TARGET_TOOLS) +endif + +if IXFRDIST +MANPAGES_INSTALL += $(MANPAGES_TARGET_IXFRDIST) +endif + +man_MANS = $(MANPAGES_INSTALL) + +EXTRA_DIST = $(MANPAGES_DIST) + +if HAVE_VIRTUALENV +if !HAVE_MANPAGES +$(MANPAGES_DIST): %: manpages/%.rst .venv + .venv/bin/python -msphinx -b man . mans $< + mv mans/$@ $@ +endif # if !HAVE_MANPAGES + +.venv: requirements.txt + virtualenv .venv + .venv/bin/pip install -U pip setuptools setuptools-git + .venv/bin/pip install -r requirements.txt + +.NOTPARALLEL: \ + all-docs \ + upload-docs \ + html-docs \ + $(MANPAGES_DIST) \ + latex/PowerDNS-Authoritative.pdf \ + PowerDNS-Authoritative.pdf \ + html-docs.tar.bz2 + +clean-local: + rm -f latex/PowerDNS-Authoritative.pdf $(MANPAGES_DIST) html-docs.tar.bz2 + rm -rf mans + +html-docs: common/** manpages/** .venv *.rst + .venv/bin/python -msphinx -b html . html-docs + +latex/PowerDNS-Authoritative.pdf: common/** manpages/** .venv *.rst + .venv/bin/python -msphinx -M latexpdf . . + +PowerDNS-Authoritative.pdf: latex/PowerDNS-Authoritative.pdf + mv $< $@ + +html-docs.tar.bz2: html-docs + tar cjf $@ $< + +all-docs: PowerDNS-Authoritative.pdf html-docs html-docs.tar.bz2 + +upload-docs: all-docs + rsync -crv --delete --no-p --chmod=g=rwX --exclude '*~' ./html-docs/ web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ + rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./html-docs.tar.bz2 web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ + rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./PowerDNS-Authoritative.pdf web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ + +else # if HAVE_VIRTUALENV +$(MANPAGES_DIST): + echo "You need virtualenv to generate the manpages" + exit 1 + +PowerDNS-Authoritative.pdf: + echo "You need virtualenv to generate the PDF" + exit 1 + +html-docs: + echo "You need virtualenv to generate the HTML docs" + exit 1 +endif + + diff --git a/docs/Makefile.in b/docs/Makefile.in new file mode 100644 index 0000000..390bfb5 --- /dev/null +++ b/docs/Makefile.in @@ -0,0 +1,808 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@LDAP_TRUE@am__append_1 = zone2ldap.1 +@HAVE_BOOST_GE_148_TRUE@am__append_2 = dnsbulktest.1 \ +@HAVE_BOOST_GE_148_TRUE@ dnstcpbench.1 + +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@am__append_3 = dnspcap2protobuf.1 +@TOOLS_TRUE@am__append_4 = $(MANPAGES_TARGET_TOOLS) +@IXFRDIST_TRUE@am__append_5 = $(MANPAGES_TARGET_IXFRDIST) +subdir = docs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" +man5dir = $(mandir)/man5 +NROFF = nroff +MANS = $(man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAIN_MANS = pdns_server.1 \ + pdns_control.1 \ + pdnsutil.1 \ + zone2json.1 \ + zone2sql.1 + +MANPAGES_INSTALL = $(MAIN_MANS) $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) +MANPAGES_DIST = $(MAIN_MANS) zone2ldap.1 $(MANPAGES_TARGET_TOOLS) \ + $(MANPAGES_TARGET_IXFRDIST) dnsbulktest.1 dnstcpbench.1 \ + dnspcap2protobuf.1 +MANPAGES_TARGET_TOOLS = calidns.1 \ + dnspcap2calidns.1 \ + dnsgram.1 \ + dnsreplay.1 \ + dnsscan.1 \ + dnsscope.1 \ + dnswasher.1 \ + dumresp.1 \ + ixplore.1 \ + nproxy.1 \ + nsec3dig.1 \ + pdns_notify.1 \ + saxfr.1 \ + sdig.1 + +MANPAGES_TARGET_IXFRDIST = ixfrdist.1 \ + ixfrdist.yml.5 + +man_MANS = $(MANPAGES_INSTALL) +EXTRA_DIST = $(MANPAGES_DIST) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign docs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign docs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man5: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_VIRTUALENV_FALSE@clean-local: +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 install-man5 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 uninstall-man5 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + clean-local cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-man1 install-man5 install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-man uninstall-man1 uninstall-man5 + +.PRECIOUS: Makefile + + +@HAVE_MANPAGES_FALSE@@HAVE_VIRTUALENV_TRUE@$(MANPAGES_DIST): %: manpages/%.rst .venv +@HAVE_MANPAGES_FALSE@@HAVE_VIRTUALENV_TRUE@ .venv/bin/python -msphinx -b man . mans $< +@HAVE_MANPAGES_FALSE@@HAVE_VIRTUALENV_TRUE@ mv mans/$@ $@ + +@HAVE_VIRTUALENV_TRUE@.venv: requirements.txt +@HAVE_VIRTUALENV_TRUE@ virtualenv .venv +@HAVE_VIRTUALENV_TRUE@ .venv/bin/pip install -U pip setuptools setuptools-git +@HAVE_VIRTUALENV_TRUE@ .venv/bin/pip install -r requirements.txt + +@HAVE_VIRTUALENV_TRUE@.NOTPARALLEL: \ +@HAVE_VIRTUALENV_TRUE@ all-docs \ +@HAVE_VIRTUALENV_TRUE@ upload-docs \ +@HAVE_VIRTUALENV_TRUE@ html-docs \ +@HAVE_VIRTUALENV_TRUE@ $(MANPAGES_DIST) \ +@HAVE_VIRTUALENV_TRUE@ latex/PowerDNS-Authoritative.pdf \ +@HAVE_VIRTUALENV_TRUE@ PowerDNS-Authoritative.pdf \ +@HAVE_VIRTUALENV_TRUE@ html-docs.tar.bz2 + +@HAVE_VIRTUALENV_TRUE@clean-local: +@HAVE_VIRTUALENV_TRUE@ rm -f latex/PowerDNS-Authoritative.pdf $(MANPAGES_DIST) html-docs.tar.bz2 +@HAVE_VIRTUALENV_TRUE@ rm -rf mans + +@HAVE_VIRTUALENV_TRUE@html-docs: common/** manpages/** .venv *.rst +@HAVE_VIRTUALENV_TRUE@ .venv/bin/python -msphinx -b html . html-docs + +@HAVE_VIRTUALENV_TRUE@latex/PowerDNS-Authoritative.pdf: common/** manpages/** .venv *.rst +@HAVE_VIRTUALENV_TRUE@ .venv/bin/python -msphinx -M latexpdf . . + +@HAVE_VIRTUALENV_TRUE@PowerDNS-Authoritative.pdf: latex/PowerDNS-Authoritative.pdf +@HAVE_VIRTUALENV_TRUE@ mv $< $@ + +@HAVE_VIRTUALENV_TRUE@html-docs.tar.bz2: html-docs +@HAVE_VIRTUALENV_TRUE@ tar cjf $@ $< + +@HAVE_VIRTUALENV_TRUE@all-docs: PowerDNS-Authoritative.pdf html-docs html-docs.tar.bz2 + +@HAVE_VIRTUALENV_TRUE@upload-docs: all-docs +@HAVE_VIRTUALENV_TRUE@ rsync -crv --delete --no-p --chmod=g=rwX --exclude '*~' ./html-docs/ web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ +@HAVE_VIRTUALENV_TRUE@ rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./html-docs.tar.bz2 web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ +@HAVE_VIRTUALENV_TRUE@ rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./PowerDNS-Authoritative.pdf web1.powerdns.com:/srv/www/doc.powerdns.com/authoritative/ + +@HAVE_VIRTUALENV_FALSE@$(MANPAGES_DIST): +@HAVE_VIRTUALENV_FALSE@ echo "You need virtualenv to generate the manpages" +@HAVE_VIRTUALENV_FALSE@ exit 1 + +@HAVE_VIRTUALENV_FALSE@PowerDNS-Authoritative.pdf: +@HAVE_VIRTUALENV_FALSE@ echo "You need virtualenv to generate the PDF" +@HAVE_VIRTUALENV_FALSE@ exit 1 + +@HAVE_VIRTUALENV_FALSE@html-docs: +@HAVE_VIRTUALENV_FALSE@ echo "You need virtualenv to generate the HTML docs" +@HAVE_VIRTUALENV_FALSE@ exit 1 + +# 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. +.NOEXPORT: diff --git a/docs/calidns.1 b/docs/calidns.1 new file mode 100644 index 0000000..f95ca0c --- /dev/null +++ b/docs/calidns.1 @@ -0,0 +1,101 @@ +.\" Man page generated from reStructuredText. +. +.TH "CALIDNS" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +calidns \- A DNS recursor testing tool +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBcalidns\fP [\fIOPTIONS\fP] \fIQUERY_FILE\fP \fIDESTINATION\fP \fIINITIAL_QPS\fP \fIHITRATE\fP +.SH DESCRIPTION +.sp +\fBcalidns\fP reads queries from \fIQUERY_FILE\fP and sends them as a +recursive query to \fIDESTINATION\fP (an IPv4 or IPv6 address, optionally +with a port number), starting at INITIAL_QPS queries per second and +aims to have a cache hitrate of \fIHITRATE\fP percent. +.sp +It will then try to determine the maximum amount of queries per second +the recursor can handle with the aforementioned \fIHITRATE\fP\&. +.SH QUERY_FILE FORMAT +.sp +The format of the \fIQUERY_FILE\fP is very simple, it should contain +"QNAME QTYPE" tuples, one per line. For example: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +powerdns.com A +powerdns.com AAAA +google.com A +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +This is similar to Alexa top 1 million list. +.SH OPTIONS +.INDENT 0.0 +.TP +.BI \-\-ecs \ +Add EDNS Client Subnet option to outgoing queries using random +addresses from the specified \fISUBNET\fP range (IPv4 only). +.TP +.B \-\-ecs\-from\-file +Read IP or subnet values from the query file and add them as EDNS +Client Subnet option to outgoing queries. +.TP +.BI \-\-increment \ +On every subsequent run, multiply the number of queries per second +by \fINUM\fP\&. By default, this is 1.1. +.TP +.BI \-\-maximum\-qps \ +Stop incrementing once this rate has been reached, to provide a +stable load. +.TP +.BI \-\-minimum\-success\-rate \ +Stop the test as soon as the success rate drops below this value, +in percent. +.TP +.BI \-\-plot\-file \ +Write results to the specified file. +.TP +.B \-\-quiet +Whether to run quietly, outputting only the maximum QPS reached. +This option is mostly useful when used with \-\-minimum\-success\-rate. +.TP +.B \-\-want\-recursion +Set this flag to send queries with the Recursion Desired flag set. +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnsbulktest.1 b/docs/dnsbulktest.1 new file mode 100644 index 0000000..b575eab --- /dev/null +++ b/docs/dnsbulktest.1 @@ -0,0 +1,65 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSBULKTEST" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnsbulktest \- A debugging tool for intermittent resolver failures +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnsbulktest\fP [\fIOPTION\fP]... \fIIPADDRESS\fP \fIPORT\fP [\fILIMIT\fP] +.SH DESCRIPTION +.sp +\fBdnsbulktest\fP sends a large amount of different queries (for up to +\fILIMIT\fP different domains) to the nameserver at \fIIPADDRESS\fP on port +\fIPORT\fP\&. It reads the domain names from STDIN in the alexa topX format +and outputs statistics on STDOUT. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help\fP,\fB \-h +Show a summary of options. +.TP +.B \-\-quiet\fP,\fB \-q +Don\(aqt show information on individual queries. +.TP +.BI \-\-type\fP,\fB \-t \ +Query the nameserver for \fITYPE\fP, A by default. +.TP +.B \-\-envoutput\fP,\fB \-e +Write results on STDOUT as shell environment variables +.TP +.B \-\-version +Display the version of dnsbulktest +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnsgram.1 b/docs/dnsgram.1 new file mode 100644 index 0000000..60603c8 --- /dev/null +++ b/docs/dnsgram.1 @@ -0,0 +1,52 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSGRAM" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnsgram \- A debugging tool for intermittent resolver failures +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnsgram\fP \fIINFILE\fP\&... +.SH DESCRIPTION +.sp +\fBdnsgram\fP takes one or more \fIINFILE\fPs in PCAP format and generates +statistics on 5 second segments allowing the study of intermittent +resolver issues. +.SH OPTIONS +.sp +None +.SH SEE ALSO +.sp +pcap(3PCAP), tcpdump(8) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnspcap2calidns.1 b/docs/dnspcap2calidns.1 new file mode 100644 index 0000000..3303e88 --- /dev/null +++ b/docs/dnspcap2calidns.1 @@ -0,0 +1,57 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSPCAP2CALIDNS" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnspcap2calidns \- A tool to convert PCAPs of DNS traffic to calidns input +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnspcap2calidns\fP \fIPCAPFILE\fP \fIOUTFILE\fP +.SH DESCRIPTION +.sp +\fBdnspcap2calidns\fP reads the PCAP file \fIPCAPFILE\fP for DNS queries and +writes these to \fIOUTFILE\fP in the format understood by \fBcalidns\fP +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +Show a summary of options. +.TP +.B \-\-version +Display the version of dnspcap2calidns +.UNINDENT +.SH SEE ALSO +.sp +\fBcalidns(1)\fP +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnspcap2protobuf.1 b/docs/dnspcap2protobuf.1 new file mode 100644 index 0000000..8137df0 --- /dev/null +++ b/docs/dnspcap2protobuf.1 @@ -0,0 +1,54 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSPCAP2PROTOBUF" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnspcap2protobuf \- A tool to convert PCAPs of DNS traffic to PowerDNS Protobuf +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnspcap2protobuf\fP \fIPCAPFILE\fP \fIOUTFILE\fP +.SH DESCRIPTION +.sp +\fBdnspcap2protobuf\fP reads the PCAP file \fIPCAPFILE\fP for DNS queries and +responses and writes these in the PowerDNS protobuf format to \fIOUTFILE\fP\&. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +Show a summary of options. +.TP +.B \-\-version +Display the version of dnspcap2protobuf +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnsreplay.1 b/docs/dnsreplay.1 new file mode 100644 index 0000000..2134175 --- /dev/null +++ b/docs/dnsreplay.1 @@ -0,0 +1,104 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSREPLAY" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnsreplay \- A PowerDNS nameserver debugging tool +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnsreplay\fP [\fIOPTION\fP]... \fIFILENAME\fP \fIADDRESS\fP [\fIPORT\fP] +.SH DESCRIPTION +.sp +This program takes recorded questions and answers and replays them to +the specified nameserver and reporting afterwards which percentage of +answers matched, were worse or better. +.sp +dnsreplay compares the answers and some other metrics with the actual +ones with those found in the dumpfile. +.sp +By default it only replay queries with recursion\-desired flag set. +.SH OPTIONS +.INDENT 0.0 +.TP +.B FILENAME +is expected to be an PCAP file. The queries are send to the DNS +server specified as \fIADDRESS\fP and \fIPORT\fP\&. +.TP +.B ADDRESS +IPv4 or IPv6 address of the nameserver to replay \fIFILENAME\fP to. +.TP +.B PORT +if omitted, 53 will be used. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-help\fP,\fB \-h +Show summary of options. +.TP +.BI \-\-ecs\-mask \ +When EDNS forwarding an IP address, mask out first octet with this value +.TP +.BI \-\-ecs\-stamp \ +Add original IP address as EDNS Client Subnet Option when +forwarding to reference server +.TP +.BI \-\-pcap\-dns\-port \ +Look at packets from or to this port in the PCAP. Default is 53. +.TP +.BI \-\-packet\-limit \ +Stop after replaying \fINUM\fP packets. Default for \fINUM\fP is 0, which +means no limit. +.TP +.BI \-\-quiet \ +If \fIFLAG\fP is set to 1. dnsreplay will not be very noisy with its +output. This is the default. +.TP +.BI \-\-recursive \ +If \fIFLAG\fP is set to 1. dnsreplay will only replay queries with +recursion desired flag set. This is the default. +.TP +.BI \-\-speedup \ +Replay queries with this speedup \fIFACTOR\fP\&. Default is 1. +.TP +.BI \-\-timeout\-msec \ +Wait at least \fIMSEC\fP milliseconds for a reply. Default is 500. +.UNINDENT +.SH BUGS +.sp +dnsreplay has no certain handling for timeouts. It handles around at +most 65536 outstanding answers. +.SH SEE ALSO +.sp +pcap(3PCAP), tcpdump(8), dnswasher(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnsscan.1 b/docs/dnsscan.1 new file mode 100644 index 0000000..095497e --- /dev/null +++ b/docs/dnsscan.1 @@ -0,0 +1,51 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSSCAN" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnsscan \- List the amount of queries per qtype in a pcap +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnsscan\fP \fIINFILE\fP\&... +.SH DESCRIPTION +.sp +\fBdnsscan\fP takes one or more \fIINFILE\fPs in PCAP format and generates a +list of the number of queries per qtype. +.SH OPTIONS +.sp +None +.SH SEE ALSO +.sp +pcap(3PCAP), tcpdump(8) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnsscope.1 b/docs/dnsscope.1 new file mode 100644 index 0000000..8097d58 --- /dev/null +++ b/docs/dnsscope.1 @@ -0,0 +1,96 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSSCOPE" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnsscope \- A PowerDNS nameserver debugging tool +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnsscope\fP [\fIOPTION\fP]... \fIINFILE\fP +.SH DESCRIPTION +.sp +\fBdnsscope\fP takes an \fIINFILE\fP in PCAP format. It generates some simple +statistics outputs these to STDOUT. +.SH OPTIONS +.INDENT 0.0 +.TP +.B INFILE +Path to a PCAP file. +.UNINDENT +.INDENT 0.0 +.TP +.B \-h\fP,\fB \-\-help +Show the help. +.TP +.B \-\-rd +Only process packets in \fIINFILE\fP with the RD (Recursion Desired) +flag set. By default, we process all DNS packets in \fIINFILE\fP\&. +.TP +.BI \-\-ipv4\fB= +Process IPv4 packets. On by default, disable with \fB\-\-ipv4 false\fP\&. +.TP +.BI \-\-ipv6\fB= +Process IPv6 packets. On by default, disable with \fB\-\-ipv6 false\fP\&. +.TP +.BI \-f\fP,\fB \-\-filter\-name\fB= +Only process packets within this domain +.TP +.BI \-\-full\-histogram \ +Write out histogram with specified bin\-size to \(aqfull\-histogram\(aq +.TP +.B \-\-log\-histogram +Write out a log\-histogram of response times to \(aqlog\-histogram\(aq +.TP +.B \-\-no\-servfail\-stats +Remove servfail responses from latency statistics +.TP +.B \-\-servfail\-tree +Figure out subtrees that generate servfails. +.TP +.BI \-\-stats\-dir \ +Drop statistics files in this directory. Defaults to ./ +.TP +.B \-l\fP,\fB \-\-load\-stats +Emit per\-second load statistics (questions, answers, outstanding). +.TP +.BI \-w \ \fP,\fB \ \-\-write\-failures \ +Write weird packets to a PCAP file at \fIFILENAME\fP\&. +.TP +.B \-v\fP,\fB \-\-verbose +Be more verbose. +.UNINDENT +.SH SEE ALSO +.sp +pcap(3PCAP), tcpdump(8) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnstcpbench.1 b/docs/dnstcpbench.1 new file mode 100644 index 0000000..8eb04ad --- /dev/null +++ b/docs/dnstcpbench.1 @@ -0,0 +1,101 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSTCPBENCH" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnstcpbench \- tool to perform TCP benchmarking of nameservers +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnstcpbench\fP [\fIOPTION\fP]... \fIREMOTE\-ADDRESS\fP [\fIREMOTE\-PORT\fP] +.SH DESCRIPTION +.sp +\fBdnstcpbench\fP reads DNS queries (by default from standard input) and +sends them out in parallel to a remote nameserver. By default TCP/IP is +used, but optionally, UDP is tried first, which allows for the +benchmarking of TCP/IP fallback. +.sp +The program reports both mean and median numbers for queries per second +and UDP and TCP latency. Each query only counts once, even if it is +tried over UDP first. This effectively means that passing \(aq\-u\(aq can lower +query rates if many queries get shunted to TCP. +.sp +The input format is one query per line: qname single\-space qtype. An +example: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +www.powerdns.com ANY +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +When benchmarking extended runs, it may be necessary to enable +TIME_WAIT recycling, as TCP/IP port tuples may otherwise run out. On +Linux this is performed by running: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The equivalent for IPv6 is not known. +.SH OPTIONS +.sp +\-f, , \-\-file \fIFILENAME\fP from which to read queries. Defaults to standard input if unspecified. +\-h, \-\-help Provide a helpful message. +\-\-timeout\-msec \fIMSEC\fP milliseconds to wait for an answer. +\-u, \-\-udp\-first Attempt resolution via UDP first, only do TCP if truncated answer is received. +\-v, \-\-verbose Be wordy on what the program is doing. +\-\-workers Use \fINUM\fP parallel worker threads. +.sp +\fIREMOTE\-ADDRESS\fP: IPv4 or IPv6 to test against. +.sp +\fIREMOTE\-PORT\fP: Port to test against, defaults to 53. +.SH BUGS +.sp +Currently the timeout code does not actually perform non\-blocking +connects or writes. So a slow connect or slow writes will still cause +low performance and delays. +.sp +Median queries per second statistics are reported as 0 for sub\-second +runs. +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dnswasher.1 b/docs/dnswasher.1 new file mode 100644 index 0000000..c04c973 --- /dev/null +++ b/docs/dnswasher.1 @@ -0,0 +1,65 @@ +.\" Man page generated from reStructuredText. +. +.TH "DNSWASHER" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dnswasher \- A PowerDNS nameserver debugging tool +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdnswasher\fP \fIINFILE\fP [\fIINFILE\fP] \fIOUTFILE\fP +.SH DESCRIPTION +.sp +dnswasher takes one or more \fIINFILE\fPs in PCAP format and writes out +\fIOUTFILE\fP also in PCAP format, while obfuscating end\-user IP addresses. +.sp +This is useful to share data with third parties while attempting to +protect the privacy of your users. +.sp +The INFILEs must be of identical PCAP type. +.sp +Please check the output of \fBdnswasher\fP to make sure no customer IP +addresses remain. Also realize that sufficient data could allow +individuals to be re\-identified based on the domain names they care +about. +.SH OPTIONS +.sp +\-\-decrypt,\-d Undo IPCipher encryption of IP addresses +\-\-help, \-h Show summary of options. +\-\-key,\-k Base64 encoded 128\-bit key for IPCipher +\-\-passphrase,\-p Passphrase that will be used to derive an IPCipher key +\-\-version,\-v Output version +.SH SEE ALSO +.sp +pcap(3PCAP), tcpdump(8) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/dumresp.1 b/docs/dumresp.1 new file mode 100644 index 0000000..d2270e3 --- /dev/null +++ b/docs/dumresp.1 @@ -0,0 +1,55 @@ +.\" Man page generated from reStructuredText. +. +.TH "DUMRESP" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +dumresp \- A dumb DNS responder +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBdumresp\fP \fILOCAL\-ADDRESS\fP \fILOCAL\-PORT\fP \fINUMBER\-OF\-PROCESSES\fP [tcp] +.SH DESCRIPTION +.sp +\fBdumresp\fP accepts DNS packets on \fILOCAL\-ADDRESS\fP:\fILOCAL\-PORT\fP and +simply replies with the same query, with the QR bit set. When +\fINUMBER\-OF\-PROCESSES\fP is set to anything but 1, \fBdumresp\fP will spawn +\fINUMBER\-OF\-PROCESSES\fP forks and use the SO_REUSEPORT option to bind to +the port. +.SH OPTIONS +.sp +tcp: Whether to listen and accept TCP connections in addition to +UDP packets. Defaults to false. +.SH SEE ALSO +.sp +socket(7) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/ixfrdist.1 b/docs/ixfrdist.1 new file mode 100644 index 0000000..7290721 --- /dev/null +++ b/docs/ixfrdist.1 @@ -0,0 +1,74 @@ +.\" Man page generated from reStructuredText. +. +.TH "IXFRDIST" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +ixfrdist \- An IXFR/AXFR-only server that re-distributes zones +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBixfrdist\fP [\fIOPTION\fP]... +.SH DESCRIPTION +.sp +\fBixfrdist\fP transfers zones from an authoritative server and re\-serves these zones over AXFR and IXFR. +It checks the SOA serial for all configured domains and downloads new versions to disk. +.sp +When a SOA query comes in and the client\(aqs address is allowed by the ACL, \fBixfrdist\fP responds with the latest SOA for the zone it has. +This query can be followed up with an IXFR or AXFR query, which will then be served to the client. +Should an IXFR be served, \fBixfrdist\fP will condense all differences it has for the domain into one IXFR. +.sp +\fBixfrdist\fP is configured with a configuration file in YAML format. +Please see \fBixfrdist.yml(5)\fP for information. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +Show all supported options +.TP +.B \-\-verbose +Log INFO messages +.TP +.B \-\-debug +Log INFO and DEBUG messages +.TP +.B \-\-version +Display the version of ixfrdist +.TP +.BI \-\-config \ +Load configuration from \fIPATH\fP, a YAML file. When not set, +an \fIixfrdist.yml\fP is attempted to be read from the SYSCONFDIR. +.UNINDENT +.SH SEE ALSO +.sp +ixplore(1), pdns_server(1), ixfrdist.yml(5) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/ixfrdist.yml.5 b/docs/ixfrdist.yml.5 new file mode 100644 index 0000000..6cc2e10 --- /dev/null +++ b/docs/ixfrdist.yml.5 @@ -0,0 +1,176 @@ +.\" Man page generated from reStructuredText. +. +.TH "IXFRDIST.YML" "5" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +ixfrdist.yml \- The ixfrdist configuration file +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +ixfrdist.yml +.SH DESCRIPTION +.sp +\fBixfrdist\fP reads its configuration for a YAML file. +By default, this file is called \fIixfrdist.yml\fP and is read from the directory configured as \fISYSCONFDIR\fP when building the software. +This directory is usually one of \fI/etc/pdns\fP, \fI/etc/powerdns\fP\&. +Run \fIixfrdist \-\-help\fP to see the default. +.SH EXAMPLE +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +listen: + \- 192.0.2.2 + \- \(aq[2001:DB8:ABCD::2]:5300\(aq + \- 127.0.0.1 + +acl: + \- 127.0.0.1 + \- \(aq192.0.2.0/24\(aq + \- \(aq2001:DB8:ABCD:1234::/64\(aq + +work\-dir: /var/lib/ixfrdist + +uid: ixfrdist +gid: ixfrdist + +domains: + \- domain: example.com + master: 192.0.2.18:5301 + \- domain: example.net + master: 2001:DB8:ABCD::2 +.ft P +.fi +.UNINDENT +.UNINDENT +.SH OPTIONS +.INDENT 0.0 +.TP +.B listen +The list of addresses to listen on. +\fBixfrdist\fP listens on both TCP and UDP. +When no port is specified, 53 is used. When specifying ports for IPv6, use the "bracket" notation. +By default, \fBixfrdist\fP listens on \fB127.0.0.1:53\fP and \fB[::1]:53\fP\&. +.TP +.B acl +A list of netmasks that are allowed to query \fBixfrdist\fP and request AXFRs and IXFRs +Entries without a netmask will be interpreted as a single address. +By default, the ACL is set is \fB127.0.0.0/8\fP and \fB::1/128\fP\&. +.TP +.B axfr\-max\-records +Maximum number of records allowed in an AXFR transaction requested by \fBixfrdist\fP\&. +This may prevent untrusted sources from using all the process memory. +By default, this setting is \fB0\fP, which means "unlimited". +.TP +.B axfr\-timeout +Timeout in seconds an AXFR transaction requested by \fBixfrdist\fP may take. +Increase this when the network to the authoritative servers is slow or the domains are very large and you experience timeouts. +Defaults to 20. +.TP +.B failed\-soa\-retry +Time in seconds between retries of the SOA query for a zone we have never transferred. Defaults to 30. +.TP +.B compress +Whether record compression should be enabled, leading to smaller answers at the cost of an increased CPU and memory usage. +Defaults to false. +.TP +.B work\-dir +The directory where the domain data is stored. +When not set, the current working directory is used. +This working directory has the following structure: \fBwork\-dir/ZONE/SERIAL\fP, e.g. \fBwork\-dir/rpz.example./2018011902\fP\&. +It is highly recommended to set this option, as the current working directory might change between invocations. +This directory must be writable for the user or group \fBixfrdist\fP runs as. +.TP +.B keep +Amount of older copies/IXFR diffs to keep for every domain. +This is set to 20 by default. +.TP +.B tcp\-in\-threads +Number of threads to spawn for TCP connections (AXFRs) from downstream hosts. +This limits the number of concurrent AXFRs to clients. +Set to 10 by default. +.TP +.B gid +Group name or numeric ID to drop privileges to after binding the listen sockets. +By default, \fBixfrdist\fP runs as the user that started the process. +.TP +.B uid +User name or numeric ID to drop privileges to after binding the listen sockets. +By default, \fBixfrdist\fP runs as the user that started the process. +.TP +.B domains +A list of domains to redistribute. +This option is mandatory. +.INDENT 7.0 +.TP +.B domain +The domain name to transfer from the \fBmaster\fP\&. +Mandatory. +.TP +.B master +IP address of the server to transfer this domain from. +Mandatory. +.UNINDENT +.TP +.B webserver\-address +IP address to listen on for the built\-in webserver. +When not set, no webserver is started. +.TP +.B webserver\-acl +A list of networks that are allowed to access the \fBixfrdist\fP webserver. +Entries without a netmask will be interpreted as a single address. +By default, this list is set to \fB127.0.0.0/8\fP and \fB::1/128\fP\&. +.TP +.B webserver\-loglevel +How much the webserver should log: \(aqnone\(aq, \(aqnormal\(aq or \(aqdetailed\(aq. +When logging, each log\-line contains the UUID of the request, this allows finding errors caused by certain requests. +With \(aqnone\(aq, nothing is logged except for errors. +With \(aqnormal\(aq (the default), one line per request is logged in the style of the common log format: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +[NOTICE] [webserver] 46326eef\-b3ba\-4455\-8e76\-15ec73879aa3 127.0.0.1:57566 "GET /metrics HTTP/1.1" 200 1846 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +with \(aqdetailed\(aq, the full requests and responses (including headers) are logged along with the regular log\-line from \(aqnormal\(aq. +.UNINDENT +.SH SEE ALSO +.sp +\fBixfrdist(1)\fP +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/ixplore.1 b/docs/ixplore.1 new file mode 100644 index 0000000..a1691df --- /dev/null +++ b/docs/ixplore.1 @@ -0,0 +1,89 @@ +.\" Man page generated from reStructuredText. +. +.TH "IXPLORE" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +ixplore \- A tool that provides insights into IXFRs +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBixplore\fP \fICOMMAND\fP \fICOMMAND_OPT\fP\&... +.sp +\fBixplore\fP diff \fIZONE\fP \fIBEFORE\fP \fIAFTER\fP +.sp +\fBixplore\fP track \fIIP ADDRESS\fP \fIPORT\fP \fIZONE\fP \fIDIRECTORY\fP +.SH DESCRIPTION +.sp +\fBixplore\fP is a tool to work with IXFR (incremental zonetransfers) in +two modes (specified by \fICOMMAND\fP): diff or track. +.sp +In the \(aqdiff\(aq mode, it will show a diff(1)\-like output between \fIBEFORE\fP +and \fIAFTER\fP\&. +.sp +In the \(aqtrack\(aq mode, \fBixplore\fP consumes IXFRs from \fIIP ADDRESS\fP and +writes the resulting zonefiles out to \fIDIRECTORY\fP/\fIZONE\fP\-serial. If no +initial zonefiles exist, an initial AXFR will be done first. \fBixplore\fP +will then check the SOA serial on \fIIP ADDRESS\fP for \fIZONE\fP every SOA +Refresh seconds and perform an IXFR if the serial has increased. +.SH OPTIONS +.SH DIFF-MODE +.INDENT 0.0 +.TP +.B ZONE +The name of the zone the IXFRs are consumed from. +.TP +.B BEFORE +Path to the \(aqbefore\(aq zonefile. +.TP +.B AFYER +Path to the \(aqafter\(aq zonefile. +.UNINDENT +.SH TRACK-MODE +.INDENT 0.0 +.TP +.B IP ADDRESS +The IP address to consume IXFRs from. +.TP +.B PORT +The port to use on \fIIP ADDRESS\fP\&. +.TP +.B ZONE +Name of the zone to track changes of. +.TP +.B DIRECTORY +Directory where the zonefiles will be stored. +.UNINDENT +.SH SEE ALSO +.sp +diff(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/nproxy.1 b/docs/nproxy.1 new file mode 100644 index 0000000..10625c8 --- /dev/null +++ b/docs/nproxy.1 @@ -0,0 +1,88 @@ +.\" Man page generated from reStructuredText. +. +.TH "NPROXY" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +nproxy \- DNS notification proxy +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBnproxy\fP \-\-powerdns\-address \fIADDRESS\fP [\fIOPTION\fP]... \fIADDRESS\fP\&... +.SH DESCRIPTION +.sp +\fBnproxy\fP is a simple daemon that reads DNS NOTIFY queries on one +address and forwards them to an \(aqinner\(aq nameserver that will process the +notification. +.sp +Its usecase is e.g. a private authoritative server inside a NAT or +firewalled LAN where \fBnproxy\fP is deployed in the DMZ. +.sp +The PowerDNS Authoritative Server has the trusted\-notification\-proxy +option that should be set to the address set with \fI\-\-origin\-address\fP to +accept these proxied notifications. +.sp +\fBnproxy\fP also has a health\-check option built in. A query for +\(aqpdns.nproxy.\(aq with QType \(aqTXT\(aq will be responded to with an answer of +"OK" (inside the TXT record. When the query is for an A\-record, +\(aq1.2.3.4.\(aq is returned. +.SH OPTIONS +.INDENT 0.0 +.TP +.BI \-\-powerdns\-address \
+IP address of the PowerDNS server to forward the notifications to. +.TP +.BI \-\-chroot \ +chroot to \fIPATH\fP for additional security. +.TP +.BI \-\-setuid \ +setuid to this numerical \fIUID\fP\&. +.TP +.BI \-\-setgid \ +setgid to this numerical \fIGID\fP\&. +.TP +.BI \-\-origin\-address \
+Set the source of the notifications sent to PowerDNS to \fIADDRESS\fP\&. By default, the best matching address (kernel\(aqs choice) is used. +.TP +.BI \-\-listen\-address \
+IP addresses to listen on. +.TP +.BI \-\-listen\-port \ +Source port to listen on, 53 by default. +.TP +.BI \-d\fP,\fB \-\-daemon \ +Set \fIARG\fP to 0 to disable running in the background. +.TP +.B \-v\fP,\fB \-\-verbose +Be verbose +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/nsec3dig.1 b/docs/nsec3dig.1 new file mode 100644 index 0000000..da87a74 --- /dev/null +++ b/docs/nsec3dig.1 @@ -0,0 +1,50 @@ +.\" Man page generated from reStructuredText. +. +.TH "NSEC3DIG" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +nsec3dig \- Show and validate NSEC3 proofs +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBnsec3dig\fP \fIIPADDRESS\fP \fIPORT\fP \fIQNAME\fP \fIQTYPE\fP [recurse] +.SH DESCRIPTION +.sp +\fBnsec3dig\fP sends a query for \fIQNAME\fP and \fIQTYPE\fP to the nameserver at +\fIIPADDRESS\fP on port \fIPORT\fP and prints whether and why the NSEC3 proofs +are correct. Using the \(aqrecurse\(aq option sets the Recursion Desired (RD) +bit in the query. +.SH EXAMPLE +.sp +\fBnsec3dig 8.8.8.8 53 doesntexist.isoc.nl TXT recurse\fP +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/pdns_control.1 b/docs/pdns_control.1 new file mode 100644 index 0000000..e3c1337 --- /dev/null +++ b/docs/pdns_control.1 @@ -0,0 +1,179 @@ +.\" Man page generated from reStructuredText. +. +.TH "PDNS_CONTROL" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +pdns_control \- Control the PowerDNS nameserver +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBpdns_control\fP [\fIOPTION\fP]... \fICOMMAND\fP +.SH DESCRIPTION +.sp +\fBpdns_control\fP is used to send commands to a running PowerDNS +nameserver. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +Show summary of options. +.TP +.BI \-\-chroot\fB= +Directory where PowerDNS is chrooted. +.TP +.BI \-\-config\-dir\fB= +Location of configuration directory (pdns.conf). +.TP +.BI \-\-config\-name\fB= +Name of this virtual configuration \- will rename the binary image. +.TP +.BI \-\-remote\-address\fB=
+Remote address to query. +.TP +.BI \-\-remote\-port\fB= +Remote port to query. +.TP +.BI \-\-secret\fB= +Secret needed to connect to remote PowerDNS. +.TP +.BI \-\-socket\-dir\fB= +Where the controlsocket lives. +.UNINDENT +.SH COMMANDS +.SS bind\-add\-zone \fIDOMAIN\fP \fIFILENAME\fP +.sp +When using the BIND backend, add a zone. This zone is added in\-memory +and served immediately. Note that this does not add the zone to the +bind\-config file. \fIFILENAME\fP must be an absolute path. +.SS bind\-domain\-status [\fIDOMAIN\fP\&...] +.sp +When using the BIND backend, list status of all domains. Optionally, +append \fIDOMAIN\fPs to get the status of specific zones. +.SS bind\-list\-rejects +.sp +When using the BIND backend, get a list of all rejected domains. +.SS bind\-reload\-now \fIDOMAIN\fP [\fIDOMAIN\fP\&...] +.sp +When using the BIND backend, immediately reload \fIDOMAIN\fP from disk. +.SS ccounts +.sp +Show the content of the cache. +.SS current\-config +.sp +Show the currently running configuration. The output has the same +format as \fBpdns_server \-\-config\fP\&. You\(aqll notice that all the are +uncommented. This is because PowerDNS simply has values, and the +default isn\(aqt known at runtime. +.SS cycle +.sp +Restart the nameserver so it reloads its configuration. Only works +when the server is running in guardian mode. +.SS list +.sp +Dump all variables and their values in a comma separated list, +equivalent to \fBshow *\fP\&. +.SS list\-zones [master,slave,native] +.sp +Show a list of zones, optionally filter on the type of zones to +show. +.SS notify \fIDOMAIN\fP +.sp +Adds \fIDOMAIN\fP to the notification list, causing PowerDNS to send out +notifications to the nameservers of a domain. Can be used if a slave +missed previous notifications or is generally hard of hearing. Use +* to notify for all domains. (Note that you may need to escape the +* sign in your shell.) +.SS notify\-host \fIDOMAIN\fP \fIADDRESS\fP +.sp +Same as above but with operator specified IP \fIADDRESS\fP as +destination, to be used if you know better than PowerDNS. +.SS ping, rping +.sp +Check if the server is still alive. Will return \(aqPONG\(aq when it is. +\fBping\fP works when running inside a guardian, whereas \fBrping\fP +works when running without a guardian. +.SS purge [\fIRECORD\fP] +.sp +Purge entries from the cache. If \fIRECORD\fP ends with a dollar ($) all +entries that end with that name are removed. If no record is +specified the entire cache is purged. +.SS qtypes +.sp +Get a count of queries per qtype on standard out. +.SS quit +.sp +Tell a running pdns_server to quit. +.SS rediscover +.sp +Instructs backends that new domains may have appeared in the +database, or, in the case of the BIND backend, in named.conf. +.SS reload +.sp +Instruct the server to reload all its zones, this will not add new +zones. +.SS remotes +.sp +Get the top number of remote addresses (clients). +.SS respsizes +.sp +Get a histogram of the response sizes. +.SS retrieve \fIDOMAIN\fP +.sp +Retrieve slave \fIDOMAIN\fP from its master. Done nearly immediately. +.SS set \fIVARIABLE\fP \fIVALUE\fP +.sp +Set the configuration parameter \fIVARIABLE\fP to \fIVALUE\fP\&. Currently +only the query\-logging can be set. +.SS show \fIVARIABLE\fP +.sp +Show a single statistic, as present in the output of the list +command. +.SS status +.sp +Show usage statistics. This only works if the server is running in +guardian mode. +.SS token\-login \fIMODULE\fP \fISLOT\fP \fIPIN\fP +.sp +Log on to a PKCS#11 slot. You only need to login once per slot, even +if you have multiple keys on single slot. Only available if PowerDNS +was compiled with PKCS#11 support. +.SS uptime +.sp +Show the uptime of the running server. +.SS version +.sp +Print the version of the running pdns daemon. +.SH SEE ALSO +.sp +pdns_server(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/pdns_notify.1 b/docs/pdns_notify.1 new file mode 100644 index 0000000..2955145 --- /dev/null +++ b/docs/pdns_notify.1 @@ -0,0 +1,49 @@ +.\" Man page generated from reStructuredText. +. +.TH "PDNS_NOTIFY" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +pdns_notify \- A simple DNS NOTIFY sender +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBpdns_notify\fP \fIIP_ADDRESS/HOSTNAME\fP[:\fIPORT\fP] \fIDOMAIN\fP +.SH DESCRIPTION +.sp +\fBpdns_notify\fP sends a DNS NOTIFY message to \fIIP_ADDRESS\fP or \fIHOSTNAME\fP, by default +on port 53, for \fIDOMAIN\fP and prints the remote nameserver\(aqs response. If \fIHOSTNAME\fP resolves +to multiple IP addresses, each one is notified. +.SH OPTIONS +.sp +None +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/pdns_server.1 b/docs/pdns_server.1 new file mode 100644 index 0000000..aa13cb1 --- /dev/null +++ b/docs/pdns_server.1 @@ -0,0 +1,74 @@ +.\" Man page generated from reStructuredText. +. +.TH "PDNS_SERVER" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +pdns_server \- The PowerDNS Authoritative Namserver +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBpdns_server\fP [\fIOPTION\fP] +.SH DESCRIPTION +.sp +The PowerDNS Authoritative Server is a versatile nameserver which +supports a large number of backends. These backends can either be plain +zone files or be more dynamic in nature. Please see the online +documentation for more information. +.SH OPTIONS +.sp +See the online documentation for all options +.INDENT 0.0 +.TP +.B \-\-daemon +Indicate if the server should run in the background as a real +daemon, or in the foreground. +.TP +.B \-\-guardian +Run \fBpdns_server\fP inside a guardian. This guardian monitors the +performance of the inner \fBpdns_server\fP instance. It is also this +guardian that \fBpdns_control\fPtalks to. +.TP +.B \-\-control\-console +Run the server in a special monitor mode. This enables detailed +logging and exposes the raw control socket. +.TP +.BI \-\-loglevel\fB= +Set the logging level. +.TP +.B \-\-help +To view more options that are available use this program. +.UNINDENT +.SH SEE ALSO +.sp +pdns_control(1), pdnsutil(1), \fI\%https://doc.powerdns.com/\fP +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/pdnsutil.1 b/docs/pdnsutil.1 new file mode 100644 index 0000000..063a063 --- /dev/null +++ b/docs/pdnsutil.1 @@ -0,0 +1,359 @@ +.\" Man page generated from reStructuredText. +. +.TH "PDNSUTIL" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +pdnsutil \- PowerDNS record and DNSSEC command and control +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +pdnsutil [OPTION]... \fICOMMAND\fP +.SH DESCRIPTION +.sp +\fBpdnsutil\fP (formerly pdnssec) is a powerful command that is the +operator\-friendly gateway into DNSSEC and zone management for PowerDNS. +Behind the scenes, \fBpdnsutil\fP manipulates a PowerDNS backend database, +which also means that for many databases, \fBpdnsutil\fP can be run +remotely, and can configure key material on different servers. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-h\fP,\fB \-\-help +Show summary of options +.TP +.B \-v\fP,\fB \-\-verbose +Be more verbose. +.TP +.B \-\-force +Force an action +.TP +.BI \-\-config\-name \ +Virtual configuration name +.TP +.BI \-\-config\-dir \ +Location of pdns.conf. Default is /etc/powerdns. +.UNINDENT +.SH COMMANDS +.sp +There are many available commands, this section splits them up into +their respective uses +.SH DNSSEC RELATED COMMANDS +.sp +Several commands manipulate the DNSSEC keys and options for zones. Some +of these commands require an \fIALGORITHM\fP to be set. The following +algorithms are supported: +.INDENT 0.0 +.IP \(bu 2 +rsasha1 +.IP \(bu 2 +rsasha256 +.IP \(bu 2 +rsasha512 +.IP \(bu 2 +ecdsa256 +.IP \(bu 2 +ecdsa384 +.IP \(bu 2 +ed25519 +.IP \(bu 2 +ed448 +.UNINDENT +.INDENT 0.0 +.TP +.B activate\-zone\-key \fIZONE\fP \fIKEY\-ID\fP +Activate a key with id \fIKEY\-ID\fP within a zone called \fIZONE\fP\&. +.TP +add\-zone\-key \fIZONE\fP {\fBKSK\fP,\fBZSK\fP} [\fBactive\fP,\fBinactive\fP] \fIKEYBITS\fP \fIALGORITHM\fP +Create a new key for zone \fIZONE\fP, and make it a KSK or a ZSK, with +the specified algorithm. The key is inactive by default, set it to +\fBactive\fP to immediately use it to sign \fIZONE\fP\&. Prints the id of +the added key. +.TP +.B create\-bind\-db \fIFILE\fP +Create DNSSEC database (sqlite3) at \fIFILE\fP for the BIND backend. +Remember to set \fBbind\-dnssec\-db=*FILE*\fP in your \fBpdns.conf\fP\&. +.TP +.B deactivate\-zone\-key \fIZONE\fP \fIKEY\-ID\fP +Deactivate a key with id KEY\-ID within a zone called \fIZONE\fP\&. +.TP +.B disable\-dnssec \fIZONE\fP +Deactivate all keys and unset PRESIGNED in \fIZONE\fP\&. +.TP +.B export\-zone\-dnskey \fIZONE\fP \fIKEY\-ID\fP +Export to standard output DNSKEY and DS of key with key id \fIKEY\-ID\fP +within zone called \fIZONE\fP\&. +.TP +.B export\-zone\-ds \fIZONE\fP +Export to standard output all KSK DS records for \fIZONE\fP\&. +.TP +.B export\-zone\-key \fIZONE\fP \fIKEY\-ID\fP +Export to standard output full (private) key with key id \fIKEY\-ID\fP +within zone called \fIZONE\fP\&. The format used is compatible with BIND +and NSD/LDNS. +.TP +generate\-zone\-key {\fBKSK\fP,\fBZSK\fP} [\fIALGORITHM\fP] [\fIKEYBITS\fP] +Generate a ZSK or KSK to stdout with specified algorithm and bits +and print it on STDOUT. If \fIALGORITHM\fP is not set, ECDSA256 is +used. If \fIKEYBITS\fP is not set, an appropriate keysize is selected +for \fIALGORITHM\fP\&. Each ECC\-based algorithm supports only one valid +\fIKEYBITS\fP value: For ECDSA256 and ED25519, it is 256; for ECDSA384, +it is 384; and for ED448, it is 456. +.TP +import\-zone\-key \fIZONE\fP \fIFILE\fP {\fBKSK\fP,\fBZSK\fP} +Import from \fIFILE\fP a full (private) key for zone called \fIZONE\fP\&. The +format used is compatible with BIND and NSD/LDNS. \fBKSK\fP or \fBZSK\fP +specifies the flags this key should have on import. Prints the id of +the added key. +.TP +.B remove\-zone\-key \fIZONE\fP \fIKEY\-ID\fP +Remove a key with id \fIKEY\-ID\fP from a zone called \fIZONE\fP\&. +.TP +set\-nsec3 \fIZONE\fP [\(aq\fIHASH\-ALGORITHM\fP \fIFLAGS\fP \fIITERATIONS\fP \fISALT\fP\(aq] [\fBnarrow\fP] +Sets NSEC3 parameters for this zone. The quoted parameters are 4 +values that are used for the the NSEC3PARAM record and decide how +NSEC3 records are created. The NSEC3 parameters must be quoted on +the command line. \fIHASH\-ALGORITHM\fP must be 1 (SHA\-1). Setting +\fIFLAGS\fP to 1 enables NSEC3 opt\-out operation. Only do this if you +know you need it. For \fIITERATIONS\fP, please consult RFC 5155, section +10.3. And be aware that a high number might overload validating +resolvers and that a limit can be set with \fBmax\-nsec3\-iterations\fP +in \fBpdns.conf\fP\&. The \fISALT\fP is a hexadecimal string encoding the bits +for the salt, or \- to use no salt. Setting \fBnarrow\fP will make PowerDNS +send out "white lies" (RFC 7129) about the next secure record to +prevent zone enumeration. Instead of looking it up in the database, +it will send out the hash + 1 as the next secure record. Narrow mode +requires online signing capabilities by the nameserver and therefore +zone transfers are denied. If only the zone is provided as argument, +the 4\-parameter quoted string defaults to \fB\(aq1 0 1 ab\(aq\fP\&. A sample +commandline is: \fBpdnsutil set\-nsec3 powerdnssec.org \(aq1 1 1 ab\(aq narrow\fP\&. +\fBWARNING\fP: If running in RSASHA1 mode (algorithm 5 or 7), switching +from NSEC to NSEC3 will require a DS update in the parent zone. +.TP +.B unset\-nsec3 \fIZONE\fP +Converts \fIZONE\fP to NSEC operations. \fBWARNING\fP: If running in +RSASHA1 mode (algorithm 5 or 7), switching from NSEC to NSEC3 will +require a DS update at the parent zone! +.TP +.B set\-publish\-cds \fIZONE\fP [\fIDIGESTALGOS\fP] +Set \fIZONE\fP to respond to queries for its CDS records. the optional +argument \fIDIGESTALGOS\fP should be a comma\-separated list of DS +algorithms to use. By default, this is 2 (SHA\-256). +.TP +.B set\-publish\-cdnskey \fIZONE\fP +Set \fIZONE\fP to publish CDNSKEY records. +.TP +.B unset\-publish\-cds \fIZONE\fP +Set \fIZONE\fP to stop responding to queries for its CDS records. +.TP +.B unset\-publish\-cdnskey \fIZONE\fP +Set \fIZONE\fP to stop publishing CDNSKEY records. +.UNINDENT +.SH TSIG RELATED COMMANDS +.sp +These commands manipulate TSIG key information in the database. Some +commands require an \fIALGORITHM\fP, the following are available: +.INDENT 0.0 +.IP \(bu 2 +hmac\-md5 +.IP \(bu 2 +hmac\-sha1 +.IP \(bu 2 +hmac\-sha224 +.IP \(bu 2 +hmac\-sha256 +.IP \(bu 2 +hmac\-sha384 +.IP \(bu 2 +hmac\-sha512 +.UNINDENT +.INDENT 0.0 +.TP +activate\-tsig\-key \fIZONE\fP \fINAME\fP {\fBmaster\fP,\fBslave\fP} +Enable TSIG authenticated AXFR using the key \fINAME\fP for zone \fIZONE\fP\&. +This sets the \fBTSIG\-ALLOW\-AXFR\fP (master) or \fBAXFR\-MASTER\-TSIG\fP +(slave) zone metadata. +.TP +deactivate\-tsig\-key \fIZONE\fP \fINAME\fP {\fBmaster\fP,\fBslave\fP} +Disable TSIG authenticated AXFR using the key \fINAME\fP for zone +\fIZONE\fP\&. +.TP +.B delete\-tsig\-key \fINAME\fP +Delete the TSIG key \fINAME\fP\&. Warning, this does not deactivate said +key. +.TP +.B generate\-tsig\-key \fINAME\fP \fIALGORITHM\fP +Generate new TSIG key with name \fINAME\fP and the specified algorithm. +.TP +.B import\-tsig\-key \fINAME\fP \fIALGORITHM\fP \fIKEY\fP +Import \fIKEY\fP of the specified algorithm as \fINAME\fP\&. +.TP +.B list\-tsig\-keys +Show a list of all configured TSIG keys. +.UNINDENT +.SH ZONE MANIPULATION COMMANDS +.INDENT 0.0 +.TP +.B add\-record \fIZONE\fP \fINAME\fP \fITYPE\fP [\fITTL\fP] \fICONTENT\fP +Add one or more records of \fINAME\fP and \fITYPE\fP to \fIZONE\fP with \fICONTENT\fP +and optional \fITTL\fP\&. If \fITTL\fP is not set, default will be used. +.TP +.B create\-zone \fIZONE\fP +Create an empty zone named \fIZONE\fP\&. +.TP +.B create\-slave\-zone \fIZONE\fP \fIMASTER\fP [\fIMASTER\fP].. +Create a new slave zone \fIZONE\fP with masters \fIMASTER\fP\&. All \fIMASTER\fPs +need to to be space\-separated IP addresses with an optional port. +.TP +.B change\-slave\-zone\-master \fIZONE\fP \fIMASTER\fP [\fIMASTER\fP].. +Change the masters for slave zone \fIZONE\fP to new masters \fIMASTER\fP\&. All +\fIMASTER\fPs need to to be space\-separated IP addresses with an optional port. +.TP +.B check\-all\-zones +Check all zones for correctness. +.TP +.B check\-zone \fIZONE\fP +Check zone \fIZONE\fP for correctness. +.TP +.B clear\-zone \fIZONE\fP +Clear the records in zone \fIZONE\fP, but leave actual domain and +settings unchanged +.TP +.B delete\-rrset \fIZONE\fP \fINAME\fP \fITYPE\fP +Delete named RRSET from zone. +.TP +.B delete\-zone \fIZONE\fP: +Delete the zone named \fIZONE\fP\&. +.TP +.B edit\-zone \fIZONE\fP +Opens \fIZONE\fP in zonefile format (regardless of backend it was loaded +from) in the editor set in the environment variable \fBEDITOR\fP\&. if +\fBEDITOR\fP is empty, \fIpdnsutil\fP falls back to using \fIeditor\fP\&. +.TP +.B get\-meta \fIZONE\fP [\fIATTRIBUTE\fP]... +Get zone metadata. If no \fIATTRIBUTE\fP given, lists all known. +.TP +.B hash\-zone\-record \fIZONE\fP \fIRNAME\fP +This convenience command hashes the name \fIRNAME\fP according to the +NSEC3 settings of \fIZONE\fP\&. Refuses to hash for zones with no NSEC3 +settings. +.TP +.B list\-keys [\fIZONE\fP] +List DNSSEC information for all keys or for \fIZONE\fP\&. +.TP +.B list\-all\-zones: +List all zone names. +.TP +.B list\-zone \fIZONE\fP +Show all records for \fIZONE\fP\&. +.TP +.B load\-zone \fIZONE\fP \fIFILE\fP +Load records for \fIZONE\fP from \fIFILE\fP\&. If \fIZONE\fP already exists, all +records are overwritten, this operation is atomic. If \fIZONE\fP doesn\(aqt +exist, it is created. +.TP +.B rectify\-zone \fIZONE\fP +Calculates the \(aqordername\(aq and \(aqauth\(aq fields for a zone called +\fIZONE\fP so they comply with DNSSEC settings. Can be used to fix up +migrated data. Can always safely be run, it does no harm. +.TP +.B rectify\-all\-zones +Calculates the \(aqordername\(aq and \(aqauth\(aq fields for all zones so they +comply with DNSSEC settings. Can be used to fix up migrated data. +Can always safely be run, it does no harm. +.TP +.B replace\-rrset \fIZONE\fP \fINAME\fP \fITYPE\fP [\fITTL\fP] \fICONTENT\fP [\fICONTENT\fP\&..] +Replace existing \fINAME\fP in zone \fIZONE\fP with a new set. +.TP +.B secure\-zone \fIZONE\fP +Configures a zone called \fIZONE\fP with reasonable DNSSEC settings. You +should manually run \(aqpdnsutil rectify\-zone\(aq afterwards. +.TP +secure\-all\-zones [\fBincrease\-serial\fP] +Configures all zones that are not currently signed with reasonable +DNSSEC settings. Setting \fBincrease\-serial\fP will increase the +serial of those zones too. You should manually run \(aqpdnsutil +rectify\-all\-zones\(aq afterwards. +.TP +.B set\-kind \fIZONE\fP \fIKIND\fP +Change the kind of \fIZONE\fP to \fIKIND\fP (master, slave, native). +.TP +.B set\-account \fIZONE\fP \fIACCOUNT\fP +Change the account (owner) of \fIZONE\fP to \fIACCOUNT\fP\&. +.TP +.B add\-meta \fIZONE\fP \fIATTRIBUTE\fP \fIVALUE\fP [\fIVALUE\fP]... +Append \fIVALUE\fP to the existing \fIATTRIBUTE\fP metadata for \fIZONE\fP\&. +Will return an error if \fIATTRIBUTE\fP does not support multiple values, use +\fBset\-meta\fP for these values. +.TP +.B set\-meta \fIZONE\fP \fIATTRIBUTE\fP [\fIVALUE\fP]... +Set domainmetadata \fIATTRIBUTE\fP for \fIZONE\fP to \fIVALUE\fP\&. An empty value +clears it. +.TP +.B set\-presigned \fIZONE\fP +Switches \fIZONE\fP to presigned operation, utilizing in\-zone RRSIGs. +.TP +.B show\-zone \fIZONE\fP +Shows all DNSSEC related settings of a zone called \fIZONE\fP\&. +.TP +.B test\-schema \fIZONE\fP +Test database schema, this creates the zone \fIZONE\fP +.TP +.B unset\-presigned \fIZONE\fP +Disables presigned operation for \fIZONE\fP\&. +.UNINDENT +.SH DEBUGGING TOOLS +.INDENT 0.0 +.TP +.B backend\-cmd \fIBACKEND\fP \fICMD\fP [\fICMD..\fP] +Send a text command to a backend for execution. GSQL backends will +take SQL commands, other backends may take different things. Be +careful! +.TP +.B bench\-db [\fIFILE\fP] +Perform a benchmark of the backend\-database. +\fIFILE\fP can be a file with a list, one per line, of domain names to use for this. +If \fIFILE\fP is not specified, powerdns.com is used. +.UNINDENT +.SH OTHER TOOLS +.INDENT 0.0 +.TP +.B ipencrypt \fIIP\-ADDRESS\fP passsword +Encrypt an IP address according to the \(aqipcipher\(aq standard +.TP +.B ipdecrypt \fIIP\-ADDRESS\fP passsword +Encrypt an IP address according to the \(aqipcipher\(aq standard +.UNINDENT +.SH SEE ALSO +.sp +pdns_server (1), pdns_control (1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/saxfr.1 b/docs/saxfr.1 new file mode 100644 index 0000000..8d1a744 --- /dev/null +++ b/docs/saxfr.1 @@ -0,0 +1,58 @@ +.\" Man page generated from reStructuredText. +. +.TH "SAXFR" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +saxfr \- Perform AXFRs and show information about it +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBsaxfr\fP \fIIPADDRESS\fP \fIPORT\fP \fIZONE\fP [\fIOptions\fP] +.SH DESCRIPTION +.sp +\fBsaxfr\fP does a zone\-transfer (AXFR) of \fIZONE\fP from the nameserver at +\fIIPADDRESS\fP on port \fIPORT\fP and displays the transferred zone with NSEC3 +information truncated. See below how to show this information. +.SH OPTIONS +.INDENT 0.0 +.TP +.B showdetails +Show all the data in the NSEC3 and DNSKEY RDATA. +.TP +.B showflags +Show the NSEC3 flags in the RDATA. +.TP +.B unhash +Unhash the NSEC3 names to the normal names. +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/sdig.1 b/docs/sdig.1 new file mode 100644 index 0000000..ddf8829 --- /dev/null +++ b/docs/sdig.1 @@ -0,0 +1,76 @@ +.\" Man page generated from reStructuredText. +. +.TH "SDIG" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +sdig \- Perform a DNS query and show the results +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBsdig\fP \fIIP\-ADDRESS\-OR\-DOH\-URL * *PORT\fP \fIQNAME\fP \fIQTYPE\fP [\fIOPTION\fP] +.SH DESCRIPTION +.sp +\fBsdig\fP sends a DNS query to \fIIP\-ADDRESS\-OR\-DOH\-URL\fP on port \fIPORT\fP and displays +the answer in a formatted way. +If the address starts with an \fBh\fP, it is assumed to be a DoH endpoint, and \fIPORT\fP is ignored. +.SH OPTIONS +.sp +These options can be added to the commandline in any order. +.INDENT 0.0 +.TP +.B dnssec +Set the DO bit to request DNSSEC information. +.TP +.B ednssubnet \fISUBNET\fP +Send \fISUBNET\fP in the edns\-client\-subnet option. If this option is +not set, no edns\-client\-subnet option is set in the query. +.TP +.B hidesoadetails +Don\(aqt show the SOA serial in the response. +.TP +.B hidettl +Replace TTLs with \fI[ttl]\fP in the response. +.TP +.B recurse +Set the RD bit in the question. +.TP +.B showflags +Show the NSEC3 flags in the response (they are hidden by default). +.TP +.B tcp +Use TCP instead of UDP to send the query. +.TP +.B xpf \fIXPFCODE\fP \fIXPFVERSION\fP \fIXPFPROTO\fP \fIXPFSRC\fP \fIXPFSRC\fP +Send an \fIXPF\fP additional with these parameters. +.UNINDENT +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/zone2json.1 b/docs/zone2json.1 new file mode 100644 index 0000000..e9b9b44 --- /dev/null +++ b/docs/zone2json.1 @@ -0,0 +1,76 @@ +.\" Man page generated from reStructuredText. +. +.TH "ZONE2JSON" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +zone2json \- convert BIND zones to JSON +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBzone2json\fP {\fB\-\-named\-conf=\fP\fIPATH\fP, \fB\-\-zone\-file=\fP\fIPATH\fP [\fB\-\-zone\-name=\fP\fINAME\fP]} [\fIOPTION\fP] +.SH DESCRIPTION +.sp +\fBzone2json\fP parses BIND named.conf files and zonefiles and outputs +JSON on standard out, which can then be fed to the PowerDNS API. +.sp +\fBzone2json\fP understands the BIND master file extension \fB$GENERATE\fP +and will also honour \fB$ORIGIN\fP and \fB$TTL\fP\&. +.SH OPTIONS +.SH INPUT OPTIONS +.INDENT 0.0 +.TP +.BI \-\-named\-conf\fB= +Read \fIPATH\fP to get the BIND configuration +.TP +.BI \-\-zone\fB= +Parse only the zone file at \fIPATH\fP Conflicts with \fB\-\-named\-conf\fP parameter. +.TP +.BI \-\-zone\-name\fB= +When parsing a single zone without $ORIGIN statement, set \fIZONE\fP as the zone name. +.UNINDENT +.SH OTHER OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +List all options +.TP +.B \-\-on\-error\-resume\-next +Ignore missing zone files during parsing. Dangerous. +.TP +.B \-\-verbose +Be verbose during conversion. +.UNINDENT +.SH SEE ALSO +.sp +pdns_server(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/zone2ldap.1 b/docs/zone2ldap.1 new file mode 100644 index 0000000..7f0db8d --- /dev/null +++ b/docs/zone2ldap.1 @@ -0,0 +1,78 @@ +.\" Man page generated from reStructuredText. +. +.TH "ZONE2LDAP" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +zone2ldap \- convert zonefiles to ldif +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBzone2ldap\fP {\fB\-\-named\-conf=\fP\fIPATH\fP,\fB\-\-zone\-file=\fP\fIPATH\fP \fB\-\-zone\-name=\fP\fINAME\fP} [\fIOPTION\fP]... +.SH DESCRIPTION +.sp +\fBzone2ldap\fP is a program that converts BIND zonefiles to ldif format +which can inserted to an LDAP server. +.SH OPTIONS +.INDENT 0.0 +.TP +.B \-\-help +Show summary of options. +.TP +.BI \-\-basedn\fB= +Base DN to store objects below +.TP +.B \-\-dnsttl +Add dnsttl attribute to every entry +.TP +.BI \-\-layout\fB= +How to arrange entries in the directory ("simple" or "tree") +.TP +.BI \-\-named\-conf\fB= +Path to a BIND named.conf to parse +.TP +.B \-\-resume +Continue after errors +.TP +.B \-\-verbose +Verbose comments on operation +.TP +.BI \-\-zone\-file\fB= +Zone file to parse +.TP +.BI \-\-zone\-name\fB= +Specify a zone name if zone is set +.UNINDENT +.SH SEE ALSO +.sp +pdns_server(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/docs/zone2sql.1 b/docs/zone2sql.1 new file mode 100644 index 0000000..496c515 --- /dev/null +++ b/docs/zone2sql.1 @@ -0,0 +1,145 @@ +.\" Man page generated from reStructuredText. +. +.TH "ZONE2SQL" "1" "Nov 29, 2019" "4.2" "PowerDNS Authoritative Server" +.SH NAME +zone2sql \- convert BIND zones to SQL +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBzone2sql\fP {\fB\-\-named\-conf=\fP\fIPATH\fP,\fB\-\-zone\-file=\fP\fIPATH\fP [\fB\-\-zone\-name=\fP\fINAME\fP]} [\fIOptions\fP] +.SH DESCRIPTION +.sp +\fBzone2sql\fP parses BIND named.conf files and zonefiles and outputs SQL +on standard out, which can then be fed to your database. +.sp +\fBzone2sql\fP understands the BIND master file extension \fB$GENERATE\fP +and will also honour \fB$ORIGIN\fP and \fB$TTL\fP\&. +.sp +For backends supporting slave operation there is also an option to keep +slave zones as slaves, and not convert them to native operation. +.sp +\fBzone2sql\fP can generate SQL for the Generic MySQL, Generic PostgreSQL, +Generic SQLite3 and Generic Oracle backends. +.SH OPTIONS +.SH INPUT OPTIONS +.INDENT 0.0 +.TP +.BI \-\-named\-conf\fB= +Read \fIPATH\fP to get the BIND configuration +.TP +.BI \-\-zone\fB= +Parse only the zone file at \fIPATH\fP Conflicts with \fB\-\-named\-conf\fP parameter. +.TP +.BI \-\-zone\-name\fB= +When parsing a single zone without $ORIGIN statement, set \fIZONE\fP as +the zone name. +.UNINDENT +.SH BACKENDS +.INDENT 0.0 +.TP +.B \-\-gmysql +Output in format suitable for the default configuration of the +Generic MySQL backend. +.TP +.B \-\-gpgsql +Output in format suitable for the default configuration of the +Generic PostgreSQL backend. +.TP +.B \-\-gsqlite +Output in format suitable for the default configuration of the +Generic SQLite3 backend. +.TP +.B \-\-goracle +Output in format suitable for the default configuration of the +Generic Oracle backend. +.TP +.B \-\-mydns +Output in a format suitable for the MyDNS backend. +.TP +.B \-\-oracle +Output in format suitable for the default configuration of the +Oracle backend. +.UNINDENT +.SH OUTPUT OPTIONS +.INDENT 0.0 +.TP +.B \-\-json\-comments +Parse JSON in zonefile comments to set the \(aqdisabled\(aq and \(aqcomment\(aq +fields in the database. See \fIJSON COMMENTS\fP for more information. +.TP +.B \-\-transactions +If the target SQL backend supports transactions, wrap every domain +into a transaction for integrity and possibly higher speed. +.UNINDENT +.SH OTHER OPTIONS +.INDENT 0.0 +.TP +.B \-\-filter\-duplicate\-soa +If there\(aqs more than one SOA record in the zone (possibly because it +was AXFR\(aqd), ignore it. If this option is not set, all SOA records +in the zone are emitted. +.TP +.B \-\-help +List all options +.TP +.B \-\-on\-error\-resume\-next +Ignore missing zone files during parsing. Dangerous. +.TP +.B \-\-slave +Maintain slave status of zones listed in named.conf as being slaves. +The default behaviour is to convert all zones to native operation. +.TP +.B \-\-verbose +Be verbose during conversion. +.UNINDENT +.SH JSON COMMENTS +.sp +The Generic SQL backends have the \(aqcomment\(aq and \(aqdisabled\(aq fields in the +\(aqrecords\(aq table. The \(aqcomment\(aq field contains a comment for this record +(if any) and the \(aqdisabled\(aq field tells PowerDNS if the record can be +served to clients. +.sp +When a zonefile contains a comment like +\fB; json={"comment": "Something", "disabled": true}\fP and +\fB\-\-json\-comments\fP is provided, the \(aqcomment\(aq field will contain +"Something" and the \(aqdisabled\(aq field will be set to the database\(aqs +native true value. +.sp +WARNING: Using JSON comments to disable records means that the zone in +PowerDNS is different from the one served by BIND, as BIND does not +handle the disabled status in the comment. +.SH SEE ALSO +.sp +pdns_server(1) +.SH AUTHOR +PowerDNS.COM BV +.SH COPYRIGHT +2001-2019, PowerDNS.COM BV +.\" Generated by docutils manpage writer. +. diff --git a/ext/Makefile.am b/ext/Makefile.am new file mode 100644 index 0000000..7c0a42d --- /dev/null +++ b/ext/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS = \ + ipcrypt \ + json11 \ + yahttp + +DIST_SUBDIRS = \ + ipcrypt \ + json11 \ + yahttp + +EXTRA_DIST = \ + luawrapper/include/LuaContext.hpp diff --git a/ext/Makefile.in b/ext/Makefile.in new file mode 100644 index 0000000..1ff68f3 --- /dev/null +++ b/ext/Makefile.in @@ -0,0 +1,784 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = ext +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-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 +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = \ + ipcrypt \ + json11 \ + yahttp + +DIST_SUBDIRS = \ + ipcrypt \ + json11 \ + yahttp + +EXTRA_DIST = \ + luawrapper/include/LuaContext.hpp + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ext/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign ext/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || 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; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/ext/ipcrypt/LICENSE b/ext/ipcrypt/LICENSE new file mode 100644 index 0000000..0a199e5 --- /dev/null +++ b/ext/ipcrypt/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2015-2018, Frank Denis + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/ext/ipcrypt/Makefile.am b/ext/ipcrypt/Makefile.am new file mode 100644 index 0000000..cd66bfc --- /dev/null +++ b/ext/ipcrypt/Makefile.am @@ -0,0 +1,8 @@ +EXTRA_DIST = \ + LICENSE + +noinst_LTLIBRARIES = libipcrypt.la + +libipcrypt_la_SOURCES = \ + ipcrypt.c \ + ipcrypt.h diff --git a/ext/ipcrypt/Makefile.in b/ext/ipcrypt/Makefile.in new file mode 100644 index 0000000..9d18036 --- /dev/null +++ b/ext/ipcrypt/Makefile.in @@ -0,0 +1,750 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = ext/ipcrypt +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libipcrypt_la_LIBADD = +am_libipcrypt_la_OBJECTS = ipcrypt.lo +libipcrypt_la_OBJECTS = $(am_libipcrypt_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libipcrypt_la_SOURCES) +DIST_SOURCES = $(libipcrypt_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + LICENSE + +noinst_LTLIBRARIES = libipcrypt.la +libipcrypt_la_SOURCES = \ + ipcrypt.c \ + ipcrypt.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ext/ipcrypt/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign ext/ipcrypt/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libipcrypt.la: $(libipcrypt_la_OBJECTS) $(libipcrypt_la_DEPENDENCIES) $(EXTRA_libipcrypt_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libipcrypt_la_OBJECTS) $(libipcrypt_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipcrypt.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@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@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@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@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/ext/ipcrypt/ipcrypt.c b/ext/ipcrypt/ipcrypt.c new file mode 100644 index 0000000..6ef464a --- /dev/null +++ b/ext/ipcrypt/ipcrypt.c @@ -0,0 +1,87 @@ + +#include "ipcrypt.h" + +#define ROTL(X, R) (X) = (unsigned char) ((X) << (R)) | ((X) >> (8 - (R))) + +static void +arx_fwd(unsigned char state[4]) +{ + state[0] += state[1]; + state[2] += state[3]; + ROTL(state[1], 2); + ROTL(state[3], 5); + state[1] ^= state[0]; + state[3] ^= state[2]; + ROTL(state[0], 4); + state[0] += state[3]; + state[2] += state[1]; + ROTL(state[1], 3); + ROTL(state[3], 7); + state[1] ^= state[2]; + state[3] ^= state[0]; + ROTL(state[2], 4); +} + +static void +arx_bwd(unsigned char state[4]) +{ + ROTL(state[2], 4); + state[1] ^= state[2]; + state[3] ^= state[0]; + ROTL(state[1], 5); + ROTL(state[3], 1); + state[0] -= state[3]; + state[2] -= state[1]; + ROTL(state[0], 4); + state[1] ^= state[0]; + state[3] ^= state[2]; + ROTL(state[1], 6); + ROTL(state[3], 3); + state[0] -= state[1]; + state[2] -= state[3]; +} + +static inline void +xor4(unsigned char *out, const unsigned char *x, const unsigned char *y) +{ + out[0] = x[0] ^ y[0]; + out[1] = x[1] ^ y[1]; + out[2] = x[2] ^ y[2]; + out[3] = x[3] ^ y[3]; +} + +int +ipcrypt_encrypt(unsigned char out[IPCRYPT_BYTES], + const unsigned char in[IPCRYPT_BYTES], + const unsigned char key[IPCRYPT_KEYBYTES]) +{ + unsigned char state[4]; + + xor4(state, in, key); + arx_fwd(state); + xor4(state, state, key + 4); + arx_fwd(state); + xor4(state, state, key + 8); + arx_fwd(state); + xor4(out, state, key + 12); + + return 0; +} + +int +ipcrypt_decrypt(unsigned char out[IPCRYPT_BYTES], + const unsigned char in[IPCRYPT_BYTES], + const unsigned char key[IPCRYPT_KEYBYTES]) +{ + unsigned char state[4]; + + xor4(state, in, key + 12); + arx_bwd(state); + xor4(state, state, key + 8); + arx_bwd(state); + xor4(state, state, key + 4); + arx_bwd(state); + xor4(out, state, key); + + return 0; +} diff --git a/ext/ipcrypt/ipcrypt.h b/ext/ipcrypt/ipcrypt.h new file mode 100644 index 0000000..76b94f5 --- /dev/null +++ b/ext/ipcrypt/ipcrypt.h @@ -0,0 +1,24 @@ + +#ifndef ipcrypt_H +#define ipcrypt_H + +#define IPCRYPT_BYTES 4 +#define IPCRYPT_KEYBYTES 16 + +#ifdef __cplusplus +extern "C" { +#endif + +int ipcrypt_encrypt(unsigned char out[IPCRYPT_BYTES], + const unsigned char in[IPCRYPT_BYTES], + const unsigned char key[IPCRYPT_KEYBYTES]); + +int ipcrypt_decrypt(unsigned char out[IPCRYPT_BYTES], + const unsigned char in[IPCRYPT_BYTES], + const unsigned char key[IPCRYPT_KEYBYTES]); + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif + +#endif diff --git a/ext/json11/Makefile.am b/ext/json11/Makefile.am new file mode 100644 index 0000000..df5f856 --- /dev/null +++ b/ext/json11/Makefile.am @@ -0,0 +1,2 @@ +noinst_LTLIBRARIES = libjson11.la +libjson11_la_SOURCES = json11.cpp json11.hpp diff --git a/ext/json11/Makefile.in b/ext/json11/Makefile.in new file mode 100644 index 0000000..c53b190 --- /dev/null +++ b/ext/json11/Makefile.in @@ -0,0 +1,762 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = ext/json11 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libjson11_la_LIBADD = +am_libjson11_la_OBJECTS = json11.lo +libjson11_la_OBJECTS = $(am_libjson11_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libjson11_la_SOURCES) +DIST_SOURCES = $(libjson11_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libjson11.la +libjson11_la_SOURCES = json11.cpp json11.hpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ext/json11/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign ext/json11/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libjson11.la: $(libjson11_la_OBJECTS) $(libjson11_la_DEPENDENCIES) $(EXTRA_libjson11_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libjson11_la_OBJECTS) $(libjson11_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json11.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/ext/json11/json11.cpp b/ext/json11/json11.cpp new file mode 100644 index 0000000..f48833b --- /dev/null +++ b/ext/json11/json11.cpp @@ -0,0 +1,784 @@ +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "json11.hpp" +#include +#include +#include +#include +#include +#include + +namespace json11 { + +static const int max_depth = 200; + +using std::string; +using std::vector; +using std::map; +using std::make_shared; +using std::initializer_list; +using std::move; + +/* Helper for representing null - just a do-nothing struct, plus comparison + * operators so the helpers in JsonValue work. We can't use nullptr_t because + * it may not be orderable. + */ +struct NullStruct { + bool operator==(NullStruct) const { return true; } + bool operator<(NullStruct) const { return false; } +}; + +/* * * * * * * * * * * * * * * * * * * * + * Serialization + */ + +static void dump(NullStruct, string &out) { + out += "null"; +} + +static void dump(double value, string &out) { + if (std::isfinite(value)) { + char buf[32]; + snprintf(buf, sizeof buf, "%.17g", value); + out += buf; + } else { + out += "null"; + } +} + +static void dump(int value, string &out) { + char buf[32]; + snprintf(buf, sizeof buf, "%d", value); + out += buf; +} + +static void dump(bool value, string &out) { + out += value ? "true" : "false"; +} + +static void dump(const string &value, string &out) { + out += '"'; + for (size_t i = 0; i < value.length(); i++) { + const char ch = value[i]; + if (ch == '\\') { + out += "\\\\"; + } else if (ch == '"') { + out += "\\\""; + } else if (ch == '\b') { + out += "\\b"; + } else if (ch == '\f') { + out += "\\f"; + } else if (ch == '\n') { + out += "\\n"; + } else if (ch == '\r') { + out += "\\r"; + } else if (ch == '\t') { + out += "\\t"; + } else if (static_cast(ch) <= 0x1f) { + char buf[8]; + snprintf(buf, sizeof buf, "\\u%04x", ch); + out += buf; + } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 + && static_cast(value[i+2]) == 0xa8) { + out += "\\u2028"; + i += 2; + } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 + && static_cast(value[i+2]) == 0xa9) { + out += "\\u2029"; + i += 2; + } else { + out += ch; + } + } + out += '"'; +} + +static void dump(const Json::array &values, string &out) { + bool first = true; + out += "["; + for (const auto &value : values) { + if (!first) + out += ", "; + value.dump(out); + first = false; + } + out += "]"; +} + +static void dump(const Json::object &values, string &out) { + bool first = true; + out += "{"; + for (const auto &kv : values) { + if (!first) + out += ", "; + dump(kv.first, out); + out += ": "; + kv.second.dump(out); + first = false; + } + out += "}"; +} + +void Json::dump(string &out) const { + m_ptr->dump(out); +} + +/* * * * * * * * * * * * * * * * * * * * + * Value wrappers + */ + +template +class Value : public JsonValue { +protected: + + // Constructors + explicit Value(const T &value) : m_value(value) {} + explicit Value(T &&value) : m_value(move(value)) {} + + // Get type tag + Json::Type type() const override { + return tag; + } + + // Comparisons + bool equals(const JsonValue * other) const override { + return m_value == static_cast *>(other)->m_value; + } + bool less(const JsonValue * other) const override { + return m_value < static_cast *>(other)->m_value; + } + + const T m_value; + void dump(string &out) const override { json11::dump(m_value, out); } +}; + +class JsonDouble final : public Value { + double number_value() const override { return m_value; } + int int_value() const override { return static_cast(m_value); } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonDouble(double value) : Value(value) {} +}; + +class JsonInt final : public Value { + double number_value() const override { return m_value; } + int int_value() const override { return m_value; } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonInt(int value) : Value(value) {} +}; + +class JsonBoolean final : public Value { + bool bool_value() const override { return m_value; } +public: + explicit JsonBoolean(bool value) : Value(value) {} +}; + +class JsonString final : public Value { + const string &string_value() const override { return m_value; } +public: + explicit JsonString(const string &value) : Value(value) {} + explicit JsonString(string &&value) : Value(move(value)) {} +}; + +class JsonArray final : public Value { + const Json::array &array_items() const override { return m_value; } + const Json & operator[](size_t i) const override; +public: + explicit JsonArray(const Json::array &value) : Value(value) {} + explicit JsonArray(Json::array &&value) : Value(move(value)) {} +}; + +class JsonObject final : public Value { + const Json::object &object_items() const override { return m_value; } + const Json & operator[](const string &key) const override; +public: + explicit JsonObject(const Json::object &value) : Value(value) {} + explicit JsonObject(Json::object &&value) : Value(move(value)) {} +}; + +class JsonNull final : public Value { +public: + JsonNull() : Value({}) {} +}; + +/* * * * * * * * * * * * * * * * * * * * + * Static globals - static-init-safe + */ +struct Statics { + const std::shared_ptr null = make_shared(); + const std::shared_ptr t = make_shared(true); + const std::shared_ptr f = make_shared(false); + const string empty_string; + const vector empty_vector; + const map empty_map; + Statics() {} +}; + +static const Statics & statics() { + static const Statics s {}; + return s; +} + +static const Json & static_null() { + // This has to be separate, not in Statics, because Json() accesses statics().null. + static const Json json_null; + return json_null; +} + +/* * * * * * * * * * * * * * * * * * * * + * Constructors + */ + +Json::Json() noexcept : m_ptr(statics().null) {} +Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} +Json::Json(double value) : m_ptr(make_shared(value)) {} +Json::Json(int value) : m_ptr(make_shared(value)) {} +Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} +Json::Json(const string &value) : m_ptr(make_shared(value)) {} +Json::Json(string &&value) : m_ptr(make_shared(move(value))) {} +Json::Json(const char * value) : m_ptr(make_shared(value)) {} +Json::Json(const Json::array &values) : m_ptr(make_shared(values)) {} +Json::Json(Json::array &&values) : m_ptr(make_shared(move(values))) {} +Json::Json(const Json::object &values) : m_ptr(make_shared(values)) {} +Json::Json(Json::object &&values) : m_ptr(make_shared(move(values))) {} + +/* * * * * * * * * * * * * * * * * * * * + * Accessors + */ + +Json::Type Json::type() const { return m_ptr->type(); } +double Json::number_value() const { return m_ptr->number_value(); } +int Json::int_value() const { return m_ptr->int_value(); } +bool Json::bool_value() const { return m_ptr->bool_value(); } +const string & Json::string_value() const { return m_ptr->string_value(); } +const vector & Json::array_items() const { return m_ptr->array_items(); } +const map & Json::object_items() const { return m_ptr->object_items(); } +const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; } +const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; } + +double JsonValue::number_value() const { return 0; } +int JsonValue::int_value() const { return 0; } +bool JsonValue::bool_value() const { return false; } +const string & JsonValue::string_value() const { return statics().empty_string; } +const vector & JsonValue::array_items() const { return statics().empty_vector; } +const map & JsonValue::object_items() const { return statics().empty_map; } +const Json & JsonValue::operator[] (size_t) const { return static_null(); } +const Json & JsonValue::operator[] (const string &) const { return static_null(); } + +const Json & JsonObject::operator[] (const string &key) const { + auto iter = m_value.find(key); + return (iter == m_value.end()) ? static_null() : iter->second; +} +const Json & JsonArray::operator[] (size_t i) const { + if (i >= m_value.size()) return static_null(); + else return m_value[i]; +} + +/* * * * * * * * * * * * * * * * * * * * + * Comparison + */ + +bool Json::operator== (const Json &other) const { + if (m_ptr->type() != other.m_ptr->type()) + return false; + + return m_ptr->equals(other.m_ptr.get()); +} + +bool Json::operator< (const Json &other) const { + if (m_ptr->type() != other.m_ptr->type()) + return m_ptr->type() < other.m_ptr->type(); + + return m_ptr->less(other.m_ptr.get()); +} + +/* * * * * * * * * * * * * * * * * * * * + * Parsing + */ + +/* esc(c) + * + * Format char c suitable for printing in an error message. + */ +static inline string esc(char c) { + char buf[12]; + if (static_cast(c) >= 0x20 && static_cast(c) <= 0x7f) { + snprintf(buf, sizeof buf, "'%c' (%d)", c, c); + } else { + snprintf(buf, sizeof buf, "(%d)", c); + } + return string(buf); +} + +static inline bool in_range(long x, long lower, long upper) { + return (x >= lower && x <= upper); +} + +namespace { +/* JsonParser + * + * Object that tracks all state of an in-progress parse. + */ +struct JsonParser final { + + /* State + */ + const string &str; + size_t i; + string &err; + bool failed; + const JsonParse strategy; + + /* fail(msg, err_ret = Json()) + * + * Mark this parse as failed. + */ + Json fail(string &&msg) { + return fail(move(msg), Json()); + } + + template + T fail(string &&msg, const T err_ret) { + if (!failed) + err = std::move(msg); + failed = true; + return err_ret; + } + + /* consume_whitespace() + * + * Advance until the current character is non-whitespace. + */ + void consume_whitespace() { + while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t') + i++; + } + + /* consume_comment() + * + * Advance comments (c-style inline and multiline). + */ + bool consume_comment() { + bool comment_found = false; + if (str[i] == '/') { + i++; + if (i == str.size()) + return fail("unexpected end of input inside comment", false); + if (str[i] == '/') { // inline comment + i++; + if (i == str.size()) + return fail("unexpected end of input inside inline comment", false); + // advance until next line + while (str[i] != '\n') { + i++; + if (i == str.size()) + return fail("unexpected end of input inside inline comment", false); + } + comment_found = true; + } + else if (str[i] == '*') { // multiline comment + i++; + if (i > str.size()-2) + return fail("unexpected end of input inside multi-line comment", false); + // advance until closing tokens + while (!(str[i] == '*' && str[i+1] == '/')) { + i++; + if (i > str.size()-2) + return fail( + "unexpected end of input inside multi-line comment", false); + } + i += 2; + if (i == str.size()) + return fail( + "unexpected end of input inside multi-line comment", false); + comment_found = true; + } + else + return fail("malformed comment", false); + } + return comment_found; + } + + /* consume_garbage() + * + * Advance until the current character is non-whitespace and non-comment. + */ + void consume_garbage() { + consume_whitespace(); + if(strategy == JsonParse::COMMENTS) { + bool comment_found = false; + do { + comment_found = consume_comment(); + consume_whitespace(); + } + while(comment_found); + } + } + + /* get_next_token() + * + * Return the next non-whitespace character. If the end of the input is reached, + * flag an error and return 0. + */ + char get_next_token() { + consume_garbage(); + if (i == str.size()) + return fail("unexpected end of input", (char)0); + + return str[i++]; + } + + /* encode_utf8(pt, out) + * + * Encode pt as UTF-8 and add it to out. + */ + void encode_utf8(long pt, string & out) { + if (pt < 0) + return; + + if (pt < 0x80) { + out += static_cast(pt); + } else if (pt < 0x800) { + out += static_cast((pt >> 6) | 0xC0); + out += static_cast((pt & 0x3F) | 0x80); + } else if (pt < 0x10000) { + out += static_cast((pt >> 12) | 0xE0); + out += static_cast(((pt >> 6) & 0x3F) | 0x80); + out += static_cast((pt & 0x3F) | 0x80); + } else { + out += static_cast((pt >> 18) | 0xF0); + out += static_cast(((pt >> 12) & 0x3F) | 0x80); + out += static_cast(((pt >> 6) & 0x3F) | 0x80); + out += static_cast((pt & 0x3F) | 0x80); + } + } + + /* parse_string() + * + * Parse a string, starting at the current position. + */ + string parse_string() { + string out; + long last_escaped_codepoint = -1; + while (true) { + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + char ch = str[i++]; + + if (ch == '"') { + encode_utf8(last_escaped_codepoint, out); + return out; + } + + if (in_range(ch, 0, 0x1f)) + return fail("unescaped " + esc(ch) + " in string", ""); + + // The usual case: non-escaped characters + if (ch != '\\') { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + out += ch; + continue; + } + + // Handle escapes + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + ch = str[i++]; + + if (ch == 'u') { + // Extract 4-byte escape sequence + string esc = str.substr(i, 4); + // Explicitly check length of the substring. The following loop + // relies on std::string returning the terminating NUL when + // accessing str[length]. Checking here reduces brittleness. + if (esc.length() < 4) { + return fail("bad \\u escape: " + esc, ""); + } + for (size_t j = 0; j < 4; j++) { + if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') + && !in_range(esc[j], '0', '9')) + return fail("bad \\u escape: " + esc, ""); + } + + long codepoint = strtol(esc.data(), nullptr, 16); + + // JSON specifies that characters outside the BMP shall be encoded as a pair + // of 4-hex-digit \u escapes encoding their surrogate pair components. Check + // whether we're in the middle of such a beast: the previous codepoint was an + // escaped lead (high) surrogate, and this is a trail (low) surrogate. + if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) + && in_range(codepoint, 0xDC00, 0xDFFF)) { + // Reassemble the two surrogate pairs into one astral-plane character, per + // the UTF-16 algorithm. + encode_utf8((((last_escaped_codepoint - 0xD800) << 10) + | (codepoint - 0xDC00)) + 0x10000, out); + last_escaped_codepoint = -1; + } else { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = codepoint; + } + + i += 4; + continue; + } + + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + + if (ch == 'b') { + out += '\b'; + } else if (ch == 'f') { + out += '\f'; + } else if (ch == 'n') { + out += '\n'; + } else if (ch == 'r') { + out += '\r'; + } else if (ch == 't') { + out += '\t'; + } else if (ch == '"' || ch == '\\' || ch == '/') { + out += ch; + } else { + return fail("invalid escape character " + esc(ch), ""); + } + } + } + + /* parse_number() + * + * Parse a double. + */ + Json parse_number() { + size_t start_pos = i; + + if (str[i] == '-') + i++; + + // Integer part + if (str[i] == '0') { + i++; + if (in_range(str[i], '0', '9')) + return fail("leading 0s not permitted in numbers"); + } else if (in_range(str[i], '1', '9')) { + i++; + while (in_range(str[i], '0', '9')) + i++; + } else { + return fail("invalid " + esc(str[i]) + " in number"); + } + + if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' + && (i - start_pos) <= static_cast(std::numeric_limits::digits10)) { + return std::atoi(str.c_str() + start_pos); + } + + // Decimal part + if (str[i] == '.') { + i++; + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in fractional part"); + + while (in_range(str[i], '0', '9')) + i++; + } + + // Exponent part + if (str[i] == 'e' || str[i] == 'E') { + i++; + + if (str[i] == '+' || str[i] == '-') + i++; + + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in exponent"); + + while (in_range(str[i], '0', '9')) + i++; + } + + return std::strtod(str.c_str() + start_pos, nullptr); + } + + /* expect(str, res) + * + * Expect that 'str' starts at the character that was just read. If it does, advance + * the input and return res. If not, flag an error. + */ + Json expect(const string &expected, Json res) { + assert(i != 0); + i--; + if (str.compare(i, expected.length(), expected) == 0) { + i += expected.length(); + return res; + } else { + return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length())); + } + } + + /* parse_json() + * + * Parse a JSON object. + */ + Json parse_json(int depth) { + if (depth > max_depth) { + return fail("exceeded maximum nesting depth"); + } + + char ch = get_next_token(); + if (failed) + return Json(); + + if (ch == '-' || (ch >= '0' && ch <= '9')) { + i--; + return parse_number(); + } + + if (ch == 't') + return expect("true", true); + + if (ch == 'f') + return expect("false", false); + + if (ch == 'n') + return expect("null", Json()); + + if (ch == '"') + return parse_string(); + + if (ch == '{') { + map data; + ch = get_next_token(); + if (ch == '}') + return data; + + while (1) { + if (ch != '"') + return fail("expected '\"' in object, got " + esc(ch)); + + string key = parse_string(); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch != ':') + return fail("expected ':' in object, got " + esc(ch)); + + data[std::move(key)] = parse_json(depth + 1); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == '}') + break; + if (ch != ',') + return fail("expected ',' in object, got " + esc(ch)); + + ch = get_next_token(); + } + return data; + } + + if (ch == '[') { + vector data; + ch = get_next_token(); + if (ch == ']') + return data; + + while (1) { + i--; + data.push_back(parse_json(depth + 1)); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == ']') + break; + if (ch != ',') + return fail("expected ',' in list, got " + esc(ch)); + + ch = get_next_token(); + (void)ch; + } + return data; + } + + return fail("expected value, got " + esc(ch)); + } +}; +}//namespace { + +Json Json::parse(const string &in, string &err, JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + Json result = parser.parse_json(0); + + // Check for any trailing garbage + parser.consume_garbage(); + if (parser.i != in.size()) + return parser.fail("unexpected trailing " + esc(in[parser.i])); + + return result; +} + +// Documented in json11.hpp +vector Json::parse_multi(const string &in, + std::string::size_type &parser_stop_pos, + string &err, + JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + parser_stop_pos = 0; + vector json_vec; + while (parser.i != in.size() && !parser.failed) { + json_vec.push_back(parser.parse_json(0)); + // Check for another object + parser.consume_garbage(); + if (!parser.failed) + parser_stop_pos = parser.i; + } + return json_vec; +} + +/* * * * * * * * * * * * * * * * * * * * + * Shape-checking + */ + +bool Json::has_shape(const shape & types, string & err) const { + if (!is_object()) { + err = "expected JSON object, got " + dump(); + return false; + } + + for (auto & item : types) { + if ((*this)[item.first].type() != item.second) { + err = "bad type for " + item.first + " in " + dump(); + return false; + } + } + + return true; +} + +} // namespace json11 diff --git a/ext/json11/json11.hpp b/ext/json11/json11.hpp new file mode 100644 index 0000000..a68394b --- /dev/null +++ b/ext/json11/json11.hpp @@ -0,0 +1,232 @@ +/* json11 + * + * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. + * + * The core object provided by the library is json11::Json. A Json object represents any JSON + * value: null, bool, number (int or double), string (std::string), array (std::vector), or + * object (std::map). + * + * Json objects act like values: they can be assigned, copied, moved, compared for equality or + * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and + * Json::parse (static) to parse a std::string as a Json object. + * + * Internally, the various types of Json object are represented by the JsonValue class + * hierarchy. + * + * A note on numbers - JSON specifies the syntax of number formatting but not its semantics, + * so some JSON implementations distinguish between integers and floating-point numbers, while + * some don't. In json11, we choose the latter. Because some JSON implementations (namely + * JavaScript itself) treat all numbers as the same type, distinguishing the two leads + * to JSON that will be *silently* changed by a round-trip through those implementations. + * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also + * provides integer helpers. + * + * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the + * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64 + * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch + * will be exact for +/- 275 years.) + */ + +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #if _MSC_VER <= 1800 // VS 2013 + #ifndef noexcept + #define noexcept throw() + #endif + + #ifndef snprintf + #define snprintf _snprintf_s + #endif + #endif +#endif + +namespace json11 { + +enum JsonParse { + STANDARD, COMMENTS +}; + +class JsonValue; + +class Json final { +public: + // Types + enum Type { + NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT + }; + + // Array and object typedefs + typedef std::vector array; + typedef std::map object; + + // Constructors for the various types of JSON value. + Json() noexcept; // NUL + Json(std::nullptr_t) noexcept; // NUL + Json(double value); // NUMBER + Json(int value); // NUMBER + Json(bool value); // BOOL + Json(const std::string &value); // STRING + Json(std::string &&value); // STRING + Json(const char * value); // STRING + Json(const array &values); // ARRAY + Json(array &&values); // ARRAY + Json(const object &values); // OBJECT + Json(object &&values); // OBJECT + + // Implicit constructor: anything with a to_json() function. + template + Json(const T & t) : Json(t.to_json()) {} + + // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) + template ::value + && std::is_constructible::value, + int>::type = 0> + Json(const M & m) : Json(object(m.begin(), m.end())) {} + + // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) + template ::value, + int>::type = 0> + Json(const V & v) : Json(array(v.begin(), v.end())) {} + + // This prevents Json(some_pointer) from accidentally producing a bool. Use + // Json(bool(some_pointer)) if that behavior is desired. + Json(void *) = delete; + + // Accessors + Type type() const; + + bool is_null() const { return type() == NUL; } + bool is_number() const { return type() == NUMBER; } + bool is_bool() const { return type() == BOOL; } + bool is_string() const { return type() == STRING; } + bool is_array() const { return type() == ARRAY; } + bool is_object() const { return type() == OBJECT; } + + // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not + // distinguish between integer and non-integer numbers - number_value() and int_value() + // can both be applied to a NUMBER-typed object. + double number_value() const; + int int_value() const; + + // Return the enclosed value if this is a boolean, false otherwise. + bool bool_value() const; + // Return the enclosed string if this is a string, "" otherwise. + const std::string &string_value() const; + // Return the enclosed std::vector if this is an array, or an empty vector otherwise. + const array &array_items() const; + // Return the enclosed std::map if this is an object, or an empty map otherwise. + const object &object_items() const; + + // Return a reference to arr[i] if this is an array, Json() otherwise. + const Json & operator[](size_t i) const; + // Return a reference to obj[key] if this is an object, Json() otherwise. + const Json & operator[](const std::string &key) const; + + // Serialize. + void dump(std::string &out) const; + std::string dump() const { + std::string out; + dump(out); + return out; + } + + // Parse. If parse fails, return Json() and assign an error message to err. + static Json parse(const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + static Json parse(const char * in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + if (in) { + return parse(std::string(in), err, strategy); + } else { + err = "null input"; + return nullptr; + } + } + // Parse multiple objects, concatenated or separated by whitespace + static std::vector parse_multi( + const std::string & in, + std::string::size_type & parser_stop_pos, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + + static inline std::vector parse_multi( + const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + std::string::size_type parser_stop_pos; + return parse_multi(in, parser_stop_pos, err, strategy); + } + + bool operator== (const Json &rhs) const; + bool operator< (const Json &rhs) const; + bool operator!= (const Json &rhs) const { return !(*this == rhs); } + bool operator<= (const Json &rhs) const { return !(rhs < *this); } + bool operator> (const Json &rhs) const { return (rhs < *this); } + bool operator>= (const Json &rhs) const { return !(*this < rhs); } + + /* has_shape(types, err) + * + * Return true if this is a JSON object and, for each item in types, has a field of + * the given type. If not, return false and set err to a descriptive message. + */ + typedef std::initializer_list> shape; + bool has_shape(const shape & types, std::string & err) const; + +private: + std::shared_ptr m_ptr; +}; + +// Internal class hierarchy - JsonValue objects are not exposed to users of this API. +class JsonValue { +protected: + friend class Json; + friend class JsonInt; + friend class JsonDouble; + virtual Json::Type type() const = 0; + virtual bool equals(const JsonValue * other) const = 0; + virtual bool less(const JsonValue * other) const = 0; + virtual void dump(std::string &out) const = 0; + virtual double number_value() const; + virtual int int_value() const; + virtual bool bool_value() const; + virtual const std::string &string_value() const; + virtual const Json::array &array_items() const; + virtual const Json &operator[](size_t i) const; + virtual const Json::object &object_items() const; + virtual const Json &operator[](const std::string &key) const; + virtual ~JsonValue() {} +}; + +} // namespace json11 diff --git a/ext/luawrapper/include/LuaContext.hpp b/ext/luawrapper/include/LuaContext.hpp new file mode 100644 index 0000000..b4c9ef1 --- /dev/null +++ b/ext/luawrapper/include/LuaContext.hpp @@ -0,0 +1,2960 @@ +/* +Copyright (c) 2013, Pierre KRIEGER +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef INCLUDE_LUACONTEXT_HPP +#define INCLUDE_LUACONTEXT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# include "misc/exception.hpp" +#endif + +#ifdef __GNUC__ +# define ATTR_UNUSED __attribute__((unused)) +#else +# define ATTR_UNUSED +#endif + +#define LUACONTEXT_GLOBAL_EQ "e5ddced079fc405aa4937b386ca387d2" +#define EQ_FUNCTION_NAME "__eq" +#define TOSTRING_FUNCTION_NAME "__tostring" + +/** + * Defines a Lua context + * A Lua context is used to interpret Lua code. Since everything in Lua is a variable (including functions), + * we only provide few functions like readVariable and writeVariable. + * + * You can also write variables with C++ functions so that they are callable by Lua. Note however that you HAVE TO convert + * your function to std::function (not directly std::bind or a lambda function) so the class can detect which argument types + * it wants. These arguments may only be of basic types (int, float, etc.) or std::string. + */ + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + +class LuaContext { + struct ValueInRegistry; + template struct Binder; + template struct IsOptional; + enum Globals_t { Globals }; // tag for "global variables" +public: + /** + * @param openDefaultLibs True if luaL_openlibs should be called + */ + explicit LuaContext(bool openDefaultLibs = true) + { + // luaL_newstate can return null if allocation failed + mState = luaL_newstate(); + if (mState == nullptr) + throw std::bad_alloc(); + + // setting the panic function + lua_atpanic(mState, [](lua_State* state) -> int { + const std::string str = lua_tostring(state, -1); + lua_pop(state, 1); + assert(false && "lua_atpanic triggered"); + exit(0); + }); + + // opening default library if required to do so + if (openDefaultLibs) + luaL_openlibs(mState); + + writeGlobalEq(); + } + + void writeGlobalEq() { + const auto eqFunction = [](lua_State* lua) -> int { + try { + lua_pushstring(lua, "__eq"); + lua_gettable(lua, -2); + /* if not found, return false */ + if (lua_isnil(lua, -1)) { + lua_pop(lua, -2); + lua_pushboolean(lua, false); + return 1; + } + lua_insert(lua, lua_gettop(lua)-2); + return callRaw(lua, PushedObject{lua, 3}, 1).release(); + } catch(...) { + Pusher::push(lua, std::current_exception()).release(); + luaError(lua); + } + }; + lua_pushcfunction(mState, eqFunction); + lua_setglobal(mState, LUACONTEXT_GLOBAL_EQ); + }; + + /** + * Move constructor + */ + LuaContext(LuaContext&& s) : + mState(s.mState) + { + s.mState = luaL_newstate(); + } + + /** + * Move operator + */ + LuaContext& operator=(LuaContext&& s) noexcept + { + std::swap(mState, s.mState); + return *this; + } + + /** + * Copy is forbidden + */ + LuaContext(const LuaContext&) = delete; + + /** + * Copy is forbidden + */ + LuaContext& operator=(const LuaContext&) = delete; + + /** + * Destructor + */ + ~LuaContext() noexcept + { + assert(mState); + lua_close(mState); + } + + /** + * Thrown when an error happens during execution of lua code (like not enough parameters for a function) + */ + class ExecutionErrorException : public std::runtime_error + { + public: + ExecutionErrorException(const std::string& msg) : + std::runtime_error(msg) + { + } + }; + + /** + * Thrown when a syntax error happens in a lua script + */ + class SyntaxErrorException : public std::runtime_error + { + public: + SyntaxErrorException(const std::string& msg) : + std::runtime_error(msg) + { + } + }; + + /** + * Thrown when trying to cast a Lua variable to an unvalid type, eg. trying to read a number when the variable is a string + */ + class WrongTypeException : public std::runtime_error + { + public: + WrongTypeException(std::string luaType_, const std::type_info& destination_) : + std::runtime_error("Trying to cast a lua variable from \"" + luaType_ + "\" to \"" + destination_.name() + "\""), + luaType(luaType_), + destination(destination_) + { + } + + std::string luaType; + const std::type_info& destination; + }; + + /** + * Function object that can call a function stored by Lua + * This type is copiable and movable, but not constructible. It can only be created through readVariable. + * @tparam TFunctionType Function type (eg. "int (int, bool)") + */ + template + class LuaFunctionCaller; + + /** + * Opaque type that identifies a Lua object + */ + struct LuaObject { + LuaObject() = default; + LuaObject(lua_State* state, int index=-1) { + this->objectInRegistry = std::make_shared(state, index); + } + std::shared_ptr objectInRegistry; + }; + + /** + * Opaque type that identifies a Lua thread + */ + struct ThreadID { + ThreadID() = default; + ThreadID(ThreadID&& o) : state(o.state), threadInRegistry(std::move(o.threadInRegistry)) { } + ThreadID& operator=(ThreadID&& o) { std::swap(state, o.state); std::swap(threadInRegistry, o.threadInRegistry); return *this; } + public: + friend LuaContext; + lua_State* state; + std::unique_ptr threadInRegistry; + }; + + /** + * Type that is considered as an empty array + */ + enum EmptyArray_t { EmptyArray }; + + /** + * Type for a metatable + */ + enum Metatable_t { Metatable }; + + /** + * Executes lua code from the stream + * @param code A stream that Lua will read its code from + */ + void executeCode(std::istream& code) + { + auto toCall = load(mState, code); + call>(mState, std::move(toCall)); + } + + /** + * Executes lua code from the stream and returns a value + * @param code A stream that Lua will read its code from + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(std::istream& code) + -> TType + { + auto toCall = load(mState, code); + return call(mState, std::move(toCall)); + } + + /** + * Executes lua code given as parameter + * @param code A string containing code that will be executed by Lua + */ + void executeCode(const std::string& code) + { + executeCode(code.c_str()); + } + + /* + * Executes Lua code from the stream and returns a value + * @param code A string containing code that will be executed by Lua + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(const std::string& code) + -> TType + { + return executeCode(code.c_str()); + } + + /** + * Executes Lua code + * @param code A string containing code that will be executed by Lua + */ + void executeCode(const char* code) + { + auto toCall = load(mState, code); + call>(mState, std::move(toCall)); + } + + /* + * Executes Lua code from the stream and returns a value + * @param code A string containing code that will be executed by Lua + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(const char* code) + -> TType + { + auto toCall = load(mState, code); + return call(mState, std::move(toCall)); + } + + /** + * Executes lua code from the stream + * @param code A stream that Lua will read its code from + */ + void executeCode(const ThreadID& thread, std::istream& code) + { + auto toCall = load(thread.state, code); + call>(thread.state, std::move(toCall)); + } + + /** + * Executes lua code from the stream and returns a value + * @param code A stream that Lua will read its code from + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(const ThreadID& thread, std::istream& code) + -> TType + { + auto toCall = load(thread.state, code); + return call(thread.state, std::move(toCall)); + } + + /** + * Executes lua code given as parameter + * @param code A string containing code that will be executed by Lua + */ + void executeCode(const ThreadID& thread, const std::string& code) + { + executeCode(thread, code.c_str()); + } + + /* + * Executes Lua code from the stream and returns a value + * @param code A string containing code that will be executed by Lua + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(const ThreadID& thread, const std::string& code) + -> TType + { + return executeCode(thread, code.c_str()); + } + + /** + * Executes Lua code + * @param code A string containing code that will be executed by Lua + */ + void executeCode(const ThreadID& thread, const char* code) + { + auto toCall = load(thread.state, code); + call>(thread.state, std::move(toCall)); + } + + /* + * Executes Lua code from the stream and returns a value + * @param code A string containing code that will be executed by Lua + * @tparam TType The type that the executing code should return + */ + template + auto executeCode(const ThreadID& thread, const char* code) + -> TType + { + auto toCall = load(thread.state, code); + return call(thread.state, std::move(toCall)); + } + + /** + * Tells that Lua will be allowed to access an object's function + * This is the version "registerFunction(name, &Foo::function)" + */ + template + auto registerFunction(const std::string& name, TPointerToMemberFunction pointer) + -> typename std::enable_if::value>::type + { + registerFunctionImpl(name, std::mem_fn(pointer), tag{}); + } + + /** + * Tells that Lua will be allowed to access an object's function + * This is the version with an explicit template parameter: "registerFunction(name, [](Foo&) { })" + * @param fn Function object which takes as first parameter a reference to the object + * @tparam TFunctionType Pointer-to-member function type + */ + template + void registerFunction(const std::string& functionName, TType fn) + { + static_assert(std::is_member_function_pointer::value, "registerFunction must take a member function pointer type as template parameter"); + registerFunctionImpl(functionName, std::move(fn), tag{}); + } + + /** + * Tells that Lua will be allowed to access an object's function + * This is the alternative version with an explicit template parameter: "registerFunction(name, [](Foo&) { })" + * @param fn Function object which takes as first parameter a reference to the object + * @tparam TObject Object to register this function to + * @tparam TFunctionType Function type + */ + template + void registerFunction(const std::string& functionName, TType fn) + { + static_assert(std::is_function::value, "registerFunction must take a function type as template parameter"); + registerFunctionImpl(functionName, std::move(fn), tag{}, tag{}); + } + + /** + * Wrappers for registering "__eq" function in case we want to change this to something else some day + */ + + template + auto registerEqFunction(TPointerToMemberFunction pointer) + -> typename std::enable_if::value>::type + { + registerFunctionImpl(EQ_FUNCTION_NAME, std::mem_fn(pointer), tag{}); + } + + template + void registerEqFunction(TType fn) + { + static_assert(std::is_member_function_pointer::value, "registerFunction must take a member function pointer type as template parameter"); + registerFunctionImpl(EQ_FUNCTION_NAME, std::move(fn), tag{}); + } + + template + void registerEqFunction(TType fn) + { + static_assert(std::is_function::value, "registerFunction must take a function type as template parameter"); + registerFunctionImpl(EQ_FUNCTION_NAME, std::move(fn), tag{}, tag{}); + } + + /** + * Wrappers for registering "__tostring" function in case we want to change this to something else some day + */ + + template + auto registerToStringFunction(TPointerToMemberFunction pointer) + -> typename std::enable_if::value>::type + { + registerFunctionImpl(TOSTRING_FUNCTION_NAME, std::mem_fn(pointer), tag{}); + } + + template + void registerToStringFunction(TType fn) + { + static_assert(std::is_member_function_pointer::value, "registerFunction must take a member function pointer type as template parameter"); + registerFunctionImpl(TOSTRING_FUNCTION_NAME, std::move(fn), tag{}); + } + + template + void registerToStringFunction(TType fn) + { + static_assert(std::is_function::value, "registerFunction must take a function type as template parameter"); + registerFunctionImpl(TOSTRING_FUNCTION_NAME, std::move(fn), tag{}, tag{}); + } + + /** + * Inverse operation of registerFunction + * @tparam TType Type whose function belongs to + */ + template + void unregisterFunction(const std::string& /*functionName*/) + { + lua_pushlightuserdata(mState, const_cast(&typeid(TType))); + lua_pushnil(mState); + lua_settable(mState, LUA_REGISTRYINDEX); + checkTypeRegistration(mState, &typeid(TType)); + + lua_pushlightuserdata(mState, const_cast(&typeid(TType*))); + lua_pushnil(mState); + lua_settable(mState, LUA_REGISTRYINDEX); + checkTypeRegistration(mState, &typeid(TType*)); + + lua_pushlightuserdata(mState, const_cast(&typeid(std::shared_ptr))); + lua_pushnil(mState); + lua_settable(mState, LUA_REGISTRYINDEX); + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + } + + /** + * Registers a member variable + * This is the version "registerMember(name, &Foo::member)" + */ + template + void registerMember(const std::string& name, TVarType TObject::*member) + { + // implementation simply calls the custom member with getter and setter + const auto getter = [=](const TObject& obj) -> TVarType { return obj.*member; }; + const auto setter = [=](TObject& obj, const TVarType& value) { obj.*member = value; }; + registerMember(name, getter, setter); + } + + /** + * Registers a member variable + * This is the version "registerMember(name, getter, setter)" + * @tparam TObject Type to register the member to + * @tparam TVarType Type of the member + * @param name Name of the member to register + * @param readFunction Function of type "TVarType (const TObject&)" + * @param writeFunction_ Function of type "void (TObject&, const TVarType&)" + */ + template + void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(name, std::move(readFunction), std::move(writeFunction_)); + } + + /** + * Registers a member variable + * This is the version "registerMember(name, getter, setter)" + * @tparam TMemberType Pointer to member object representing the type + * @param name Name of the member to register + * @param readFunction Function of type "TVarType (const TObject&)" + * @param writeFunction_ Function of type "void (TObject&, const TVarType&)" + */ + template + void registerMember(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) + { + static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); + registerMemberImpl(tag{}, name, std::move(readFunction), std::move(writeFunction_)); + } + + /** + * Registers a non-modifiable member variable + * This is the version "registerMember(name, getter)" + * @tparam TObject Type to register the member to + * @tparam TVarType Type of the member + * @param name Name of the member to register + * @param readFunction Function of type "TVarType (const TObject&)" + */ + template + void registerMember(const std::string& name, TReadFunction readFunction) + { + registerMemberImpl(name, std::move(readFunction)); + } + + /** + * Registers a non-modifiable member variable + * This is the version "registerMember(name, getter)" + * @tparam TMemberType Pointer to member object representing the type + * @param name Name of the member to register + * @param readFunction Function of type "TVarType (const TObject&)" + */ + template + void registerMember(const std::string& name, TReadFunction readFunction) + { + static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); + registerMemberImpl(tag{}, name, std::move(readFunction)); + } + + /** + * Registers a dynamic member variable + * This is the version "registerMember(getter, setter)" + * @tparam TObject Type to register the member to + * @tparam TVarType Type of the member + * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" + * @param writeFunction_ Function of type "void (TObject&, const std::string&, const TVarType&)" + */ + template + void registerMember(TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(std::move(readFunction), std::move(writeFunction_)); + } + + /** + * Registers a dynamic member variable + * This is the version "registerMember(getter, setter)" + * @tparam TMemberType Pointer to member object representing the type + * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" + * @param writeFunction_ Function of type "void (TObject&, const std::string&, const TVarType&)" + */ + template + void registerMember(TReadFunction readFunction, TWriteFunction writeFunction_) + { + static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); + registerMemberImpl(tag{}, std::move(readFunction), std::move(writeFunction_)); + } + + /** + * Registers a dynamic non-modifiable member variable + * This is the version "registerMember(getter)" + * @tparam TObject Type to register the member to + * @tparam TVarType Type of the member + * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" + */ + template + void registerMember(TReadFunction readFunction) + { + registerMemberImpl(std::move(readFunction)); + } + + /** + * Registers a dynamic non-modifiable member variable + * This is the version "registerMember(getter)" + * @tparam TMemberType Pointer to member object representing the type + * @param readFunction Function of type "TVarType (const TObject&, const std::string&)" + */ + template + void registerMember(TReadFunction readFunction) + { + static_assert(std::is_member_object_pointer::value, "registerMember must take a member object pointer type as template parameter"); + registerMemberImpl(tag{}, std::move(readFunction)); + } + + /** + * Creates a new thread + * A Lua thread is not really a thread, but rather an "execution stack". + * You can destroy the thread by calling destroyThread + * @sa destroyThread + */ + auto createThread() + -> ThreadID + { + ThreadID result; + + result.state = lua_newthread(mState); + result.threadInRegistry = std::unique_ptr(new ValueInRegistry(mState)); + lua_pop(mState, 1); + + return result; + } + + /** + * Destroys a thread created with createThread + * @sa createThread + */ + void destroyThread(ThreadID& id) + { + id.threadInRegistry.reset(); + } + + /** + * Reads the content of a Lua variable + * + * @tparam TType Type requested for the read + * @throw WrongTypeException When the variable is not convertible to the requested type + * @sa writeVariable + * + * Readable types are all types accepted by writeVariable except nullptr, std::unique_ptr and function pointers + * Additionally supported: + * - LuaFunctionCaller, which is an alternative to std::function + * - references to custom objects, in which case it will return the object in-place + * + * After the variable name, you can add other parameters. + * If the variable is an array, it will instead get the element of that array whose offset is the second parameter. + * Same applies for third, fourth, etc. parameters. + */ + template + TType readVariable(const std::string& name, TTypes&&... elements) const + { + lua_getglobal(mState, name.c_str()); + lookIntoStackTop(mState, std::forward(elements)...); + return readTopAndPop(mState, PushedObject{mState, 1}); + } + + /** + * @sa readVariable + */ + template + TType readVariable(const char* name, TTypes&&... elements) const + { + lua_getglobal(mState, name); + lookIntoStackTop(mState, std::forward(elements)...); + return readTopAndPop(mState, PushedObject{mState, 1}); + } + + /** + * @sa readVariable + */ + template + TType readVariable(const ThreadID& thread, const std::string& name, TTypes&&... elements) const + { + lua_getglobal(thread.state, name.c_str()); + lookIntoStackTop(thread.state, std::forward(elements)...); + return readTopAndPop(thread.state, PushedObject{thread.state, 1}); + } + + /** + * @sa readVariable + */ + template + TType readVariable(const ThreadID& thread, const char* name, TTypes&&... elements) const + { + lua_getglobal(thread.state, name); + lookIntoStackTop(thread.state, std::forward(elements)...); + return readTopAndPop(thread.state, PushedObject{thread.state, 1}); + } + + /** + * Changes the content of a Lua variable + * + * Accepted values are: + * - all base types (char, short, int, float, double, bool) + * - std::string + * - enums + * - std::vector<> + * - std::vector>, std::map<> and std::unordered_map<> (the key and value must also be accepted values) + * - std::function<> (all parameters must be accepted values, and return type must be either an accepted value for readVariable or a tuple) + * - std::shared_ptr<> (std::unique_ptr<> are converted to std::shared_ptr<>) + * - nullptr (writes nil) + * - any object + * + * All objects are passed by copy and destroyed by the garbage collector if necessary. + */ + template + void writeVariable(TData&&... data) noexcept { + static_assert(sizeof...(TData) >= 2, "You must pass at least a variable name and a value to writeVariable"); + typedef typename std::decay>::type>::type + RealDataType; + static_assert(!std::is_same::type,RealDataType>::value, "Error: you can't use LuaContext::writeVariable with a tuple"); + + setTable(mState, Globals, std::forward(data)...); + } + + /** + * Equivalent to writeVariable(varName, ..., std::function(data)); + * This version is more efficient than writeVariable if you want to write functions + */ + template + void writeFunction(TData&&... data) noexcept { + static_assert(sizeof...(TData) >= 2, "You must pass at least a variable name and a value to writeFunction"); + + setTable(mState, Globals, std::forward(data)...); + } + + /** + * Same as the other writeFunction, except that the template parameter is automatically detected + * This only works if the data is either a native function pointer, or contains one operator() (this is the case for lambdas) + */ + template + void writeFunction(TData&&... data) noexcept { + static_assert(sizeof...(TData) >= 2, "You must pass at least a variable name and a value to writeFunction"); + typedef typename std::decay>::type>::type + RealDataType; + typedef typename FunctionTypeDetector::type + DetectedFunctionType; + + return writeFunction(std::forward(data)...); + } + + +private: + // the state is the most important variable in the class since it is our interface with Lua + // - registered members and functions are stored in tables at offset &typeid(type) of the registry + // each table has its getter functions at offset 0, getter members at offset 1, default getter at offset 2 + // offset 3 is unused, setter members at offset 4, default setter at offset 5 + lua_State* mState; + + + /**************************************************/ + /* PUSH OBJECT */ + /**************************************************/ + struct PushedObject { + PushedObject(lua_State* state_, int num_ = 1) : state(state_), num(num_) {} + ~PushedObject() { assert(lua_gettop(state) >= num); if (num >= 1) lua_pop(state, num); } + + PushedObject& operator=(const PushedObject&) = delete; + PushedObject(const PushedObject&) = delete; + PushedObject& operator=(PushedObject&& other) { std::swap(state, other.state); std::swap(num, other.num); return *this; } + PushedObject(PushedObject&& other) : state(other.state), num(other.num) { other.num = 0; } + + PushedObject operator+(PushedObject&& other) && { PushedObject obj(state, num + other.num); num = 0; other.num = 0; return obj; } + void operator+=(PushedObject&& other) { assert(state == other.state); num += other.num; other.num = 0; } + + auto getState() const -> lua_State* { return state; } + auto getNum() const -> int { return num; } + + int release() { const auto n = num; num = 0; return n; } + void pop() { if (num >= 1) lua_pop(state, num); num = 0; } + void pop(int n) { assert(num >= n); lua_pop(state, n); num -= n; } + + private: + lua_State* state; + int num = 0; + }; + + + /**************************************************/ + /* MISC */ + /**************************************************/ + // type used as a tag + template + struct tag {}; + + // tag for "the registry" + enum RegistryTag { Registry }; + + // this function takes a value representing the offset to look into + // it will look into the top element of the stack and replace the element by its content at the given index + template + static void lookIntoStackTop(lua_State* state, OffsetType1&& offset1, OffsetTypeOthers&&... offsetOthers) { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + auto p1 = Pusher::type>::push(state, offset1); + lua_gettable(state, -2); + lua_remove(state, -2); + p1.release(); + + lookIntoStackTop(state, std::forward(offsetOthers)...); + } + + template + static void lookIntoStackTop(lua_State* state, Metatable_t, OffsetTypeOthers&&... offsetOthers) { + lua_getmetatable(state, -1); + lua_remove(state, -2); + + lookIntoStackTop(state, std::forward(offsetOthers)...); + } + + static void lookIntoStackTop(lua_State*) { + } + + // equivalent of lua_settable with t[k]=n, where t is the value at the index in the template parameter, k is the second parameter, n is the last parameter, and n is pushed by the function in the first parameter + // if there are more than 3 parameters, parameters 3 to n-1 are considered as sub-indices into the array + // the dataPusher MUST push only one thing on the stack + // TTableIndex must be either LUA_REGISTRYINDEX, LUA_GLOBALSINDEX, LUA_ENVINDEX, or the position of the element on the stack + template + static void setTable(lua_State* state, const PushedObject&, TIndex&& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, index); + auto p2 = Pusher::type>::push(state, std::forward(data)); + + lua_settable(state, -3); + p1.release(); + p2.release(); + } + + template + static void setTable(lua_State* state, const PushedObject&, const std::string& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setfield(state, -2, index.c_str()); + p1.release(); + } + + template + static void setTable(lua_State* state, const PushedObject&, const char* index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setfield(state, -2, index); + p1.release(); + } + + template + static void setTable(lua_State* state, const PushedObject&, Metatable_t, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setmetatable(state, -2); + p1.release(); + } + + template + static auto setTable(lua_State* state, PushedObject&, TIndex1&& index1, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + -> typename std::enable_if::type, Metatable_t>::value>::type + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + + auto p1 = Pusher::type>::push(state, std::forward(index1)); + lua_gettable(state, -2); + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + + template + static auto setTable(lua_State* state, PushedObject&& pushedTable, TIndex1&& index1, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + -> typename std::enable_if::type, Metatable_t>::value>::type + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + + auto p1 = Pusher::type>::push(state, std::forward(index1)) + std::move(pushedTable); + lua_gettable(state, -2); + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + + template + static void setTable(lua_State* state, PushedObject& pushedObject, Metatable_t, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + if (lua_getmetatable(state, -1) == 0) + { + lua_newtable(state); + PushedObject p1{state, 1}; + + setTable(state, p1, std::forward(index2), std::forward(index3), std::forward(indices)...); + + lua_setmetatable(state, -2); + p1.release(); + } + else + { + setTable(state, pushedObject, std::forward(index2), std::forward(index3), std::forward(indices)...); + } + } + + template + static void setTable(lua_State* state, PushedObject&& pushedObject, Metatable_t, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + if (lua_getmetatable(state, -1) == 0) + { + lua_newtable(state); + PushedObject p1{state, 1}; + + setTable(state, p1, std::forward(index2), std::forward(index3), std::forward(indices)...); + + lua_setmetatable(state, -2); + p1.release(); + } + else + { + setTable(state, std::move(pushedObject), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + } + + template + static void setTable(lua_State* state, RegistryTag, TIndex&& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, index); + auto p2 = Pusher::type>::push(state, std::forward(data)); + + lua_settable(state, LUA_REGISTRYINDEX); + p1.release(); + p2.release(); + } + + template + static void setTable(lua_State* state, RegistryTag, const std::string& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setfield(state, LUA_REGISTRYINDEX, index.c_str()); + p1.release(); + } + + template + static void setTable(lua_State* state, RegistryTag, const char* index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setfield(state, LUA_REGISTRYINDEX, index); + p1.release(); + } + + template + static void setTable(lua_State* state, RegistryTag, TIndex1&& index1, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + + auto p1 = Pusher::type>::push(state, std::forward(index1)); + lua_gettable(state, LUA_REGISTRYINDEX); + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + + template + static void setTable(lua_State* state, Globals_t, TIndex&& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + +# if LUA_VERSION_NUM >= 502 + + lua_pushglobaltable(state); + PushedObject p3{state, 1}; + auto p1 = Pusher::type>::push(state, index); + auto p2 = Pusher::type>::push(state, std::forward(data)); + lua_settable(state, -3); + +# else + + auto p1 = Pusher::type>::push(state, index); + auto p2 = Pusher::type>::push(state, std::forward(data)); + lua_settable(state, LUA_GLOBALSINDEX); + +# endif + + p1.release(); + p2.release(); + } + + template + static void setTable(lua_State* state, Globals_t, const std::string& index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setglobal(state, index.c_str()); + p1.release(); + } + + template + static void setTable(lua_State* state, Globals_t, const char* index, TData&& data) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values data"); + + auto p1 = Pusher::type>::push(state, std::forward(data)); + lua_setglobal(state, index); + p1.release(); + } + + template + static void setTable(lua_State* state, Globals_t, TIndex1&& index1, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Impossible to have a multiple-values index"); + +# if LUA_VERSION_NUM >= 502 + + lua_pushglobaltable(state); + auto p1 = Pusher::type>::push(state, std::forward(index1)) + PushedObject{state, 1}; + lua_gettable(state, -2); + +# else + + auto p1 = Pusher::type>::push(state, std::forward(index1)); + lua_gettable(state, LUA_GLOBALSINDEX); + +# endif + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + + // TODO: g++ reports "ambiguous overload" + /*template + static void setTable(lua_State* state, Globals_t, const char* index, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + lua_getglobal(state, index); + PushedObject p1{state, 1}; + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + } + + template + static void setTable(lua_State* state, Globals_t, const std::string& index, TIndex2&& index2, TIndex3&& index3, TIndices&&... indices) noexcept + { + lua_getglobal(state, index.c_str()); + PushedObject p1{state, 1}; + + setTable(state, std::move(p1), std::forward(index2), std::forward(index3), std::forward(indices)...); + }*/ + + // simple function that reads the "nb" first top elements of the stack, pops them, and returns the value + // warning: first parameter is the number of parameters, not the parameter index + // if read generates an exception, stack is poped anyway + template + static auto readTopAndPop(lua_State* state, PushedObject object) + -> TReturnType + { + auto val = Reader::type>::read(state, -object.getNum()); + if (!val.is_initialized()) + throw WrongTypeException{lua_typename(state, lua_type(state, -object.getNum())), typeid(TReturnType)}; + return val.get(); + } + + // checks that the offsets for a type's registrations are set in the registry + static void checkTypeRegistration(lua_State* state, const std::type_info* type) + { + lua_pushlightuserdata(state, const_cast(type)); + lua_gettable(state, LUA_REGISTRYINDEX); + if (!lua_isnil(state, -1)) { + lua_pop(state, 1); + return; + } + lua_pop(state, 1); + + lua_pushlightuserdata(state, const_cast(type)); + lua_newtable(state); + + lua_pushinteger(state, 0); + lua_newtable(state); + lua_settable(state, -3); + + lua_pushinteger(state, 1); + lua_newtable(state); + lua_settable(state, -3); + + lua_pushinteger(state, 3); + lua_newtable(state); + lua_settable(state, -3); + + lua_pushinteger(state, 4); + lua_newtable(state); + lua_settable(state, -3); + + lua_settable(state, LUA_REGISTRYINDEX); + } + + // +# ifdef _MSC_VER + __declspec(noreturn) +# else + [[noreturn]] +# endif + static void luaError(lua_State* state) + { + lua_error(state); + assert(false); + std::terminate(); // removes compilation warning + } + + + /**************************************************/ + /* FUNCTIONS REGISTRATION */ + /**************************************************/ + // the "registerFunction" public functions call this one + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag, tag) + { + static_assert(std::is_class::value || std::is_pointer::value || std::is_union::value , "registerFunction can only be used for a class a union or a pointer"); + + checkTypeRegistration(mState, &typeid(TObject)); + setTable(mState, Registry, &typeid(TObject), 0, functionName, function); + + checkTypeRegistration(mState, &typeid(TObject*)); + setTable(mState, Registry, &typeid(TObject*), 0, functionName, [=](TObject* obj, TOtherParams... rest) { assert(obj); return function(*obj, std::forward(rest)...); }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable, TOtherParams...)>(mState, Registry, &typeid(std::shared_ptr), 0, functionName, [=](const std::shared_ptr& obj, TOtherParams... rest) { assert(obj); return function(*obj, std::forward(rest)...); }); + } + + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag, tag fTypeTag) + { + registerFunctionImpl(functionName, function, tag{}, fTypeTag); + + checkTypeRegistration(mState, &typeid(TObject const*)); + setTable(mState, Registry, &typeid(TObject const*), 0, functionName, [=](TObject const* obj, TOtherParams... rest) { assert(obj); return function(*obj, std::forward(rest)...); }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable, TOtherParams...)>(mState, Registry, &typeid(std::shared_ptr), 0, functionName, [=](const std::shared_ptr& obj, TOtherParams... rest) { assert(obj); return function(*obj, std::forward(rest)...); }); + } + + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag) + { + registerFunctionImpl(functionName, std::move(function), tag{}, tag{}); + } + + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag) + { + registerFunctionImpl(functionName, std::move(function), tag{}, tag{}); + } + + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag) + { + registerFunctionImpl(functionName, std::move(function), tag{}, tag{}); + } + + template + void registerFunctionImpl(const std::string& functionName, TFunctionType function, tag) + { + registerFunctionImpl(functionName, std::move(function), tag{}, tag{}); + } + + // the "registerMember" public functions call this one + template + void registerMemberImpl(const std::string& name, TReadFunction readFunction) + { + static_assert(std::is_class::value || std::is_pointer::value, "registerMember can only be called on a class or a pointer"); + + checkTypeRegistration(mState, &typeid(TObject)); + setTable(mState, Registry, &typeid(TObject), 1, name, [readFunction](TObject const& object) { + return readFunction(object); + }); + + checkTypeRegistration(mState, &typeid(TObject*)); + setTable(mState, Registry, &typeid(TObject*), 1, name, [readFunction](TObject const* object) { + assert(object); + return readFunction(*object); + }); + + checkTypeRegistration(mState, &typeid(TObject const*)); + setTable(mState, Registry, &typeid(TObject const*), 1, name, [readFunction](TObject const* object) { + assert(object); + return readFunction(*object); + }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable)>(mState, Registry, &typeid(std::shared_ptr), 1, name, [readFunction](const std::shared_ptr& object) { + assert(object); + return readFunction(*object); + }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable)>(mState, Registry, &typeid(std::shared_ptr), 1, name, [readFunction](const std::shared_ptr& object) { + assert(object); + return readFunction(*object); + }); + } + + template + void registerMemberImpl(const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(name, readFunction); + + setTable(mState, Registry, &typeid(TObject), 4, name, [writeFunction_](TObject& object, const TVarType& value) { + writeFunction_(object, value); + }); + + setTable(mState, Registry, &typeid(TObject*), 4, name, [writeFunction_](TObject* object, const TVarType& value) { + assert(object); + writeFunction_(*object, value); + }); + + setTable, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 4, name, [writeFunction_](std::shared_ptr object, const TVarType& value) { + assert(object); + writeFunction_(*object, value); + }); + } + + template + void registerMemberImpl(tag, const std::string& name, TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(name, std::move(readFunction), std::move(writeFunction_)); + } + + template + void registerMemberImpl(tag, const std::string& name, TReadFunction readFunction) + { + registerMemberImpl(name, std::move(readFunction)); + } + + // the "registerMember" public functions call this one + template + void registerMemberImpl(TReadFunction readFunction) + { + checkTypeRegistration(mState, &typeid(TObject)); + setTable(mState, Registry, &typeid(TObject), 2, [readFunction](TObject const& object, const std::string& name) { + return readFunction(object, name); + }); + + checkTypeRegistration(mState, &typeid(TObject*)); + setTable(mState, Registry, &typeid(TObject*), 2, [readFunction](TObject const* object, const std::string& name) { + assert(object); + return readFunction(*object, name); + }); + + checkTypeRegistration(mState, &typeid(TObject const*)); + setTable(mState, Registry, &typeid(TObject const*), 2, [readFunction](TObject const* object, const std::string& name) { + assert(object); + return readFunction(*object, name); + }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable, std::string)>(mState, Registry, &typeid(std::shared_ptr), 2, [readFunction](const std::shared_ptr& object, const std::string& name) { + assert(object); + return readFunction(*object, name); + }); + + checkTypeRegistration(mState, &typeid(std::shared_ptr)); + setTable, std::string)>(mState, Registry, &typeid(std::shared_ptr), 2, [readFunction](const std::shared_ptr& object, const std::string& name) { + assert(object); + return readFunction(*object, name); + }); + } + + template + void registerMemberImpl(TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(readFunction); + + setTable(mState, Registry, &typeid(TObject), 5, [writeFunction_](TObject& object, const std::string& name, const TVarType& value) { + writeFunction_(object, name, value); + }); + + setTable(mState, Registry, &typeid(TObject*), 2, [writeFunction_](TObject* object, const std::string& name, const TVarType& value) { + assert(object); + writeFunction_(*object, name, value); + }); + + setTable, std::string, TVarType)>(mState, Registry, &typeid(std::shared_ptr), 2, [writeFunction_](const std::shared_ptr& object, const std::string& name, const TVarType& value) { + assert(object); + writeFunction_(*object, name, value); + }); + } + + template + void registerMemberImpl(tag, TReadFunction readFunction, TWriteFunction writeFunction_) + { + registerMemberImpl(std::move(readFunction), std::move(writeFunction_)); + } + + template + void registerMemberImpl(tag, TReadFunction readFunction) + { + registerMemberImpl(std::move(readFunction)); + } + + + /**************************************************/ + /* LOADING AND CALLING */ + /**************************************************/ + // this function loads data from the stream and pushes a function at the top of the stack + // throws in case of syntax error + static PushedObject load(lua_State* state, std::istream& code) { + // since the lua_load function requires a static function, we use this structure + // the Reader structure is at the same time an object storing an istream and a buffer, + // and a static function provider + struct Reader { + Reader(std::istream& str) : stream(str) {} + std::istream& stream; + std::array buffer; + + // read function ; "data" must be an instance of Reader + static const char* read(lua_State* /*l*/, void* data, size_t* size) { + assert(size != nullptr); + assert(data != nullptr); + Reader& me = *static_cast(data); + if (me.stream.eof()) { *size = 0; return nullptr; } + + me.stream.read(me.buffer.data(), me.buffer.size()); + *size = static_cast(me.stream.gcount()); // gcount could return a value larger than a size_t, but its maximum is me.buffer.size() so there's no problem + return me.buffer.data(); + } + }; + + // we create an instance of Reader, and we call lua_load + Reader reader{code}; + const auto loadReturnValue = lua_load(state, &Reader::read, &reader, "chunk" +# if LUA_VERSION_NUM >= 502 + , nullptr +# endif + ); + + // now we have to check return value + if (loadReturnValue != 0) { + // there was an error during loading, an error message was pushed on the stack + const std::string errorMsg = lua_tostring(state, -1); + lua_pop(state, 1); + if (loadReturnValue == LUA_ERRMEM) + throw std::bad_alloc(); + else if (loadReturnValue == LUA_ERRSYNTAX) + throw SyntaxErrorException{errorMsg}; + throw std::runtime_error("Error while calling lua_load: " + errorMsg); + } + + return PushedObject{state, 1}; + } + + // this function loads data and pushes a function at the top of the stack + // throws in case of syntax error + static PushedObject load(lua_State* state, const char* code) { + auto loadReturnValue = luaL_loadstring(state, code); + + // now we have to check return value + if (loadReturnValue != 0) { + // there was an error during loading, an error message was pushed on the stack + const std::string errorMsg = lua_tostring(state, -1); + lua_pop(state, 1); + if (loadReturnValue == LUA_ERRMEM) + throw std::bad_alloc(); + else if (loadReturnValue == LUA_ERRSYNTAX) + throw SyntaxErrorException{errorMsg}; + throw std::runtime_error("Error while calling lua_load: " + errorMsg); + } + + return PushedObject{state, 1}; + } + + // this function calls what is on the top of the stack and removes it (just like lua_call) + // if an exception is triggered, the top of the stack will be removed anyway + template + static auto call(lua_State* state, PushedObject toCall, TParameters&&... input) + -> TReturnType + { + typedef typename Tupleizer::type + RealReturnType; + + // we push the parameters on the stack + auto inArguments = Pusher>::push(state, std::forward_as_tuple(std::forward(input)...)); + + // + const int outArgumentsCount = std::tuple_size::value; + auto outArguments = callRaw(state, std::move(toCall) + std::move(inArguments), outArgumentsCount); + + // pcall succeeded, we pop the returned values and return them + return readTopAndPop(state, std::move(outArguments)); + } + + // this function just calls lua_pcall and checks for errors + static PushedObject callRaw(lua_State* state, PushedObject functionAndArguments, const int outArguments) + { + // calling pcall automatically pops the parameters and pushes output + const auto pcallReturnValue = lua_pcall(state, functionAndArguments.getNum() - 1, outArguments, 0); + functionAndArguments.release(); + + // if pcall failed, analyzing the problem and throwing + if (pcallReturnValue != 0) { + PushedObject errorCode{state, 1}; + + // an error occured during execution, either an error message or a std::exception_ptr was pushed on the stack + if (pcallReturnValue == LUA_ERRMEM) { + throw std::bad_alloc{}; + + } else if (pcallReturnValue == LUA_ERRRUN) { + if (lua_isstring(state, 1)) { + // the error is a string + const auto str = readTopAndPop(state, std::move(errorCode)); + throw ExecutionErrorException{str}; + + } else { + // an exception_ptr was pushed on the stack + // rethrowing it with an additional ExecutionErrorException + try { + if (const auto exp = readTopAndPop(state, std::move(errorCode))) { + std::rethrow_exception(exp); + } + } catch(const std::exception& e) { + std::throw_with_nested(ExecutionErrorException{std::string{"Exception thrown by a callback function: "} + e.what()}); + } catch(...) { + std::throw_with_nested(ExecutionErrorException{"Exception thrown by a callback function called by Lua"}); + } + throw ExecutionErrorException{"Unknown Lua error"}; + } + } + } + + return PushedObject{state, outArguments}; + } + + + /**************************************************/ + /* PUSH FUNCTIONS */ + /**************************************************/ + template + static PushedObject push(lua_State* state, T&& value) + { + return Pusher::type>::push(state, std::forward(value)); + } + + // the Pusher structures allow you to push a value on the stack + // - static const int minSize : minimum size on the stack that the value can have + // - static const int maxSize : maximum size on the stack that the value can have + // - static int push(const LuaContext&, ValueType) : pushes the value on the stack and returns the size on the stack + + // implementation for custom objects + template + struct Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + template + static PushedObject push(lua_State* state, TType2&& value) noexcept { + // this function is called when lua's garbage collector wants to destroy our object + // we simply call its destructor + const auto garbageCallbackFunction = [](lua_State* lua) -> int { + assert(lua_gettop(lua) == 1); + TType* ptr = static_cast(lua_touserdata(lua, 1)); + assert(ptr); + ptr->~TType(); + return 0; + }; + + // this function will be stored in __index in the metatable + const auto indexFunction = [](lua_State* lua) -> int { + try { + assert(lua_gettop(lua) == 2); + assert(lua_isuserdata(lua, 1)); + + // searching for a handler + lua_pushlightuserdata(lua, const_cast(&typeid(TType))); + lua_gettable(lua, LUA_REGISTRYINDEX); + assert(!lua_isnil(lua, -1)); + + // looking into getter functions + lua_pushinteger(lua, 0); + lua_gettable(lua, -2); + lua_pushvalue(lua, 2); + lua_gettable(lua, -2); + if (!lua_isnil(lua, -1)) + return 1; + lua_pop(lua, 2); + + // looking into getter members + lua_pushinteger(lua, 1); + lua_gettable(lua, -2); + lua_pushvalue(lua, 2); + lua_gettable(lua, -2); + if (!lua_isnil(lua, -1)) { + lua_pushvalue(lua, 1); + return callRaw(lua, PushedObject{lua, 2}, 1).release(); + } + lua_pop(lua, 2); + + // looking into default getter + lua_pushinteger(lua, 2); + lua_gettable(lua, -2); + if (lua_isnil(lua, -1)) + return 1; + lua_pushvalue(lua, 1); + lua_pushvalue(lua, 2); + return callRaw(lua, PushedObject{lua, 3}, 1).release(); + + } catch (...) { + Pusher::push(lua, std::current_exception()).release(); + luaError(lua); + } + }; + + // this function will be stored in __newindex in the metatable + const auto newIndexFunction = [](lua_State* lua) -> int { + try { + assert(lua_gettop(lua) == 3); + assert(lua_isuserdata(lua, 1)); + + // searching for a handler + lua_pushlightuserdata(lua, const_cast(&typeid(TType))); + lua_rawget(lua, LUA_REGISTRYINDEX); + assert(!lua_isnil(lua, -1)); + + // looking into setter members + lua_pushinteger(lua, 4); + lua_rawget(lua, -2); + lua_pushvalue(lua, 2); + lua_rawget(lua, -2); + if (!lua_isnil(lua, -1)) { + lua_pushvalue(lua, 1); + lua_pushvalue(lua, 3); + callRaw(lua, PushedObject{lua, 3}, 0); + lua_pop(lua, 2); + return 0; + } + lua_pop(lua, 2); + + // looking into default setter + lua_pushinteger(lua, 5); + lua_rawget(lua, -2); + if (lua_isnil(lua, -1)) + { + lua_pop(lua, 2); + lua_pushstring(lua, "No setter found"); + luaError(lua); + } + lua_pushvalue(lua, 1); + lua_pushvalue(lua, 2); + lua_pushvalue(lua, 3); + callRaw(lua, PushedObject{lua, 4}, 0); + lua_pop(lua, 1); + return 0; + + } catch (...) { + Pusher::push(lua, std::current_exception()).release(); + luaError(lua); + } + }; + + const auto toStringFunction = [](lua_State* lua) -> int { + try { + assert(lua_gettop(lua) == 1); + assert(lua_isuserdata(lua, 1)); + lua_pushstring(lua, "__tostring"); + lua_gettable(lua, 1); + if (lua_isnil(lua, -1)) + { + const void *ptr = lua_topointer(lua, -2); + lua_pop(lua, 1); + lua_pushstring(lua, (boost::format("userdata 0x%08x") % reinterpret_cast(ptr)).str().c_str()); + return 1; + } + lua_pushvalue(lua, 1); + return callRaw(lua, PushedObject{lua, 2}, 1).release(); + } catch (...) { + Pusher::push(lua, std::current_exception()).release(); + luaError(lua); + } + }; + + + // writing structure for this type into the registry + checkTypeRegistration(state, &typeid(TType)); + + // creating the object + // lua_newuserdata allocates memory in the internals of the lua library and returns it so we can fill it + // and that's what we do with placement-new + const auto pointerLocation = static_cast(lua_newuserdata(state, sizeof(TType))); + new (pointerLocation) TType(std::forward(value)); + PushedObject obj{state, 1}; + + // creating the metatable (over the object on the stack) + // lua_settable pops the key and value we just pushed, so stack management is easy + // all that remains on the stack after these function calls is the metatable + lua_newtable(state); + PushedObject pushedTable{state, 1}; + + // using the garbage collecting function we created above + if (!boost::has_trivial_destructor::value) + { + lua_pushstring(state, "__gc"); + lua_pushcfunction(state, garbageCallbackFunction); + lua_settable(state, -3); + } + + // the _typeid index of the metatable will store the type_info* + lua_pushstring(state, "_typeid"); + lua_pushlightuserdata(state, const_cast(&typeid(TType))); + lua_settable(state, -3); + + // using the index function we created above + lua_pushstring(state, "__index"); + lua_pushcfunction(state, indexFunction); + lua_settable(state, -3); + + // using the newindex function we created above + lua_pushstring(state, "__newindex"); + lua_pushcfunction(state, newIndexFunction); + lua_settable(state, -3); + + lua_pushstring(state, "__tostring"); + lua_pushcfunction(state, toStringFunction); + lua_settable(state, -3); + + lua_pushstring(state, "__eq"); + lua_getglobal(state, LUACONTEXT_GLOBAL_EQ); + lua_settable(state, -3); + + + // at this point, the stack contains the object at offset -2 and the metatable at offset -1 + // lua_setmetatable will bind the two together and pop the metatable + // our custom type remains on the stack (and that's what we want since this is a push function) + lua_setmetatable(state, -2); + pushedTable.release(); + + return obj; + } + }; + + // this structure has a "size" int static member which is equal to the total of the push min size of all the types + template + struct PusherTotalMinSize; + + // this structure has a "size" int static member which is equal to the total of the push max size of all the types + template + struct PusherTotalMaxSize; + + // this structure has a "size" int static member which is equal to the maximum size of the push of all the types + template + struct PusherMinSize; + + // this structure has a "size" int static member which is equal to the maximum size of the push of all the types + template + struct PusherMaxSize; + + + /**************************************************/ + /* READ FUNCTIONS */ + /**************************************************/ + // the "Reader" structures allow to read data from the stack + // - the "ReturnType" type is what is returned by the reader, and can be different than the template parameter (especially with references and constness) + // - the "read" static function will check and read at the same time, returning an empty optional if it is the wrong type + + template + struct Reader { + typedef typename std::conditional::value, TType, TType&>::type + ReturnType; + + static auto read(lua_State* state, int index) + -> boost::optional + { + if (!test(state, index)) + return boost::none; + return boost::optional(*static_cast(lua_touserdata(state, index))); + } + + private: + static bool test(lua_State* state, int index) + { + if (!lua_isuserdata(state, index)) + return false; + if (!lua_getmetatable(state, index)) + return false; + + // now we have our metatable on the top of the stack + // retrieving its _typeid member + lua_pushstring(state, "_typeid"); + lua_gettable(state, -2); + const auto storedTypeID = static_cast(lua_touserdata(state, -1)); + const auto typeIDToCompare = &typeid(TType); + + // if wrong typeid, returning false + lua_pop(state, 2); + if (storedTypeID != typeIDToCompare) + return false; + + return true; + } + }; + + /** + * This functions reads multiple values starting at "index" and passes them to the callback + */ + template + static auto readIntoFunction(lua_State* /*state*/, tag, TCallback&& callback, int /*index*/) + -> TRetValue + { + return callback(); + } + template + static auto readIntoFunction(lua_State* state, tag retValueTag, TCallback&& callback, int index, tag, tag... othersTags) + -> typename std::enable_if::value, TRetValue>::type + { + if (index >= 0) { + Binder binder{ callback, {} }; + return readIntoFunction(state, retValueTag, binder, index + 1, othersTags...); + } + + const auto& firstElem = Reader::type>::read(state, index); + if (!firstElem) + throw WrongTypeException(lua_typename(state, lua_type(state, index)), typeid(TFirstType)); + + Binder binder{ callback, *firstElem }; + return readIntoFunction(state, retValueTag, binder, index + 1, othersTags...); + } + template + static auto readIntoFunction(lua_State* state, tag retValueTag, TCallback&& callback, int index, tag, tag... othersTags) + -> typename std::enable_if::value, TRetValue>::type + { + if (index >= 0) + throw std::logic_error("Wrong number of parameters"); + + const auto& firstElem = Reader::type>::read(state, index); + if (!firstElem) + throw WrongTypeException(lua_typename(state, lua_type(state, index)), typeid(TFirstType)); + + Binder binder{ callback, *firstElem }; + return readIntoFunction(state, retValueTag, binder, index + 1, othersTags...); + } + + + /**************************************************/ + /* UTILITIES */ + /**************************************************/ + // structure that will ensure that a certain value is stored somewhere in the registry + struct ValueInRegistry { + // this constructor will clone and hold the value at the specified index (or by default at the top of the stack) in the registry + ValueInRegistry(lua_State* lua_, int index=-1) : lua{lua_} + { + lua_pushlightuserdata(lua, this); + lua_pushvalue(lua, -1 + index); + lua_settable(lua, LUA_REGISTRYINDEX); + } + + // removing the function from the registry + ~ValueInRegistry() + { + lua_pushlightuserdata(lua, this); + lua_pushnil(lua); + lua_settable(lua, LUA_REGISTRYINDEX); + } + + // loads the value and puts it at the top of the stack + PushedObject pop() + { + lua_pushlightuserdata(lua, this); + lua_gettable(lua, LUA_REGISTRYINDEX); + return PushedObject{lua, 1}; + } + + ValueInRegistry(const ValueInRegistry&) = delete; + ValueInRegistry& operator=(const ValueInRegistry&) = delete; + + private: + lua_State* lua; + }; + + // binds the first parameter of a function object + template + struct Binder { + TFunctionObject function; + TFirstParamType param; + + template + auto operator()(TParams&&... params) + -> decltype(function(param, std::forward(params)...)) + { + return function(param, std::forward(params)...); + } + }; + + // turns a type into a tuple + // void is turned into std::tuple<> + // existing tuples are untouched + template + struct Tupleizer; + + // this structure takes a pointer to a member function type and returns the base function type + template + struct RemoveMemberPointerFunction { typedef void type; }; // required because of a compiler bug + + // this structure takes any object and detects its function type + template + struct FunctionTypeDetector { typedef typename RemoveMemberPointerFunction::type::operator())>::type type; }; + + // this structure takes a function arguments list and has the "min" and the "max" static const member variables, whose value equal to the min and max number of parameters for the function + // the only case where "min != max" is with boost::optional at the end of the list + template + struct FunctionArgumentsCounter {}; + + // true is the template parameter is a boost::optional + template + struct IsOptional : public std::false_type {}; +}; + +/// @deprecated +static LuaContext::EmptyArray_t ATTR_UNUSED + LuaEmptyArray {}; +/// @deprecated +static LuaContext::Metatable_t ATTR_UNUSED + LuaMetatable {}; + +/**************************************************/ +/* PARTIAL IMPLEMENTATIONS */ +/**************************************************/ +template<> +inline auto LuaContext::readTopAndPop(lua_State* /*state*/, PushedObject /*obj*/) + -> void +{ +} + +// this structure takes a template parameter T +// if T is a tuple, it returns T ; if T is not a tuple, it returns std::tuple +// we have to use this structure because std::tuple> triggers a bug in both MSVC++ and GCC +template +struct LuaContext::Tupleizer { typedef std::tuple type; }; +template +struct LuaContext::Tupleizer> { typedef std::tuple type; }; +template<> +struct LuaContext::Tupleizer { typedef std::tuple<> type; }; + +// this structure takes any object and detects its function type +template +struct LuaContext::FunctionTypeDetector { typedef TRetValue type(TParameters...); }; +template +struct LuaContext::FunctionTypeDetector { typedef typename FunctionTypeDetector::type type; }; + +// this structure takes a pointer to a member function type and returns the base function type +template +struct LuaContext::RemoveMemberPointerFunction { typedef TRetValue type(TParameters...); }; +template +struct LuaContext::RemoveMemberPointerFunction { typedef TRetValue type(TParameters...); }; +template +struct LuaContext::RemoveMemberPointerFunction { typedef TRetValue type(TParameters...); }; +template +struct LuaContext::RemoveMemberPointerFunction { typedef TRetValue type(TParameters...); }; + +// implementation of PusherTotalMinSize +template +struct LuaContext::PusherTotalMinSize { static const int size = Pusher::type>::minSize + PusherTotalMinSize::size; }; +template<> +struct LuaContext::PusherTotalMinSize<> { static const int size = 0; }; + +// implementation of PusherTotalMaxSize +template +struct LuaContext::PusherTotalMaxSize { static const int size = Pusher::type>::maxSize + PusherTotalMaxSize::size; }; +template<> +struct LuaContext::PusherTotalMaxSize<> { static const int size = 0; }; + +// implementation of PusherMinSize +template +struct LuaContext::PusherMinSize +{ + static const int size = Pusher::type>::minSize < Pusher::type>::minSize + ? + PusherMinSize::type, TTypes...>::size + : + PusherMinSize::type, TTypes...>::size; +}; + +template +struct LuaContext::PusherMinSize { static const int size = Pusher::type>::minSize; }; + +// implementation of PusherMaxSize +template +struct LuaContext::PusherMaxSize { static const int size = Pusher::type>::maxSize > PusherTotalMaxSize::size ? Pusher::type>::maxSize : PusherMaxSize::size; }; +template<> +struct LuaContext::PusherMaxSize<> { static const int size = 0; }; + +// implementation of FunctionArgumentsCounter +template +struct LuaContext::FunctionArgumentsCounter { + typedef FunctionArgumentsCounter + SubType; + static const int min = (IsOptional::value && SubType::min == 0) ? 0 : 1 + SubType::min; + static const int max = 1 + SubType::max; +}; +template<> +struct LuaContext::FunctionArgumentsCounter<> { + static const int min = 0; + static const int max = 0; +}; + +// implementation of IsOptional +template +struct LuaContext::IsOptional> : public std::true_type {}; + +// implementation of LuaFunctionCaller +template +class LuaContext::LuaFunctionCaller { static_assert(std::is_function::value, "Template parameter of LuaFunctionCaller must be a function type"); }; +template +class LuaContext::LuaFunctionCaller +{ +public: + TRetValue operator()(TParams&&... params) const + { + auto obj = valueHolder->pop(); + return call(state, std::move(obj), std::forward(params)...); + } + +private: + std::shared_ptr valueHolder; + lua_State* state; + +private: + friend LuaContext; + explicit LuaFunctionCaller(lua_State* state_, int index) : + valueHolder(std::make_shared(state_, index)), + state(state_) + {} +}; + + +/**************************************************/ +/* PUSH FUNCTIONS */ +/**************************************************/ +// specializations of the Pusher structure + +// opaque Lua references +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const LuaContext::LuaObject& value) noexcept { + if (value.objectInRegistry.get()) { + PushedObject obj = value.objectInRegistry->pop(); + return obj; + } else { + lua_pushnil(state); + return PushedObject{state, 1}; + } + } +}; + +// boolean +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, bool value) noexcept { + lua_pushboolean(state, value); + return PushedObject{state, 1}; + } +}; + +// string +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::string& value) noexcept { + lua_pushlstring(state, value.c_str(), value.length()); + return PushedObject{state, 1}; + } +}; + +// const char* +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const char* value) noexcept { + lua_pushstring(state, value); + return PushedObject{state, 1}; + } +}; + +// const char[N] +template +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const char* value) noexcept { + lua_pushstring(state, value); + return PushedObject{state, 1}; + } +}; + +// floating numbers +template +struct LuaContext::Pusher::value>::type> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, T value) noexcept { + lua_pushnumber(state, value); + return PushedObject{state, 1}; + } +}; + +// integers +template +struct LuaContext::Pusher::value>::type> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, T value) noexcept { + lua_pushinteger(state, value); + return PushedObject{state, 1}; + } +}; + +// nil +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, std::nullptr_t) noexcept { + lua_pushnil(state); + return PushedObject{state, 1}; + } +}; + +// empty arrays +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, EmptyArray_t) noexcept { + lua_newtable(state); + return PushedObject{state, 1}; + } +}; + +// std::type_info* is a lightuserdata +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::type_info* ptr) noexcept { + lua_pushlightuserdata(state, const_cast(ptr)); + return PushedObject{state, 1}; + } +}; + +// thread +template<> +struct LuaContext::Pusher { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const LuaContext::ThreadID& value) noexcept { + lua_pushthread(value.state); + return PushedObject{state, 1}; + } +}; + +// maps +template +struct LuaContext::Pusher> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::map& value) noexcept { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table key"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table value"); + + auto obj = Pusher::push(state, EmptyArray); + + for (auto i = value.begin(), e = value.end(); i != e; ++i) + setTable(state, obj, i->first, i->second); + + return obj; + } +}; + +// unordered_maps +template +struct LuaContext::Pusher> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::unordered_map& value) noexcept { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table key"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table value"); + + auto obj = Pusher::push(state, EmptyArray); + + for (auto i = value.begin(), e = value.end(); i != e; ++i) + setTable(state, obj, i->first, i->second); + + return obj; + } +}; + +// vectors of pairs +template +struct LuaContext::Pusher>> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::vector>& value) noexcept { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table key"); + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table value"); + + auto obj = Pusher::push(state, EmptyArray); + + for (auto i = value.begin(), e = value.end(); i != e; ++i) + setTable(state, obj, i->first, i->second); + + return obj; + } +}; + +// vectors +template +struct LuaContext::Pusher> { + static const int minSize = 1; + static const int maxSize = 1; + + static PushedObject push(lua_State* state, const std::vector& value) noexcept { + static_assert(Pusher::type>::minSize == 1 && Pusher::type>::maxSize == 1, "Can't push multiple elements for a table value"); + + auto obj = Pusher::push(state, EmptyArray); + + for (unsigned int i = 0; i < value.size(); ++i) + setTable(state, obj, i + 1, value[i]); + + return obj; + } +}; + +// unique_ptr +template +struct LuaContext::Pusher> { + static const int minSize = Pusher>::minSize; + static const int maxSize = Pusher>::maxSize; + + static PushedObject push(lua_State* state, std::unique_ptr value) noexcept { + return Pusher>::push(state, std::move(value)); + } +}; + +// enum +template +struct LuaContext::Pusher::value>::type> { + #if !defined(__clang__) || __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ > 3) + typedef typename std::underlying_type::type + RealType; + #else + // implementation when std::underlying_type is not supported + typedef unsigned long + RealType; + #endif + + static const int minSize = Pusher::minSize; + static const int maxSize = Pusher::maxSize; + + static PushedObject push(lua_State* state, TEnum value) noexcept { + return Pusher::push(state, static_cast(value)); + } +}; + +// any function +// this specialization is not directly called, but is called by other specializations +template +struct LuaContext::Pusher +{ + static const int minSize = 1; + static const int maxSize = 1; + + // counts the number of arguments + typedef FunctionArgumentsCounter + LocalFunctionArgumentsCounter; + + // this is the version of "push" for non-trivially destructible function objects + template + static auto push(lua_State* state, TFunctionObject fn) noexcept + -> typename std::enable_if::value, PushedObject>::type + { + // TODO: is_move_constructible not supported by some compilers + //static_assert(std::is_move_constructible::value, "The function object must be move-constructible"); + + // when the lua script calls the thing we will push on the stack, we want "fn" to be executed + // if we used lua's cfunctions system, we could not detect when the function is no longer in use, which could cause problems + // so we use userdata instead + + // this function is called when the lua script tries to call our custom data type + // we transfer execution to the "callback" function below + const auto callCallback = [](lua_State* lua) -> int { + assert(lua_gettop(lua) >= 1); + assert(lua_isuserdata(lua, 1)); + auto function = static_cast(lua_touserdata(lua, 1)); + assert(function); + + return callback(lua, function, lua_gettop(lua) - 1).release(); + }; + + // this one is called when lua's garbage collector no longer needs our custom data type + // we call the function object's destructor + const auto garbageCallback = [](lua_State* lua) -> int { + assert(lua_gettop(lua) == 1); + auto function = static_cast(lua_touserdata(lua, 1)); + assert(function); + function->~TFunctionObject(); + return 0; + }; + + // creating the object + // lua_newuserdata allocates memory in the internals of the lua library and returns it so we can fill it + // and that's what we do with placement-new + const auto functionLocation = static_cast(lua_newuserdata(state, sizeof(TFunctionObject))); + new (functionLocation) TFunctionObject(std::move(fn)); + + // creating the metatable (over the object on the stack) + // lua_settable pops the key and value we just pushed, so stack management is easy + // all that remains on the stack after these function calls is the metatable + lua_newtable(state); + lua_pushstring(state, "__call"); + lua_pushcfunction(state, callCallback); + lua_settable(state, -3); + + lua_pushstring(state, "__gc"); + lua_pushcfunction(state, garbageCallback); + lua_settable(state, -3); + + // at this point, the stack contains the object at offset -2 and the metatable at offset -1 + // lua_setmetatable will bind the two together and pop the metatable + // our custom function remains on the stack (and that's what we want) + lua_setmetatable(state, -2); + + return PushedObject{state, 1}; + } + + // this is the version of "push" for trivially destructible objects + template + static auto push(lua_State* state, TFunctionObject fn) noexcept + -> typename std::enable_if::value, PushedObject>::type + { + // TODO: is_move_constructible not supported by some compilers + //static_assert(std::is_move_constructible::value, "The function object must be move-constructible"); + + // when the lua script calls the thing we will push on the stack, we want "fn" to be executed + // since "fn" doesn't need to be destroyed, we simply push it on the stack + + // this is the cfunction that is the callback + const auto function = [](lua_State* state_) -> int + { + // the function object is an upvalue + const auto toCall = static_cast(lua_touserdata(state_, lua_upvalueindex(1))); + return callback(state_, toCall, lua_gettop(state_)).release(); + }; + + // we copy the function object onto the stack + const auto functionObjectLocation = static_cast(lua_newuserdata(state, sizeof(TFunctionObject))); + new (functionObjectLocation) TFunctionObject(std::move(fn)); + + // pushing the function with the function object as upvalue + lua_pushcclosure(state, function, 1); + return PushedObject{state, 1}; + } + + // this is the version of "push" for pointer to functions + static auto push(lua_State* state, TReturnType (*fn)(TParameters...)) noexcept + -> PushedObject + { + // when the lua script calls the thing we will push on the stack, we want "fn" to be executed + // since "fn" doesn't need to be destroyed, we simply push it on the stack + + // this is the cfunction that is the callback + const auto function = [](lua_State* state_) -> int + { + // the function object is an upvalue + const auto toCall = reinterpret_cast(lua_touserdata(state_, lua_upvalueindex(1))); + return callback(state_, toCall, lua_gettop(state_)).release(); + }; + + // we copy the function object onto the stack + lua_pushlightuserdata(state, reinterpret_cast(fn)); + + // pushing the function with the function object as upvalue + lua_pushcclosure(state, function, 1); + return PushedObject{state, 1}; + } + + // this is the version of "push" for references to functions + static auto push(lua_State* state, TReturnType (&fn)(TParameters...)) noexcept + -> PushedObject + { + return push(state, &fn); + } + +private: + // callback that calls the function object + // this function is used by the callbacks and handles loading arguments from the stack and pushing the return value back + template + static auto callback(lua_State* state, TFunctionObject* toCall, int argumentsCount) + -> PushedObject + { + // checking if number of parameters is correct + if (argumentsCount < LocalFunctionArgumentsCounter::min) { + // if not, using lua_error to return an error + luaL_where(state, 1); + lua_pushstring(state, "This function requires at least "); + lua_pushnumber(state, LocalFunctionArgumentsCounter::min); + lua_pushstring(state, " parameter(s)"); + lua_concat(state, 4); + luaError(state); + + } else if (argumentsCount > LocalFunctionArgumentsCounter::max) { + // if not, using lua_error to return an error + luaL_where(state, 1); + lua_pushstring(state, "This function requires at most "); + lua_pushnumber(state, LocalFunctionArgumentsCounter::max); + lua_pushstring(state, " parameter(s)"); + lua_concat(state, 4); + luaError(state); + } + + // calling the function + try { + return callback2(state, *toCall, argumentsCount); + + } catch (const WrongTypeException& ex) { + // wrong parameter type, using lua_error to return an error + luaL_where(state, 1); + lua_pushstring(state, "Unable to convert parameter from "); + lua_pushstring(state, ex.luaType.c_str()); + lua_pushstring(state, " to "); + lua_pushstring(state, ex.destination.name()); + lua_concat(state, 5); + luaError(state); + + } catch (const std::exception& e) { + luaL_where(state, 1); + lua_pushstring(state, "Caught exception: "); + lua_pushstring(state, e.what()); + lua_concat(state, 3); + luaError(state); + } catch (...) { + Pusher::push(state, std::current_exception()).release(); + luaError(state); + } + } + + template + static auto callback2(lua_State* state, TFunctionObject&& toCall, int argumentsCount) + -> typename std::enable_if::value && !std::is_void::value, PushedObject>::type + { + // pushing the result on the stack and returning number of pushed elements + typedef Pusher::type> + P; + return P::push(state, readIntoFunction(state, tag{}, toCall, -argumentsCount, tag{}...)); + } + + template + static auto callback2(lua_State* state, TFunctionObject&& toCall, int argumentsCount) + -> typename std::enable_if::value && !std::is_void::value, PushedObject>::type + { + readIntoFunction(state, tag{}, toCall, -argumentsCount, tag{}...); + return PushedObject{state, 0}; + } +}; + +// C function pointers +template +struct LuaContext::Pusher +{ + // using the function-pushing implementation + typedef Pusher + SubPusher; + static const int minSize = SubPusher::minSize; + static const int maxSize = SubPusher::maxSize; + + template + static PushedObject push(lua_State* state, TType value) noexcept { + return SubPusher::push(state, value); + } +}; + +// C function references +template +struct LuaContext::Pusher +{ + // using the function-pushing implementation + typedef Pusher + SubPusher; + static const int minSize = SubPusher::minSize; + static const int maxSize = SubPusher::maxSize; + + template + static PushedObject push(lua_State* state, TType value) noexcept { + return SubPusher::push(state, value); + } +}; + +// std::function +template +struct LuaContext::Pusher> +{ + // using the function-pushing implementation + typedef Pusher + SubPusher; + static const int minSize = SubPusher::minSize; + static const int maxSize = SubPusher::maxSize; + + static PushedObject push(lua_State* state, const std::function& value) noexcept { + return SubPusher::push(state, value); + } +}; + +// boost::variant +template +struct LuaContext::Pusher> +{ + static const int minSize = PusherMinSize::size; + static const int maxSize = PusherMaxSize::size; + + static PushedObject push(lua_State* state, const boost::variant& value) noexcept { + PushedObject obj{state, 0}; + VariantWriter writer{state, obj}; + value.apply_visitor(writer); + return obj; + } + +private: + struct VariantWriter : public boost::static_visitor<> { + template + void operator()(TType value) noexcept + { + obj = Pusher::type>::push(state, std::move(value)); + } + + VariantWriter(lua_State* state_, PushedObject& obj_) : state(state_), obj(obj_) {} + lua_State* state; + PushedObject& obj; + }; +}; + +// boost::optional +template +struct LuaContext::Pusher> { + typedef Pusher::type> + UnderlyingPusher; + + static const int minSize = UnderlyingPusher::minSize < 1 ? UnderlyingPusher::minSize : 1; + static const int maxSize = UnderlyingPusher::maxSize > 1 ? UnderlyingPusher::maxSize : 1; + + static PushedObject push(lua_State* state, const boost::optional& value) noexcept { + if (value) { + return UnderlyingPusher::push(state, value.get()); + } else { + lua_pushnil(state); + return PushedObject{state, 1}; + } + } +}; + +// tuple +template +struct LuaContext::Pusher> { + // TODO: NOT EXCEPTION SAFE /!\ // + static const int minSize = PusherTotalMinSize::size; + static const int maxSize = PusherTotalMaxSize::size; + + static PushedObject push(lua_State* state, const std::tuple& value) noexcept { + return PushedObject{state, push2(state, value, std::integral_constant{})}; + } + + static PushedObject push(lua_State* state, std::tuple&& value) noexcept { + return PushedObject{state, push2(state, std::move(value), std::integral_constant{})}; + } + +private: + template + static int push2(lua_State* state, const std::tuple& value, std::integral_constant) noexcept { + typedef typename std::tuple_element>::type ElemType; + + return Pusher::type>::push(state, std::get(value)).release() + + push2(state, value, std::integral_constant{}); + } + + template + static int push2(lua_State* state, std::tuple&& value, std::integral_constant) noexcept { + typedef typename std::tuple_element>::type ElemType; + + return Pusher::type>::push(state, std::move(std::get(value))).release() + + push2(state, std::move(value), std::integral_constant{}); + } + + static int push2(lua_State* /*state*/, const std::tuple&, std::integral_constant) noexcept { + return 0; + } + + static int push2(lua_State* /*state*/, std::tuple&&, std::integral_constant) noexcept { + return 0; + } +}; + +/**************************************************/ +/* READ FUNCTIONS */ +/**************************************************/ +// specializations of the Reader structures + +// opaque Lua references +template<> +struct LuaContext::Reader +{ + static auto read(lua_State* state, int index) + -> boost::optional + { + LuaContext::LuaObject obj(state, index); + return obj; + } +}; + +// reading null +template<> +struct LuaContext::Reader +{ + static auto read(lua_State* state, int index) + -> boost::optional + { + if (!lua_isnil(state, index)) + return boost::none; + return nullptr; + } +}; + +// integrals +template +struct LuaContext::Reader< + TType, + typename std::enable_if::value>::type + > +{ + static auto read(lua_State* state, int index) + -> boost::optional + { +# if LUA_VERSION_NUM >= 502 + + int success; + auto value = lua_tointegerx(state, index, &success); + if (success == 0) + return boost::none; + return static_cast(value); + +# else + + if (!lua_isnumber(state, index)) + return boost::none; + return static_cast(lua_tointeger(state, index)); + +# endif + } +}; + +// floating points +template +struct LuaContext::Reader< + TType, + typename std::enable_if::value>::type + > +{ + static auto read(lua_State* state, int index) + -> boost::optional + { +# if LUA_VERSION_NUM >= 502 + + int success; + auto value = lua_tonumberx(state, index, &success); + if (success == 0) + return boost::none; + return static_cast(value); + +# else + + if (!lua_isnumber(state, index)) + return boost::none; + return static_cast(lua_tonumber(state, index)); + +# endif + } +}; + +// boolean +template<> +struct LuaContext::Reader +{ + static auto read(lua_State* state, int index) + -> boost::optional + { + if (!lua_isboolean(state, index)) + return boost::none; + return lua_toboolean(state, index) != 0; + } +}; + +// string +// lua_tostring returns a temporary pointer, but that's not a problem since we copy +// the data into a std::string +template<> +struct LuaContext::Reader +{ + static auto read(lua_State* state, int index) + -> boost::optional + { + size_t len; + const auto val = lua_tolstring(state, index, &len); + if (val == 0) + return boost::none; + return std::string(val, len); + } +}; + +// enums +template +struct LuaContext::Reader< + TType, + typename std::enable_if::value>::type + > +{ + static auto read(lua_State* state, int index) + -> boost::optional + { + if (!lua_isnumber(state, index) || fmod(lua_tonumber(state, index), 1.) != 0) + return boost::none; + return static_cast(lua_tointeger(state, index)); + } +}; + +// LuaFunctionCaller +template +struct LuaContext::Reader> +{ + typedef LuaFunctionCaller + ReturnType; + + static auto read(lua_State* state, int index) + -> boost::optional + { + if (lua_isfunction(state, index) == 0 && lua_isuserdata(state, index) == 0) + return boost::none; + return ReturnType(state, index); + } +}; + +// function +template +struct LuaContext::Reader> +{ + static auto read(lua_State* state, int index) + -> boost::optional> + { + if (auto val = Reader>::read(state, index)) + { + std::function f{*val}; + return boost::optional>{std::move(f)}; + } + + return boost::none; + } +}; + +// vector of pairs +template +struct LuaContext::Reader>> +{ + static auto read(lua_State* state, int index) + -> boost::optional>> + { + if (!lua_istable(state, index)) + return boost::none; + + std::vector> result; + + // we traverse the table at the top of the stack + lua_pushnil(state); // first key + while (lua_next(state, (index > 0) ? index : (index - 1)) != 0) { + // now a key and its value are pushed on the stack + try { + auto val1 = Reader::read(state, -2); + auto val2 = Reader::read(state, -1); + + if (!val1.is_initialized() || !val2.is_initialized()) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + + result.push_back({ val1.get(), val2.get() }); + lua_pop(state, 1); // we remove the value but keep the key for the next iteration + + } catch(...) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + } + + return { std::move(result) }; + } +}; + +// map +template +struct LuaContext::Reader> +{ + static auto read(lua_State* state, int index) + -> boost::optional> + { + if (!lua_istable(state, index)) + return boost::none; + + std::map result; + + // we traverse the table at the top of the stack + lua_pushnil(state); // first key + while (lua_next(state, (index > 0) ? index : (index - 1)) != 0) { + // now a key and its value are pushed on the stack + try { + auto key = Reader::read(state, -2); + auto value = Reader::read(state, -1); + + if (!key.is_initialized() || !value.is_initialized()) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + + result.insert({ key.get(), value.get() }); + lua_pop(state, 1); // we remove the value but keep the key for the next iteration + + } catch(...) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + } + + return { std::move(result) }; + } +}; + +// unordered_map +template +struct LuaContext::Reader> +{ + static auto read(lua_State* state, int index) + -> boost::optional> + { + if (!lua_istable(state, index)) + return boost::none; + + std::unordered_map result; + + // we traverse the table at the top of the stack + lua_pushnil(state); // first key + while (lua_next(state, (index > 0) ? index : (index - 1)) != 0) { + // now a key and its value are pushed on the stack + try { + auto key = Reader::read(state, -2); + auto value = Reader::read(state, -1); + + if (!key.is_initialized() || !value.is_initialized()) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + + result.insert({ key.get(), value.get() }); + lua_pop(state, 1); // we remove the value but keep the key for the next iteration + + } catch(...) { + lua_pop(state, 2); // we remove the value and the key + return {}; + } + } + + return { std::move(result) }; + } +}; + +// optional +// IMPORTANT: optional means "either nil or the value of the right type" +// * if the value is nil, then an optional containing an empty optional is returned +// * if the value is of the right type, then an optional containing an optional containing the value is returned +// * if the value is of the wrong type, then an empty optional is returned +template +struct LuaContext::Reader> +{ + static auto read(lua_State* state, int index) + -> boost::optional> + { + if (lua_isnil(state, index)) + return boost::optional{boost::none}; + if (auto&& other = Reader::read(state, index)) + return std::move(other); + return boost::none; + } +}; + +// variant +template +struct LuaContext::Reader> +{ + typedef boost::variant + ReturnType; + +private: + // class doing operations for a range of types from TIterBegin to TIterEnd + template + struct VariantReader + { + using SubReader = Reader::type>::type>; + + static auto read(lua_State* state, int index) + -> boost::optional + { + // note: using SubReader::read triggers a compilation error when used with a reference + if (const auto val = SubReader::read(state, index)) + return boost::variant{*val}; + return VariantReader::type, TIterEnd>::read(state, index); + } + }; + + // specialization of class above being called when list of remaining types is empty + template + struct VariantReader::type::value == 0>::type> + { + static auto read(lua_State* /*state*/, int /*index*/) + -> boost::optional + { + return boost::none; + } + }; + + // this is the main type + typedef VariantReader::type, typename boost::mpl::end::type> + MainVariantReader; + +public: + static auto read(lua_State* state, int index) + -> boost::optional + { + return MainVariantReader::read(state, index); + } +}; + +// reading a tuple +// tuple have an additional argument for their functions, that is the maximum size to read +// if maxSize is smaller than the tuple size, then the remaining parameters will be left to default value +template<> +struct LuaContext::Reader> +{ + static auto read(lua_State* /*state*/, int /*index*/, int /*maxSize*/ = 0) + -> boost::optional> + { + return std::tuple<>{}; + } +}; + +template +struct LuaContext::Reader, + typename std::enable_if::value>::type // TODO: replace by std::is_default_constructible when it works on every compiler + > +{ + // this is the "TFirst is NOT default constructible" version + + typedef std::tuple + ReturnType; + + static auto read(lua_State* state, int index, int maxSize = std::tuple_size::value) + -> boost::optional + { + if (maxSize <= 0) + return boost::none; + + auto firstVal = Reader::read(state, index); + auto othersVal = Reader>::read(state, index + 1, maxSize - 1); + + if (!firstVal || !othersVal) + return boost::none; + + return std::tuple_cat(std::tuple(*firstVal), std::move(*othersVal)); + } +}; + +template +struct LuaContext::Reader, + typename std::enable_if::value>::type // TODO: replace by std::is_default_constructible when it works on every compiler + > +{ + // this is the "TFirst is default-constructible" version + + typedef std::tuple + ReturnType; + + static auto read(lua_State* state, int index, int maxSize = std::tuple_size::value) + -> boost::optional + { + auto othersVal = Reader>::read(state, index + 1, maxSize - 1); + if (!othersVal) + return boost::none; + + if (maxSize <= 0) + return std::tuple_cat(std::tuple(), std::move(*othersVal)); + + auto firstVal = Reader::read(state, index); + if (!firstVal) + return boost::none; + + return std::tuple_cat(std::tuple(*firstVal), std::move(*othersVal)); + } +}; + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/ext/yahttp/LICENSE b/ext/yahttp/LICENSE new file mode 100644 index 0000000..08f6f64 --- /dev/null +++ b/ext/yahttp/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Aki Tuomi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ext/yahttp/Makefile.am b/ext/yahttp/Makefile.am new file mode 100644 index 0000000..aaaeee0 --- /dev/null +++ b/ext/yahttp/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = yahttp + +EXTRA_DIST = LICENSE README.md diff --git a/ext/yahttp/Makefile.in b/ext/yahttp/Makefile.in new file mode 100644 index 0000000..be29a54 --- /dev/null +++ b/ext/yahttp/Makefile.in @@ -0,0 +1,774 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = ext/yahttp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-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 +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = yahttp +EXTRA_DIST = LICENSE README.md +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ext/yahttp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign ext/yahttp/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || 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; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/ext/yahttp/README.md b/ext/yahttp/README.md new file mode 100644 index 0000000..86794b5 --- /dev/null +++ b/ext/yahttp/README.md @@ -0,0 +1,69 @@ +Yet Another HTTP Library +======================== + +YaHTTP aims to be a pure http request/response parser that has no IO ties. It is intended to be used on small-footprint applications and other utilities that want to use HTTP over something else than network IO. + +[![Build Status](https://travis-ci.org/cmouse/yahttp.svg?branch=master)](https://travis-ci.org/cmouse/yahttp) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/2161/badge.svg)](https://scan.coverity.com/projects/2161) +[![Coverage Status](https://coveralls.io/repos/github/cmouse/yahttp/badge.svg)](https://coveralls.io/github/cmouse/yahttp) + +WARNINGS +-------- +If you are upgrading from version before May 02, 2014 - *PLEASE BE SURE TO CHECK THAT EVERYTHING WORKS AS EXPECTED*. There has been complete overhaul of the library and many things have changed. + +NOTES +----- +Do not use resp = req, or resp(req) to build the response object, despite it being supported. This will cause request headers to get duplicated. Also, you *must* set response#version to request#version if you intend to support older than HTTP/1.1 clients. Set response#status to at least 200, it won't be done for you. No Server or Product token is sent either, you can add those if you want. + +If you do not want to send chunked responses, set content-length header. Setting this header will always disable chunked responses. This will also happen if you downgrade your responses to version 10 or 9. + +Integration guide +----------------- + +Here are some instructions on how to integrate YaHTTP into your project. + +With automake and libtool +------------------------- + +If you don't need router or any of the C++11 features, you can just create empty yahttp-config.h, or symlink it to your project's config.h for the yahttp.hpp to include. Then just put this stuff into it's own folder and create Makefile.am with following contents (you can change the compilation flags): + +``` +noinst_LTLIBRARIES=libyahttp.la +libyahttp_la_CXXFLAGS=$(RELRO_CFLAGS) $(PIE_CFLAGS) -D__STRICT_ANSI__ +libyahttp_la_SOURCES=cookie.hpp exception.hpp reqresp.cpp reqresp.hpp router.cpp router.hpp url.hpp utility.hpp yahttp.hpp +``` + +You can define RELRO and PIE to match your project. + +To compile your project use -Lpath/to/yahttp -lyahttp + +If you need router, additionally check for boost or C++11 and replace yahttp-config.h to config.h in yahttp.hpp or add relevant options to your compiler CXXFLAGS. See below for the flags. + +Without automake +---------------- + +Create simple Makefile with contents for C++11: + +``` +OBJECTS=reqresp.o router.o +CXX=gcc +CXXFLAGS=-W -Wall -DHAVE_CXX11 -std=c++11 +``` + +Or create simple Makefile with contents for boost: + +``` +OBJECTS=reqresp.o router.o +CXX=gcc +CXXFLAGS=-W -Wall -DHAVE_BOOST +``` + +Or if you don't need either one, just: + +``` +OBJECTS=reqresp.o +CXX=gcc +CXXFLAGS=-W -Wall +``` + +YaHTTP include files can be placed where the rest of your includes are. Then just add your own code there and it should work just fine. diff --git a/ext/yahttp/yahttp/Makefile.am b/ext/yahttp/yahttp/Makefile.am new file mode 100644 index 0000000..3ed41e5 --- /dev/null +++ b/ext/yahttp/yahttp/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libyahttp.la + +libyahttp_la_SOURCES = \ + cookie.hpp \ + exception.hpp \ + reqresp.cpp \ + reqresp.hpp \ + router.cpp \ + router.hpp \ + url.hpp \ + utility.hpp \ + yahttp-config.h \ + yahttp.hpp diff --git a/ext/yahttp/yahttp/Makefile.in b/ext/yahttp/yahttp/Makefile.in new file mode 100644 index 0000000..e212d22 --- /dev/null +++ b/ext/yahttp/yahttp/Makefile.in @@ -0,0 +1,774 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = ext/yahttp/yahttp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libyahttp_la_LIBADD = +am_libyahttp_la_OBJECTS = reqresp.lo router.lo +libyahttp_la_OBJECTS = $(am_libyahttp_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libyahttp_la_SOURCES) +DIST_SOURCES = $(libyahttp_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libyahttp.la +libyahttp_la_SOURCES = \ + cookie.hpp \ + exception.hpp \ + reqresp.cpp \ + reqresp.hpp \ + router.cpp \ + router.hpp \ + url.hpp \ + utility.hpp \ + yahttp-config.h \ + yahttp.hpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ext/yahttp/yahttp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign ext/yahttp/yahttp/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libyahttp.la: $(libyahttp_la_OBJECTS) $(libyahttp_la_DEPENDENCIES) $(EXTRA_libyahttp_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libyahttp_la_OBJECTS) $(libyahttp_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reqresp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/router.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/ext/yahttp/yahttp/cookie.hpp b/ext/yahttp/yahttp/cookie.hpp new file mode 100644 index 0000000..c597c7c --- /dev/null +++ b/ext/yahttp/yahttp/cookie.hpp @@ -0,0 +1,143 @@ +namespace YaHTTP { + /*! Implements a single cookie */ + class Cookie { + public: + Cookie() { + secure = false; + httponly = false; + name = value = ""; + expires = DateTime(); + }; //!< Set the cookie to empty value + + Cookie(const Cookie &rhs) { + name = rhs.name; + value = rhs.value; + domain = rhs.domain; + path = rhs.path; + secure = rhs.secure; + httponly = rhs.httponly; + expires = rhs.expires; + }; //0) + oss << "; domain=" << domain; + if (path.size()>0) + oss << "; path=" << path; + if (secure) + oss << "; secure"; + if (httponly) + oss << "; httpOnly"; + return oss.str(); + }; //!< Stringify the cookie + }; + + /*! Implements a Cookie jar for storing multiple cookies */ + class CookieJar { + public: + std::map cookies; //cookies = rhs.cookies; + } //cookies.clear(); + } + + void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value) { + size_t pos; + pos = keyvalue.find("="); + if (pos == std::string::npos) throw "Not a Key-Value pair (cookie)"; + key = std::string(keyvalue.begin(), keyvalue.begin()+pos); + value = std::string(keyvalue.begin()+pos+1, keyvalue.end()); + } // lcookies; + Cookie c; + pos = 0; + while(pos < cookiestr.size()) { + if ((npos = cookiestr.find("; ", pos)) == std::string::npos) + npos = cookiestr.size(); + keyValuePair(cookiestr.substr(pos, npos-pos), c.name, c.value); + c.name = YaHTTP::Utility::decodeURL(c.name); + c.value = YaHTTP::Utility::decodeURL(c.value); + lcookies.push_back(c); + pos = npos+2; + } + for(std::list::iterator i = lcookies.begin(); i != lcookies.end(); i++) { + this->cookies[i->name] = *i; + } + } + + void parseSetCookieHeader(const std::string &cookiestr) { + Cookie c; + size_t pos,npos; + std::string k, v; + + if ((pos = cookiestr.find("; ", 0)) == std::string::npos) + pos = cookiestr.size(); + keyValuePair(cookiestr.substr(0, pos), c.name, c.value); + c.name = YaHTTP::Utility::decodeURL(c.name); + c.value = YaHTTP::Utility::decodeURL(c.value); + if (pos < cookiestr.size()) pos+=2; + + while(pos < cookiestr.size()) { + if ((npos = cookiestr.find("; ", pos)) == std::string::npos) + npos = cookiestr.size(); + std::string s = cookiestr.substr(pos, npos-pos); + if (s.find("=") != std::string::npos) + keyValuePair(s, k, v); + else + k = s; + if (k == "expires") { + DateTime dt; + dt.parseCookie(v); + c.expires = dt; + } else if (k == "domain") { + c.domain = v; + } else if (k == "path") { + c.path = v; + } else if (k == "httpOnly") { + c.httponly = true; + } else if (k == "secure") { + c.secure = true; + } else { + // ignore crap + break; + } + pos = npos+2; + } + + this->cookies[c.name] = c; + }; // + +namespace YaHTTP { + /*! Generic error class */ + class Error: public std::exception { + public: + Error() {}; + Error(const std::string& reason_): reason(reason_) {}; + virtual ~Error() throw() {}; + + virtual const char* what() const throw() + { + return reason.c_str(); + } + const std::string reason; // + bool AsyncLoader::feed(const std::string& somedata) { + buffer.append(somedata); + while(state < 2) { + int cr=0; + pos = buffer.find_first_of("\n"); + // need to find CRLF in buffer + if (pos == std::string::npos) return false; + if (pos>0 && buffer[pos-1]=='\r') + cr=1; + std::string line(buffer.begin(), buffer.begin()+pos-cr); // exclude CRLF + buffer.erase(buffer.begin(), buffer.begin()+pos+1); // remove line from buffer including CRLF + + if (state == 0) { // startup line + if (target->kind == YAHTTP_TYPE_REQUEST) { + std::string ver; + std::string tmpurl; + std::istringstream iss(line); + iss >> target->method >> tmpurl >> ver; + if (ver.size() == 0) + target->version = 9; + else if (ver.find("HTTP/0.9") == 0) + target->version = 9; + else if (ver.find("HTTP/1.0") == 0) + target->version = 10; + else if (ver.find("HTTP/1.1") == 0) + target->version = 11; + else + throw ParseError("HTTP version not supported"); + // uppercase the target method + std::transform(target->method.begin(), target->method.end(), target->method.begin(), ::toupper); + target->url.parse(tmpurl); + target->getvars = Utility::parseUrlParameters(target->url.parameters); + state = 1; + } else if(target->kind == YAHTTP_TYPE_RESPONSE) { + std::string ver; + std::istringstream iss(line); + std::string::size_type pos1; + iss >> ver >> target->status; + std::getline(iss, target->statusText); + pos1=0; + while(pos1 < target->statusText.size() && YaHTTP::isspace(target->statusText.at(pos1))) pos1++; + target->statusText = target->statusText.substr(pos1); + if ((pos1 = target->statusText.find("\r")) != std::string::npos) { + target->statusText = target->statusText.substr(0, pos1-1); + } + if (ver.size() == 0) { + target->version = 9; + } else if (ver.find("HTTP/0.9") == 0) + target->version = 9; + else if (ver.find("HTTP/1.0") == 0) + target->version = 10; + else if (ver.find("HTTP/1.1") == 0) + target->version = 11; + else + throw ParseError("HTTP version not supported"); + state = 1; + } + } else if (state == 1) { + std::string key,value; + size_t pos1; + if (line.empty()) { + chunked = (target->headers.find("transfer-encoding") != target->headers.end() && target->headers["transfer-encoding"] == "chunked"); + state = 2; + break; + } + // split headers + if ((pos1 = line.find(":")) == std::string::npos) { + throw ParseError("Malformed header line"); + } + key = line.substr(0, pos1); + value = line.substr(pos1 + 1); + for(std::string::iterator it=key.begin(); it != key.end(); it++) + if (YaHTTP::isspace(*it)) + throw ParseError("Header key contains whitespace which is not allowed by RFC"); + + Utility::trim(value); + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + // is it already defined + + if (key == "set-cookie" && target->kind == YAHTTP_TYPE_RESPONSE) { + target->jar.parseSetCookieHeader(value); + } else if (key == "cookie" && target->kind == YAHTTP_TYPE_REQUEST) { + target->jar.parseCookieHeader(value); + } else { + if (key == "host" && target->kind == YAHTTP_TYPE_REQUEST) { + // maybe it contains port? + if ((pos1 = value.find(":")) == std::string::npos) { + target->url.host = value; + } else { + target->url.host = value.substr(0, pos1); + target->url.port = ::atoi(value.substr(pos1).c_str()); + } + } + if (target->headers.find(key) != target->headers.end()) { + target->headers[key] = target->headers[key] + ";" + value; + } else { + target->headers[key] = value; + } + } + } + } + + minbody = 0; + // check for expected body size + if (target->kind == YAHTTP_TYPE_REQUEST) maxbody = target->max_request_size; + else if (target->kind == YAHTTP_TYPE_RESPONSE) maxbody = target->max_response_size; + else maxbody = 0; + + if (!chunked) { + if (target->headers.find("content-length") != target->headers.end()) { + std::istringstream maxbodyS(target->headers["content-length"]); + maxbodyS >> minbody; + maxbody = minbody; + } + if (minbody < 1) return true; // guess there isn't anything left. + if (target->kind == YAHTTP_TYPE_REQUEST && static_cast(minbody) > target->max_request_size) throw ParseError("Max request body size exceeded"); + else if (target->kind == YAHTTP_TYPE_RESPONSE && static_cast(minbody) > target->max_response_size) throw ParseError("Max response body size exceeded"); + } + + if (maxbody == 0) hasBody = false; + else hasBody = true; + + if (buffer.size() == 0) return ready(); + + while(buffer.size() > 0) { + if (chunked) { + if (chunk_size == 0) { + char buf[100]; + // read chunk length + if ((pos = buffer.find('\n')) == std::string::npos) return false; + if (pos > 99) + throw ParseError("Impossible chunk_size"); + buffer.copy(buf, pos); + buf[pos]=0; // just in case... + buffer.erase(buffer.begin(), buffer.begin()+pos+1); // remove line from buffer + sscanf(buf, "%x", &chunk_size); + if (chunk_size == 0) { state = 3; break; } // last chunk + } else { + int crlf=1; + if (buffer.size() < static_cast(chunk_size+1)) return false; // expect newline + if (buffer.at(chunk_size) == '\r') { + if (buffer.size() < static_cast(chunk_size+2) || buffer.at(chunk_size+1) != '\n') return false; // expect newline after carriage return + crlf=2; + } else if (buffer.at(chunk_size) != '\n') return false; + std::string tmp = buffer.substr(0, chunk_size); + buffer.erase(buffer.begin(), buffer.begin()+chunk_size+crlf); + bodybuf << tmp; + chunk_size = 0; + if (buffer.size() == 0) break; // just in case + } + } else { + if (bodybuf.str().length() + buffer.length() > maxbody) + bodybuf << buffer.substr(0, maxbody - bodybuf.str().length()); + else + bodybuf << buffer; + buffer = ""; + } + } + + if (chunk_size!=0) return false; // need more data + + return ready(); + }; + + void HTTPBase::write(std::ostream& os) const { + if (kind == YAHTTP_TYPE_REQUEST) { + std::ostringstream getparmbuf; + std::string getparms; + // prepare URL + for(strstr_map_t::const_iterator i = getvars.begin(); i != getvars.end(); i++) { + getparmbuf << Utility::encodeURL(i->first, false) << "=" << Utility::encodeURL(i->second, false) << "&"; + } + if (getparmbuf.str().length() > 0) { + std::string buf = getparmbuf.str(); + getparms = "?" + std::string(buf.begin(), buf.end() - 1); + } + else + getparms = ""; + os << method << " " << url.path << getparms << " HTTP/" << versionStr(this->version); + } else if (kind == YAHTTP_TYPE_RESPONSE) { + os << "HTTP/" << versionStr(this->version) << " " << status << " "; + if (statusText.empty()) + os << Utility::status2text(status); + else + os << statusText; + } + os << "\r\n"; + + bool cookieSent = false; + bool sendChunked = false; + + if (this->version > 10) { // 1.1 or better + if (headers.find("content-length") == headers.end() && !this->is_multipart) { + // must use chunked on response + sendChunked = (kind == YAHTTP_TYPE_RESPONSE); + if ((headers.find("transfer-encoding") != headers.end() && headers.find("transfer-encoding")->second != "chunked")) { + throw YaHTTP::Error("Transfer-encoding must be chunked, or Content-Length defined"); + } + if ((headers.find("transfer-encoding") == headers.end() && kind == YAHTTP_TYPE_RESPONSE)) { + sendChunked = true; + os << "Transfer-Encoding: chunked\r\n"; + } + } else { + sendChunked = false; + } + } + + // write headers + strstr_map_t::const_iterator iter = headers.begin(); + while(iter != headers.end()) { + if (iter->first == "host" && (kind != YAHTTP_TYPE_REQUEST || version < 10)) { iter++; continue; } + if (iter->first == "transfer-encoding" && sendChunked) { iter++; continue; } + std::string header = Utility::camelizeHeader(iter->first); + if (header == "Cookie" || header == "Set-Cookie") cookieSent = true; + os << Utility::camelizeHeader(iter->first) << ": " << iter->second << "\r\n"; + iter++; + } + if (version > 9 && !cookieSent && jar.cookies.size() > 0) { // write cookies + if (kind == YAHTTP_TYPE_REQUEST) { + bool first = true; + os << "Cookie: "; + for(strcookie_map_t::const_iterator i = jar.cookies.begin(); i != jar.cookies.end(); i++) { + if (first) + first = false; + else + os << "; "; + os << Utility::encodeURL(i->second.name) << "=" << Utility::encodeURL(i->second.value); + } + } else if (kind == YAHTTP_TYPE_RESPONSE) { + for(strcookie_map_t::const_iterator i = jar.cookies.begin(); i != jar.cookies.end(); i++) { + os << "Set-Cookie: "; + os << i->second.str() << "\r\n"; + } + } + } + os << "\r\n"; +#ifdef HAVE_CPP_FUNC_PTR + this->renderer(this, os, sendChunked); +#else + SendbodyRenderer r; + r(this, os, chunked) +#endif + }; + + std::ostream& operator<<(std::ostream& os, const Response &resp) { + resp.write(os); + return os; + }; + + std::istream& operator>>(std::istream& is, Response &resp) { + YaHTTP::AsyncResponseLoader arl; + arl.initialize(&resp); + while(is.good()) { + char buf[1024]; + is.read(buf, 1024); + if (is.gcount()>0) { // did we actually read anything + is.clear(); + if (arl.feed(std::string(buf, is.gcount())) == true) break; // completed + } + } + // throw unless ready + if (arl.ready() == false) + throw ParseError("Was not able to extract a valid Response from stream"); + arl.finalize(); + return is; + }; + + std::ostream& operator<<(std::ostream& os, const Request &req) { + req.write(os); + return os; + }; + + std::istream& operator>>(std::istream& is, Request &req) { + YaHTTP::AsyncRequestLoader arl; + arl.initialize(&req); + while(is.good()) { + char buf[1024]; + is.read(buf, 1024); + if (is.gcount() > 0) { // did we actually read anything + is.clear(); + if (arl.feed(std::string(buf, is.gcount())) == true) break; // completed + } + } + if (arl.ready() == false) + throw ParseError("Was not able to extract a valid Request from stream"); + arl.finalize(); + return is; + }; +}; diff --git a/ext/yahttp/yahttp/reqresp.hpp b/ext/yahttp/yahttp/reqresp.hpp new file mode 100644 index 0000000..d9e7a19 --- /dev/null +++ b/ext/yahttp/yahttp/reqresp.hpp @@ -0,0 +1,351 @@ +#ifdef HAVE_CXX11 +#include +#define HAVE_CPP_FUNC_PTR +namespace funcptr = std; +#else +#ifdef HAVE_BOOST +#include +namespace funcptr = boost; +#define HAVE_CPP_FUNC_PTR +#endif +#endif + +#include +#include + +#ifndef WIN32 +#include +#include +#endif + +#include + +#ifndef YAHTTP_MAX_REQUEST_SIZE +#define YAHTTP_MAX_REQUEST_SIZE 2097152 +#endif + +#ifndef YAHTTP_MAX_RESPONSE_SIZE +#define YAHTTP_MAX_RESPONSE_SIZE 2097152 +#endif + +#define YAHTTP_TYPE_REQUEST 1 +#define YAHTTP_TYPE_RESPONSE 2 + +namespace YaHTTP { + typedef std::map strcookie_map_t; //body.length();i+=1024) { + cl = std::min(static_cast(1024), doc->body.length()-i); // for less than 1k blocks + os << std::hex << cl << std::dec << "\r\n"; + os << doc->body.substr(i, cl) << "\r\n"; + } + os << 0 << "\r\n\r\n"; // last chunk + } else { + os << doc->body; + } + return doc->body.length(); + }; //path = path_; + }; + + size_t operator()(const HTTPBase *doc __attribute__((unused)), std::ostream& os, bool chunked) const { + char buf[4096]; + size_t n,k; +#ifdef HAVE_CXX11 + std::ifstream ifs(path, std::ifstream::binary); +#else + std::ifstream ifs(path.c_str(), std::ifstream::binary); +#endif + n = 0; + + while(ifs.good()) { + ifs.read(buf, sizeof buf); + n += (k = ifs.gcount()); + if (k > 0) { + if (chunked) os << std::hex << k << std::dec << "\r\n"; + os.write(buf, k); + if (chunked) os << "\r\n"; + } + } + if (chunked) os << 0 << "\r\n\r\n"; + return n; + }; //url = rhs.url; this->kind = rhs.kind; + this->status = rhs.status; this->statusText = rhs.statusText; + this->method = rhs.method; this->headers = rhs.headers; + this->jar = rhs.jar; this->postvars = rhs.postvars; + this->parameters = rhs.parameters; this->getvars = rhs.getvars; + this->body = rhs.body; this->max_request_size = rhs.max_request_size; + this->max_response_size = rhs.max_response_size; this->version = rhs.version; +#ifdef HAVE_CPP_FUNC_PTR + this->renderer = rhs.renderer; +#endif + this->is_multipart = rhs.is_multipart; + }; + HTTPBase& operator=(const HTTPBase& rhs) { + this->url = rhs.url; this->kind = rhs.kind; + this->status = rhs.status; this->statusText = rhs.statusText; + this->method = rhs.method; this->headers = rhs.headers; + this->jar = rhs.jar; this->postvars = rhs.postvars; + this->parameters = rhs.parameters; this->getvars = rhs.getvars; + this->body = rhs.body; this->max_request_size = rhs.max_request_size; + this->max_response_size = rhs.max_response_size; this->version = rhs.version; +#ifdef HAVE_CPP_FUNC_PTR + this->renderer = rhs.renderer; +#endif + this->is_multipart = rhs.is_multipart; + return *this; + }; +public: + URL url; // renderer; //kind = YAHTTP_TYPE_RESPONSE; + }; + Response& operator=(const HTTPBase& rhs) { + HTTPBase::operator=(rhs); + this->kind = YAHTTP_TYPE_RESPONSE; + return *this; + }; + void initialize() { + HTTPBase::initialize(); + this->kind = YAHTTP_TYPE_RESPONSE; + } + void initialize(const HTTPBase& rhs) { + HTTPBase::initialize(); + this->kind = YAHTTP_TYPE_RESPONSE; + // copy SOME attributes + this->url = rhs.url; + this->method = rhs.method; + this->jar = rhs.jar; + this->version = rhs.version; + } + friend std::ostream& operator<<(std::ostream& os, const Response &resp); + friend std::istream& operator>>(std::istream& is, Response &resp); + }; + + /* Request class, represents a HTTP Request document */ + class Request: public HTTPBase { + public: + Request() { initialize(); }; + Request(const HTTPBase& rhs): HTTPBase(rhs) { + this->kind = YAHTTP_TYPE_REQUEST; + }; + Request& operator=(const HTTPBase& rhs) { + HTTPBase::operator=(rhs); + this->kind = YAHTTP_TYPE_REQUEST; + return *this; + }; + void initialize() { + HTTPBase::initialize(); + this->kind = YAHTTP_TYPE_REQUEST; + } + void initialize(const HTTPBase& rhs) { + HTTPBase::initialize(); + this->kind = YAHTTP_TYPE_REQUEST; + // copy SOME attributes + this->url = rhs.url; + this->method = rhs.method; + this->jar = rhs.jar; + this->version = rhs.version; + } + void setup(const std::string& method_, const std::string& url_) { + this->url.parse(url_); + this->headers["host"] = this->url.host; + this->method = method_; + std::transform(this->method.begin(), this->method.end(), this->method.begin(), ::toupper); + this->headers["user-agent"] = "YaHTTP v1.0"; + }; //first, false) << "=" << Utility::encodeURL(i->second, false) << "&"; + } + // remove last bit + if (postbuf.str().length()>0) + body = postbuf.str().substr(0, postbuf.str().length()-1); + else + body = ""; + headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + } else if (format == multipart) { + headers["content-type"] = "multipart/form-data; boundary=YaHTTP-12ca543"; + this->is_multipart = true; + for(strstr_map_t::const_iterator i = POST().begin(); i != POST().end(); i++) { + postbuf << "--YaHTTP-12ca543\r\nContent-Disposition: form-data; name=\"" << Utility::encodeURL(i->first, false) << "\"; charset=UTF-8\r\nContent-Length: " << i->second.size() << "\r\n\r\n" + << Utility::encodeURL(i->second, false) << "\r\n"; + } + postbuf << "--"; + body = postbuf.str(); + } + + postbuf.str(""); + postbuf << body.length(); + // set method and change headers + method = "POST"; + if (!this->is_multipart) + headers["content-length"] = postbuf.str(); + }; //>(std::istream& is, Request &resp); + }; + + /*! Asynchronous HTTP document loader */ + template + class AsyncLoader { + public: + T* target; //target = target_; + hasBody = false; + buffer = ""; + this->target->initialize(); + }; // 1 && + (!hasBody || + (bodybuf.str().size() <= maxbody && + bodybuf.str().size() >= minbody) + ) + ); + }; //headers.find("content-type"); + if (cpos != target->headers.end() && Utility::iequals(cpos->second, "application/x-www-form-urlencoded", 32)) { + target->postvars = Utility::parseUrlParameters(bodybuf.str()); + } + target->body = bodybuf.str(); + } + bodybuf.str(""); + this->target = NULL; + }; // { + }; + + /*! Asynchronous HTTP request loader */ + class AsyncRequestLoader: public AsyncLoader { + }; + +}; diff --git a/ext/yahttp/yahttp/router.cpp b/ext/yahttp/yahttp/router.cpp new file mode 100644 index 0000000..a92be62 --- /dev/null +++ b/ext/yahttp/yahttp/router.cpp @@ -0,0 +1,161 @@ +/* @file + * @brief Concrete implementation of Router + */ +#include "yahttp.hpp" +#include "router.hpp" + +namespace YaHTTP { + typedef funcptr::tuple TDelim; + + // router is defined here. + YaHTTP::Router Router::router; + + void Router::map(const std::string& method, const std::string& url, THandlerFunction handler, const std::string& name) { + std::string method2 = method; + bool isopen=false; + // add into vector + for(std::string::const_iterator i = url.begin(); i != url.end(); i++) { + if (*i == '<' && isopen) throw Error("Invalid URL mask, cannot have < after <"); + if (*i == '<') isopen = true; + if (*i == '>' && !isopen) throw Error("Invalid URL mask, cannot have > without < first"); + if (*i == '>') isopen = false; + } + std::transform(method2.begin(), method2.end(), method2.begin(), ::toupper); + routes.push_back(funcptr::make_tuple(method2, url, handler, name)); + }; + + bool Router::route(Request *req, THandlerFunction& handler) { + std::map params; + int pos1,pos2; + bool matched = false; + std::string rname; + + // iterate routes + for(TRouteList::iterator i = routes.begin(); !matched && i != routes.end(); i++) { + int k1,k2,k3; + std::string pname; + std::string method, url; + funcptr::tie(method, url, handler, rname) = *i; + + if (method.empty() == false && req->method != method) continue; // no match on method + // see if we can't match the url + params.clear(); + // simple matcher func + for(k1=0, k2=0; k1 < static_cast(url.size()) && k2 < static_cast(req->url.path.size()); ) { + if (url[k1] == '<') { + pos1 = k2; + k3 = k1+1; + // start of parameter + while(k1 < static_cast(url.size()) && url[k1] != '>') k1++; + pname = std::string(url.begin()+k3, url.begin()+k1); + // then we also look it on the url + if (pname[0]=='*') { + pname = pname.substr(1); + // this matches whatever comes after it, basically end of string + pos2 = req->url.path.size(); + matched = true; + if (pname != "") + params[pname] = funcptr::tie(pos1,pos2); + k1 = url.size(); + k2 = req->url.path.size(); + break; + } else { + // match until url[k1] + while(k2 < static_cast(req->url.path.size()) && req->url.path[k2] != url[k1+1]) k2++; + pos2 = k2; + params[pname] = funcptr::tie(pos1,pos2); + } + k2--; + } + else if (url[k1] != req->url.path[k2]) { + break; + } + + k1++; k2++; + } + + // ensure. + if (url[k1] != req->url.path[k2]) + matched = false; + else + matched = true; + } + + if (!matched) { return false; } // no route + req->parameters.clear(); + + for(std::map::iterator i = params.begin(); i != params.end(); i++) { + int p1,p2; + funcptr::tie(p1,p2) = i->second; + std::string value(req->url.path.begin() + p1, req->url.path.begin() + p2); + value = Utility::decodeURL(value); + req->parameters[i->first] = value; + } + + req->routeName = rname; + + return true; + }; + + void Router::printRoutes(std::ostream &os) { + for(TRouteList::iterator i = routes.begin(); i != routes.end(); i++) { +#ifdef HAVE_CXX11 + std::streamsize ss = os.width(); + std::ios::fmtflags ff = os.setf(std::ios::left); + os.width(10); + os << std::get<0>(*i); + os.width(50); + os << std::get<1>(*i); + os.width(ss); + os.setf(ff); + os << " " << std::get<3>(*i); + os << std::endl; +#else + os << i->get<0>() << " " << i->get<1>() << " " << i->get<3>() << std::endl; +#endif + } + }; + + std::pair Router::urlFor(const std::string &name, const strstr_map_t& arguments) { + std::ostringstream path; + std::string mask,method,result; + int k1,k2,k3; + + bool found = false; + for(TRouteList::iterator i = routes.begin(); !found && i != routes.end(); i++) { +#ifdef HAVE_CXX11 + if (std::get<3>(*i) == name) { mask = std::get<1>(*i); method = std::get<0>(*i); found = true; } +#else + if (i->get<3>() == name) { mask = i->get<1>(); method = i->get<0>(); found = true; } +#endif + } + + if (!found) + throw Error("Route not found"); + + for(k1=0,k3=0;k1(mask.size());k1++) { + if (mask[k1] == '<') { + std::string pname; + strstr_map_t::const_iterator pptr; + k2=k1; + while(k1(mask.size()) && mask[k1]!='>') k1++; + path << mask.substr(k3,k2-k3); + if (mask[k2+1] == '*') + pname = std::string(mask.begin() + k2 + 2, mask.begin() + k1); + else + pname = std::string(mask.begin() + k2 + 1, mask.begin() + k1); + if ((pptr = arguments.find(pname)) != arguments.end()) + path << Utility::encodeURL(pptr->second); + k3 = k1+1; + } + else if (mask[k1] == '*') { + // ready + k3++; + continue; + } + } + path << mask.substr(k3); + result = path.str(); + return std::make_pair(method, result); + } +}; diff --git a/ext/yahttp/yahttp/router.hpp b/ext/yahttp/yahttp/router.hpp new file mode 100644 index 0000000..a0dbd13 --- /dev/null +++ b/ext/yahttp/yahttp/router.hpp @@ -0,0 +1,72 @@ +#pragma once +/* @file + * @brief Defines router class and support structures + */ +#ifdef HAVE_CXX11 +#include +#include +#define HAVE_CPP_FUNC_PTR +#define IGNORE std::ignore +namespace funcptr = std; +#else +#ifdef HAVE_BOOST +#include +#include +#define IGNORE boost::tuples::ignore +namespace funcptr = boost; +#define HAVE_CPP_FUNC_PTR +#else +#warning "You need to configure with boost or have C++11 capable compiler for router" +#endif +#endif + +#ifdef HAVE_CPP_FUNC_PTR +#include +#include + +namespace YaHTTP { + typedef funcptr::function THandlerFunction; //!< Handler function pointer + typedef funcptr::tuple TRoute; //!< Route tuple (method, urlmask, handler, name) + typedef std::vector TRouteList; //!< List of routes in order of evaluation + + /*! Implements simple router. + +This class implements a router for masked urls. The URL mask syntax is as of follows + +/<masked>/url<number>/<hi>.<format> + +You can use <*param> to denote that everything will be matched and consumed into the parameter, including slash (/). Use <*> to denote that URL +is consumed but not stored. Note that only path is matched, scheme, host and url parameters are ignored. + */ + class Router { + private: + Router() {}; + static Router router; // urlFor(const std::string &name, const strstr_map_t& arguments); //url.path + static void PrintRoutes(std::ostream &os) { router.printRoutes(os); }; // URLFor(const std::string &name, const strstr_map_t& arguments) { return router.urlFor(name,arguments); }; // +#include + +#include "utility.hpp" + +#ifndef YAHTTP_MAX_URL_LENGTH +#define YAHTTP_MAX_URL_LENGTH 2048 +#endif + +namespace YaHTTP { + /*! URL parser and container */ + class URL { + private: + bool parseSchema(const std::string& url, size_t &pos) { + size_t pos1; + if (pos >= url.size()) return false; // no data + if ( (pos1 = url.find_first_of(":",pos)) == std::string::npos ) return false; // schema is mandatory + protocol = url.substr(pos, pos1-pos); + if (protocol == "http") port = 80; + if (protocol == "https") port = 443; + pos = pos1+1; // after : + if (url.compare(pos, 2, "//") == 0) { + pathless = false; // if this is true we put rest into parameters + pos += 2; + } + return true; + }; //= url.size()) return true; // no data + if ( (pos1 = url.find_first_of("/", pos)) == std::string::npos ) { + host = url.substr(pos); + path = "/"; + pos = url.size(); + } else { + host = url.substr(pos, pos1-pos); + pos = pos1; + } + if ( (pos1 = host.find_first_of(":")) != std::string::npos ) { + std::istringstream tmp(host.substr(pos1+1)); + tmp >> port; + host = host.substr(0, pos1); + } + return true; + }; //= url.size()) return true; // no data + + if ( (pos1 = url.find_first_of("@",pos)) == std::string::npos ) return true; // no userinfo + pos2 = url.find_first_of(":",pos); + + if (pos2 != std::string::npos) { // comes with password + username = url.substr(pos, pos2 - pos); + password = url.substr(pos2+1, pos1 - pos2 - 1); + password = Utility::decodeURL(password); + } else { + username = url.substr(pos, pos1 - pos); + } + pos = pos1+1; + username = Utility::decodeURL(username); + return true; + }; //= url.size()) return true; // no data + if (url[pos] != '/') return false; // not an url + if ( (pos1 = url.find_first_of("?", pos)) == std::string::npos ) { + path = url.substr(pos); + pos = url.size(); + } else { + path = url.substr(pos, pos1-pos); + pos = pos1; + } + return true; + }; //= url.size()) return true; // no data + if (url[pos] == '#') return true; // anchor starts here + if (url[pos] != '?') return false; // not a parameter + if ( (pos1 = url.find_first_of("#", pos)) == std::string::npos ) { + parameters = url.substr(pos+1);; + pos = url.size(); + } else { + parameters = url.substr(pos+1, pos1-pos-1); + pos = pos1; + } + if (parameters.size()>0 && *(parameters.end()-1) == '&') parameters.resize(parameters.size()-1); + return true; + }; //= url.size()) return true; // no data + if (url[pos] != '#') return false; // not anchor + anchor = url.substr(pos+1); + return true; + }; // 0) + oss << ":" << port; + + oss << path; + if (parameters.empty() == false) { + if (!pathless) + oss << "?"; + oss << parameters; + } + if (anchor.empty() == false) + oss << "#" << anchor; + return oss.str(); + }; // YAHTTP_MAX_URL_LENGTH) return false; + size_t pos = 0; + if (*(url.begin()) != '/') { // full url? + if (parseSchema(url, pos) == false) return false; + if (pathless) { + parameters = url.substr(pos); + return true; + } + if (parseUserPass(url, pos) == false) return false; + if (parseHost(url, pos) == false) return false; + } + if (parsePath(url, pos) == false) return false; + if (parseParameters(url, pos) == false) return false; + return parseAnchor(url, pos); + }; // strstr_map_t; //utc_offset = ((t2-t)/10)*10; // removes any possible differences. +#endif + }; //utc_offset = 0; +#endif + }; //tm_year + 1900; + month = tm->tm_mon + 1; + day = tm->tm_mday; + hours = tm->tm_hour; + minutes = tm->tm_min; + seconds = tm->tm_sec; + wday = tm->tm_wday; +#ifdef HAVE_TM_GMTOFF + utc_offset = tm->tm_gmtoff; +#endif + isSet = true; + }; // 6) throw std::range_error("Invalid date"); + if (month < 1 || month > 12) throw std::range_error("Invalid date"); + if (year < 0) throw std::range_error("Invalid date"); + if (hours < 0 || hours > 23 || + minutes < 0 || minutes > 59 || + seconds < 0 || seconds > 60) throw std::range_error("Invalid date"); + }; //=0) oss << "+"; + else oss << "-"; + int tmp_off = ( utc_offset < 0 ? utc_offset*-1 : utc_offset ); + oss << std::setfill('0') << std::setw(2) << (tmp_off/3600); + oss << std::setfill('0') << std::setw(2) << (tmp_off%3600)/60; + + return oss.str(); + }; //utc_offset = 0; + } else { + std::cout << cookie_date << std::endl; + throw YaHTTP::ParseError("Unparseable date (did not match pattern cookie)"); + } + }; // result.length()) return result; // end of result + code = result.substr(pos1+1, 2); + a = std::tolower(code[0]); b = std::tolower(code[1]); + + if ((( '0' > a || a > '9') && ('a' > a || a > 'f')) || + (( '0' > b || b > '9') && ('a' > b || b > 'f'))) { + pos2 = pos1+3; + continue; + } + + if ('0' <= a && a <= '9') a = a - '0'; + if ('a' <= a && a <= 'f') a = a - 'a' + 0x0a; + if ('0' <= b && b <= '9') b = b - '0'; + if ('a' <= b && b <= 'f') b = b - 'a' + 0x0a; + + c = (a<<4)+b; + result = result.replace(pos1,3,1,c); + pos2=pos1; + } + return result; + }; //(*iter)); + result = result.replace(pos, 1, "%", 1).insert(pos+1, repl, 2); + iter = result.begin() + pos + 2; + } + } + return result; + }; //(&component[0]); + std::size_t s = component.size() * sizeof((*component.begin())); + std::vector vec(p, p+s); + + std::ostringstream result; + std::string skip = "+-.,&;_#%[]?/@(){}="; + for(std::vector::iterator iter = vec.begin(); iter != vec.end(); iter++) { + if (!YaHTTP::isalnum((char)*iter) && (!asUrl || skip.find((char)*iter) == std::string::npos)) { + // bit more complex replace + result << "%" << std::hex << std::setw(2) << std::setfill('0') << static_cast(*iter); + } else result << (char)*iter; + } + return result.str(); + }; // nextpos) { + delim = nextpos; + } + std::string key; + std::string value; + if (delim == std::string::npos) { + key = parameters.substr(pos); + } else { + key = parameters.substr(pos, delim-pos); + if (nextpos == std::string::npos) { + value = parameters.substr(delim+1); + } else { + value = parameters.substr(delim+1, nextpos-delim-1); + } + } + if (key.empty()) { + // no parameters at all + break; + } + key = decodeURL(key); + value = decodeURL(value); + parameter_map[key] = value; + if (nextpos == std::string::npos) { + // no more parameters left + break; + } + + pos = nextpos+1; + } + return parameter_map; + }; // Content-Type + }; +}; diff --git a/ext/yahttp/yahttp/yahttp-config.h b/ext/yahttp/yahttp/yahttp-config.h new file mode 100644 index 0000000..1ac2545 --- /dev/null +++ b/ext/yahttp/yahttp/yahttp-config.h @@ -0,0 +1 @@ +#include "config.h" diff --git a/ext/yahttp/yahttp/yahttp.hpp b/ext/yahttp/yahttp/yahttp.hpp new file mode 100644 index 0000000..d60be7a --- /dev/null +++ b/ext/yahttp/yahttp/yahttp.hpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "yahttp-config.h" +#include "exception.hpp" +#include "url.hpp" +#include "utility.hpp" +#include "url.hpp" +#include "cookie.hpp" +#include "reqresp.hpp" + +/*! \mainpage Yet Another HTTP Library Documentation +\section sec_quick_start Quick start example + +@code +#include + +int main(void) { + std::ifstream ifs("request.txt"); + YaHTTP::Request req; + ifs >> req; + + std::cout << req.method " " << req.url.path << std::endl; + return 0; +} +@endcode +\author Aki Tuomi +*/ diff --git a/m4/ac_pthread_set_name.m4 b/m4/ac_pthread_set_name.m4 new file mode 100644 index 0000000..4b2cb23 --- /dev/null +++ b/m4/ac_pthread_set_name.m4 @@ -0,0 +1,71 @@ +# PTHREAD_SET_NAME(); +# Check which variant (if any) of pthread_set_name_np we have. +# ----------------------------------------------------------------------------- +AC_DEFUN([PTHREAD_SET_NAME], +[ + stored_LIBS="$LIBS" + LIBS="-lpthread" + # pthread setname (4 non-portable variants...) + AC_CHECK_HEADERS([pthread_np.h], [], [], [#include ]) + define(pthread_np_preamble,[ + #include + #if HAVE_PTHREAD_NP_H + # include + #endif + ]) + # 2-arg setname (e.g. Linux/glibc, QNX, IBM) + AC_MSG_CHECKING([for 2-arg pthread_setname_np]) + AC_LINK_IFELSE([AC_LANG_PROGRAM(pthread_np_preamble, [ + pthread_setname_np(pthread_self(), "foo") + ])], [ + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_2, 1, [2-arg pthread_setname_np]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + # 2-arg set_name (e.g. FreeBSD, OpenBSD) + AC_MSG_CHECKING([for 2-arg pthread_set_name_np]) + AC_LINK_IFELSE([AC_LANG_PROGRAM(pthread_np_preamble, [ + return pthread_set_name_np(pthread_self(), "foo"); + ])], [ + AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP_2, 1, [2-arg pthread_set_name_np]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + # 2-arg void set_name (e.g. FreeBSD, OpenBSD) + AC_MSG_CHECKING([for 2-arg void pthread_set_name_np]) + AC_LINK_IFELSE([AC_LANG_PROGRAM(pthread_np_preamble, [ + pthread_set_name_np(pthread_self(), "foo"); + ])], [ + AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP_2_VOID, 1, [2-arg void pthread_set_name_np]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + # 1-arg setname (e.g. Darwin) + AC_MSG_CHECKING([for 1-arg pthread_setname_np]) + AC_LINK_IFELSE([AC_LANG_PROGRAM(pthread_np_preamble, [ + return pthread_setname_np("foo"); + ])], [ + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_1, 1, [1-arg pthread_setname_np]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + + # 3-arg setname (e.g. NetBSD) + AC_MSG_CHECKING([for 3-arg pthread_setname_np]) + AC_LINK_IFELSE([AC_LANG_PROGRAM(pthread_np_preamble, [ + return pthread_setname_np(pthread_self(), "foo", NULL); + ])], [ + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_3, 1, [3-arg pthread_setname_np]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + ]) + ]) + ]) + ]) + LIBS=$stored_LIBS +]) diff --git a/m4/ax_arg_default_enable_disable.m4 b/m4/ax_arg_default_enable_disable.m4 new file mode 100644 index 0000000..66d99ab --- /dev/null +++ b/m4/ax_arg_default_enable_disable.m4 @@ -0,0 +1,21 @@ +AC_DEFUN([AX_ARG_DEFAULT_ENABLE], [ +AC_ARG_ENABLE([$1], AS_HELP_STRING([--disable-$1], [$2 (default is ENABLED$3)])) +AX_PARSE_VALUE([$1], [y]) +]) + +AC_DEFUN([AX_ARG_DEFAULT_DISABLE], [ +AC_ARG_ENABLE([$1], AS_HELP_STRING([--enable-$1], [$2 (default is DISABLED$3)])) +AX_PARSE_VALUE([$1], [n]) +]) + +dnl This function should not be called outside of this file +AC_DEFUN([AX_PARSE_VALUE], [ +AS_IF([test "x$enable_$1" = "xno"], [ + ax_cv_$1="n" +], [test "x$enable_$1" = "xyes"], [ + ax_cv_$1="y" +], [test -z $ax_cv_$1], [ + ax_cv_$1="$2" +]) +$1=$ax_cv_$1 +AC_SUBST($1)]) diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000..a9a8f58 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,165 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# The first argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The second argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline C++11 support is required and that the macro +# should error out if no mode with that support is found. If specified +# 'optional', then configuration proceeds regardless, after defining +# HAVE_CXX11 if and only if a supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + struct Base { + virtual void f() {} + }; + struct Child : public Base { + virtual void f() override {} + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + auto l = [](){}; + // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] + struct use_l { use_l() { l(); } }; + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this + namespace test_template_alias_sfinae { + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { + func(0); + } + } +]]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], + [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], + [$2], [optional], [ax_cxx_compile_cxx11_required=false], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + AC_MSG_NOTICE([No compiler with C++11 support was found]) + else + HAVE_CXX11=1 + AC_DEFINE(HAVE_CXX11,1, + [define if the compiler supports basic C++11 syntax]) + fi + + AC_SUBST(HAVE_CXX11) + fi +]) diff --git a/m4/boost.m4 b/m4/boost.m4 new file mode 100644 index 0000000..c2cee53 --- /dev/null +++ b/m4/boost.m4 @@ -0,0 +1,1776 @@ +# boost.m4: Locate Boost headers and libraries for autoconf-based projects. +# Copyright (C) 2007-2011, 2014 Benoit Sigoure +# +# This program 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 of the License, or +# (at your option) any later version. +# +# Additional permission under section 7 of the GNU General Public +# License, version 3 ("GPLv3"): +# +# If you convey this file as part of a work that contains a +# configuration script generated by Autoconf, you may do so under +# terms of your choice. +# +# This program 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 this program. If not, see . + +m4_define([_BOOST_SERIAL], [m4_translit([ +# serial 30 +], [# +], [])]) + +# Original sources can be found at http://github.com/tsuna/boost.m4 +# You can fetch the latest version of the script by doing: +# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 + +# ------ # +# README # +# ------ # + +# This file provides several macros to use the various Boost libraries. +# The first macro is BOOST_REQUIRE. It will simply check if it's possible to +# find the Boost headers of a given (optional) minimum version and it will +# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to +# your configure so that users can specify non standard locations. +# If the user's environment contains BOOST_ROOT and --with-boost was not +# specified, --with-boost=$BOOST_ROOT is implicitly used. +# For more README and documentation, go to http://github.com/tsuna/boost.m4 +# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, +# simply read the README, it will show you what to do step by step. + +m4_pattern_forbid([^_?(BOOST|Boost)_]) + + +# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------- +# Same as AC_EGREP_CPP, but leave the result in conftest.i. +# +# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded +# in double-quotes, so escape your double quotes. +# +# It could be useful to turn this into a macro which extracts the +# value of any macro. +m4_define([_BOOST_SED_CPP], +[AC_LANG_PUSH([C++])dnl +AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_SED])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) +AS_IF([dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +dnl Beware of Windows end-of-lines, for instance if we are running +dnl some Windows programs under Wine. In that case, boost/version.hpp +dnl is certainly using "\r\n", but the regular Unix shell will only +dnl strip `\n' with backquotes, not the `\r'. This results in +dnl boost_cv_lib_version='1_37\r' for instance, which breaks +dnl everything else. +dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK +dnl +dnl Beware that GCC 5, when expanding macros, may embed # line directives +dnl a within single line: +dnl +dnl # 1 "conftest.cc" +dnl # 1 "" +dnl # 1 "" +dnl # 1 "conftest.cc" +dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 +dnl # 2 "conftest.cc" 2 +dnl boost-lib-version = +dnl # 2 "conftest.cc" 3 +dnl "1_56" +dnl +dnl So get rid of the # and empty lines, and glue the remaining ones together. +(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + grep -v '#' | + grep -v '^[[[:space:]]]*$' | + tr -d '\r' | + tr -s '\n' ' ' | + $SED -n -e "$1" >conftest.i 2>&1], + [$3], + [$4]) +rm -rf conftest* +AC_LANG_POP([C++])dnl +])# _BOOST_SED_CPP + + + +# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------- +# Look for Boost. If version is given, it must either be a literal of the form +# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a +# variable "$var". +# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with +# the required version, it does not check for any of the Boost libraries. +# On # success, defines HAVE_BOOST. On failure, calls the optional +# ACTION-IF-NOT-FOUND action if one was supplied. +# Otherwise aborts with an error message. +AC_DEFUN_ONCE([BOOST_REQUIRE], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_GREP])dnl +echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD +boost_save_IFS=$IFS +boost_version_req=$1 +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` +boost_version_req_string=$[1].$[2].$[3] +AC_ARG_WITH([boost], + [AS_HELP_STRING([--with-boost=DIR], + [prefix of Boost $1 @<:@guess@:>@])])dnl +AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) + with_boost=$BOOST_ROOT + else + AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) + fi +fi +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], + ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl +boost_save_CPPFLAGS=$CPPFLAGS + AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], + [boost_cv_inc_path], + [boost_cv_inc_path=no +AC_LANG_PUSH([C++])dnl +m4_pattern_allow([^BOOST_VERSION$])dnl + AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif +]])]) + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # + # Any ${boost_dir}/boost-x_xx directories are searched in reverse version + # order followed by ${boost_dir}. The final '.' is a sentinel for + # searching $boost_dir" itself. Entries are whitespace separated. + # + # I didn't indent this loop on purpose (to avoid over-indented code) + boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ + && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ + && echo .` + for boost_inc in $boost_layout_system_search_list + do + if test x"$boost_inc" != x.; then + boost_inc="$boost_dir/$boost_inc" + else + boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list + fi + if test x"$boost_inc" != x; then + # We are going to check whether the version of Boost installed + # in $boost_inc is usable by running a compilation that + # #includes it. But if we pass a -I/some/path in which Boost + # is not installed, the compiler will just skip this -I and + # use other locations (either from CPPFLAGS, or from its list + # of system include directories). As a result we would use + # header installed on the machine instead of the /some/path + # specified by the user. So in that precise case (trying + # $boost_inc), make sure the version.hpp exists. + # + # Use test -e as there can be symlinks. + test -e "$boost_inc/boost/version.hpp" || continue + CPPFLAGS="$CPPFLAGS -I$boost_inc" + fi + AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +AC_LANG_POP([C++])dnl + ]) + case $boost_cv_inc_path in #( + no) + boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" + m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], + [AC_MSG_NOTICE([$boost_errmsg])]) + $2 + ;;#( + yes) + BOOST_CPPFLAGS= + ;;#( + *) + AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl + ;; + esac + if test x"$boost_cv_inc_path" != xno; then + AC_DEFINE([HAVE_BOOST], [1], + [Defined if the requested minimum BOOST version is satisfied]) + AC_CACHE_CHECK([for Boost's header version], + [boost_cv_lib_version], + [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl + _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], + [#include +boost-lib-version = BOOST_LIB_VERSION], + [boost_cv_lib_version=`cat conftest.i`])]) + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[[!0-9]]*) + AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) + ;; + esac +fi +CPPFLAGS=$boost_save_CPPFLAGS +])# BOOST_REQUIRE + + +# BOOST_STATIC() +# -------------- +# Add the "--enable-static-boost" configure argument. If this argument is given +# on the command line, static versions of the libraries will be looked up. +AC_DEFUN([BOOST_STATIC], + [AC_ARG_ENABLE([static-boost], + [AS_HELP_STRING([--enable-static-boost], + [Prefer the static boost libraries over the shared ones [no]])], + [enable_static_boost=yes], + [enable_static_boost=no])])# BOOST_STATIC + + +# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) +# -------------------------------------------------------------------------- +# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for +# some parts of the Boost library which are only made of headers and don't +# require linking (such as Boost.Foreach). +# +# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be +# found in the first place, in which case by default a notice is issued to the +# user. Presumably if we haven't died already it's because it's OK to not have +# Boost, which is why only a notice is issued instead of a hard error. +# +# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in +# case of success # (where HEADER-NAME is written LIKE_THIS, e.g., +# HAVE_BOOST_FOREACH_HPP). +AC_DEFUN([BOOST_FIND_HEADER], +[AC_REQUIRE([BOOST_REQUIRE])dnl +if test x"$boost_cv_inc_path" = xno; then + m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) +else +AC_LANG_PUSH([C++])dnl +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CHECK_HEADER([$1], + [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], + [Define to 1 if you have <$1>])])], + [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) +CPPFLAGS=$boost_save_CPPFLAGS +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_HEADER + + +# BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], +# [ERROR_ON_UNUSABLE]) +# -------------------------------------------------------------- +# Look for the Boost library COMPONENT-NAME (e.g., `thread', for +# libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., +# "thread_win32 thread"). Check that HEADER-NAME works and check that +# libboost_LIB-NAME can link with the code CXX-TEST. The optional +# argument CXX-PROLOGUE can be used to include some C++ code before +# the `main' function. The CXX-POST-INCLUDE-PROLOGUE can be used to +# include some code before the `main' function, but after the +# `#include '. +# +# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). +# +# Boost libraries typically come compiled with several flavors (with different +# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one +# or more of the following letters: sgdpn (in that order). s = static +# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, +# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' +# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can +# start with `mt-' to indicate that there is a preference for multi-thread +# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp +# ... If you want to make sure you have a specific version of Boost +# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. +# +# ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their +# configure to fail +AC_DEFUN([BOOST_FIND_LIBS], +[AC_REQUIRE([BOOST_REQUIRE])dnl +AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl +AC_REQUIRE([BOOST_STATIC])dnl +AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl +if test x"$boost_cv_inc_path" = xno; then + AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) +else +dnl The else branch is huge and wasn't indented on purpose. +AC_LANG_PUSH([C++])dnl +AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl +AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl +AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl +AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl +AS_IF([test x"$8" = "xno"], [not_found_header='true']) +BOOST_FIND_HEADER([$4], [$not_found_header]) +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], + [_BOOST_FIND_LIBS($@)]) +case $Boost_lib in #( + (yes) _AC_MSG_LOG_CONFTEST + AC_DEFINE(AS_TR_CPP([HAVE_BOOST_$1]), [1], [Defined if the Boost $1 library is available])dnl + AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl + AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl + AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl + AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl + ;; + (no) _AC_MSG_LOG_CONFTEST + AS_IF([test x"$8" != "xno"], [ + AC_MSG_ERROR([cannot find flags to link with the Boost $1 library (libboost-$1)]) + ]) + ;; +esac +CPPFLAGS=$boost_save_CPPFLAGS +AS_VAR_POPDEF([Boost_lib])dnl +AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl +AS_VAR_POPDEF([Boost_lib_LDPATH])dnl +AS_VAR_POPDEF([Boost_lib_LIBS])dnl +AC_LANG_POP([C++])dnl +fi +]) + + +# BOOST_FIND_LIB([LIB-NAME], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], +# [ERROR_ON_UNUSABLE]) +# -------------------------------------------------------------- +# Backward compatibility wrapper for BOOST_FIND_LIBS. +# ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their +# configure to fail +AC_DEFUN([BOOST_FIND_LIB], +[BOOST_FIND_LIBS([$1], $@)]) + + +# _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], +# [ERROR_ON_UNUSABLE]) +# -------------------------------------------------------------- +# Real implementation of BOOST_FIND_LIBS: rely on these local macros: +# Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS +# +# The algorithm is as follows: first look for a given library name +# according to the user's PREFERRED-RT-OPT. For each library name, we +# prefer to use the ones that carry the tag (toolset name). Each +# library is searched through the various standard paths were Boost is +# usually installed. If we can't find the standard variants, we try +# to enforce -mt (for instance on MacOSX, libboost_thread.dylib +# doesn't exist but there's -obviously- libboost_thread-mt.dylib). +# +# ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their +# configure to fail +AC_DEFUN([_BOOST_FIND_LIBS], +[Boost_lib=no + case "$3" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=$3;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) + boost_save_ac_objext=$ac_objext + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([$7 +#include <$4> +$6], [$5])]) +dnl Optimization hacks: compiling C++ is slow, especially with Boost. What +dnl we're trying to do here is guess the right combination of link flags +dnl (LIBS / LDFLAGS) to use a given library. This can take several +dnl iterations before it succeeds and is thus *very* slow. So what we do +dnl instead is that we compile the code first (and thus get an object file, +dnl typically conftest.o). Then we try various combinations of link flags +dnl until we succeed to link conftest.o in an executable. The problem is +dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always +dnl remove all the temporary files including conftest.o. So the trick here +dnl is to temporarily change the value of ac_objext so that conftest.o is +dnl preserved accross tests. This is obviously fragile and I will burn in +dnl hell for not respecting Autoconf's documented interfaces, but in the +dnl mean time, it optimizes the macro by a factor of 5 to 30. +dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left +dnl empty because the test file is generated only once above (before we +dnl start the for loops). + AC_COMPILE_IFELSE([], + [ac_objext=do_not_rm_me_plz], + [AS_IF([test x"$8" != x"no"], [ + AC_MSG_ERROR([cannot compile a test that uses Boost $1]) + ]) + ]) + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in $2; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_full_suffix in \ + $boost_last_suffix \ + x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_rtopt_$boost_ver_ \ + x$boost_tag_$boost_mt_$boost_ver_ \ + x$boost_tag_$boost_ver_ + do + boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` + boost_lib="boost_$boost_lib_$boost_real_suffix" + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$Boost_lib_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + Boost_lib_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$Boost_lib_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" +dnl First argument of AC_LINK_IFELSE left empty because the test file is +dnl generated only once above (before we start the for loops). + _BOOST_AC_LINK_IFELSE([], + [Boost_lib=yes], [Boost_lib=no]) + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$Boost_lib" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + AC_CACHE_VAL([boost_cv_rpath_link_ldflag], + [case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$Boost_lib_LIBS $boost_save_LIBS" + _BOOST_AC_LINK_IFELSE([], + [boost_rpath_link_ldflag_found=yes + break], + [boost_rpath_link_ldflag_found=no]) + done + ;; + esac + AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], + [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + ]) + test x"$boost_ldpath" != x && + Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + Boost_lib_LDPATH="$boost_ldpath" + boost_last_suffix="$boost_full_suffix" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext +]) + + + +# --------------------------------------- # +# Checks for the various Boost libraries. # +# --------------------------------------- # + +# List of boost libraries: http://www.boost.org/libs/libraries.htm +# The page http://beta.boost.org/doc/libs is useful: it gives the first release +# version of each library (among other things). + +# BOOST_DEFUN(LIBRARY, CODE) +# -------------------------- +# Define BOOST_ as a macro that runs CODE. +# +# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. +m4_define([BOOST_DEFUN], +[m4_indir([AC_DEFUN], + m4_toupper([BOOST_$1]), +[m4_pushdef([BOOST_Library], [$1])dnl +$2 +m4_popdef([BOOST_Library])dnl +]) +]) + + +# BOOST_ANY() +# ------------ +# Look for Boost.Any +BOOST_DEFUN([Any], +[BOOST_FIND_HEADER([boost/any.hpp])]) + + +# BOOST_ARRAY() +# ------------- +# Look for Boost.Array +BOOST_DEFUN([Array], +[BOOST_FIND_HEADER([boost/array.hpp])]) + + +# BOOST_ASIO() +# ------------ +# Look for Boost.Asio (new in Boost 1.35). +BOOST_DEFUN([Asio], +[AC_REQUIRE([BOOST_SYSTEM])dnl +BOOST_FIND_HEADER([boost/asio.hpp])]) + +# BOOST_BIMAP() +# ------------ +# Look for Boost.Bimap +BOOST_DEFUN([Bimap], +[BOOST_FIND_HEADER([boost/bimap.hpp])]) + + +# BOOST_ASSIGN() +# ------------- +# Look for Boost.Assign +BOOST_DEFUN([Assign], +[BOOST_FIND_HEADER([boost/assign.hpp])]) + + +# BOOST_ATOMIC([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------- +# Look for Boost.Atomic. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Atomic], +[BOOST_FIND_LIB([atomic], [$1], + [boost/atomic.hpp], + [boost::atomic a;], + [ ], + [#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif], [$2]) +])# BOOST_ATOMIC + + +# BOOST_BIND() +# ------------ +# Look for Boost.Bind. +BOOST_DEFUN([Bind], +[BOOST_FIND_HEADER([boost/bind.hpp])]) + + +# BOOST_CAST() +# ------------ +# Look for Boost.Cast +BOOST_DEFUN([Cast], +[BOOST_FIND_HEADER([boost/cast.hpp])]) + + +# BOOST_CHRONO([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# -------------- +# Look for Boost.Chrono. +BOOST_DEFUN([Chrono], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then + BOOST_SYSTEM([$1], [$2]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([chrono], [$1], + [boost/chrono.hpp], + [boost::chrono::thread_clock d;], [], [], [$2]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_CHRONO + + +# BOOST_CONTEXT([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------- +# Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +# +# * This library was introduced in Boost 1.51.0 +# * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0 +# * A dependency on boost_thread appears in 1.57.0 +# * The implementation details were moved to boost::context::detail in 1.61.0 +BOOST_DEFUN([Context], +[boost_context_save_LIBS=$LIBS + boost_context_save_LDFLAGS=$LDFLAGS +if test $boost_major_version -ge 157; then + BOOST_THREAD([$1], [$2]) + m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_THREAD_LIBS" + LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS" +fi + +if test $boost_major_version -ge 161; then +BOOST_FIND_LIB([context], [$1], + [boost/context/continuation.hpp], [[ +namespace ctx=boost::context; +int a; +ctx::continuation source=ctx::callcc( + [&a](ctx::continuation && sink){ + a=0; + int b=1; + for(;;){ + sink=sink.resume(); + int next=a+b; + a=b; + b=next; + } + return std::move(sink); + }); +for (int j=0;j<10;++j) { + source=source.resume(); +} +return a == 34; +]], [], [], [$2]) + +else + +BOOST_FIND_LIB([context], [$1], + [boost/context/fcontext.hpp],[[ + +// creates a stack +void * stack_pointer = new void*[4096]; +std::size_t const size = sizeof(void*[4096]); + +#if BOOST_VERSION <= 105100 +ctx::make_fcontext(&fc, f); +return ctx::jump_fcontext(&fcm, &fc, 3) == 6; + +#else + +fc = ctx::make_fcontext(stack_pointer, size, f); +return ctx::jump_fcontext(&fcm, fc, 3) == 6; + +#endif + + +]],[dnl + +#include +#if BOOST_VERSION <= 105100 + +namespace ctx = boost::ctx; + +static ctx::fcontext_t fcm, fc; + +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, &fcm, i * 2); +} + +#elif BOOST_VERSION <= 105500 + +namespace ctx = boost::context; + +// context +static ctx::fcontext_t fcm, *fc; + +// context-function +static void f(intptr_t i) { + ctx::jump_fcontext(fc, &fcm, i * 2); +} + +#else + +namespace ctx = boost::context; + +// context +static ctx::fcontext_t fcm, fc; + +// context-function +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, fcm, i * 2); +} +#endif +], [], [], [$2]) + +fi + +LIBS=$boost_context_save_LIBS +LDFLAGS=$boost_context_save_LDFLAGS +])# BOOST_CONTEXT + + +# BOOST_CONVERSION() +# ------------------ +# Look for Boost.Conversion (cast / lexical_cast) +BOOST_DEFUN([Conversion], +[BOOST_FIND_HEADER([boost/cast.hpp]) +BOOST_FIND_HEADER([boost/lexical_cast.hpp]) +])# BOOST_CONVERSION + + +# BOOST_COROUTINE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------- +# Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.53.0 +BOOST_DEFUN([Coroutine], +[ +boost_coroutine_save_LIBS=$LIBS +boost_coroutine_save_LDFLAGS=$LDFLAGS +# Link-time dependency from coroutine to context +BOOST_CONTEXT([$1], [$2]) +# Starting from Boost 1.55 a dependency on Boost.System is added +if test $boost_major_version -ge 155; then + BOOST_SYSTEM([$1], [$2]) +fi +m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) +LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" + +# in 1.53 coroutine was a header only library +if test $boost_major_version -eq 153; then + AS_IF([test x"$2" = "xno"], [not_found_header='true']) + BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp], [$not_found_header]) +else + BOOST_FIND_LIB([coroutine], [$1], + [boost/coroutine/coroutine.hpp], + [ + #include + #if BOOST_VERSION <= 105500 + boost::coroutines::coroutine coro; coro.get(); + #else + boost::coroutines::asymmetric_coroutine::pull_type coro; coro.get(); + #endif + ], [], [], [$2]) +fi +# Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 +# coroutine doesn't use context from its headers but from its library. +if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then + BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" + BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" +fi +if test $enable_static_boost = yes && test $boost_major_version -ge 155; then + BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" + BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" +fi +LIBS=$boost_coroutine_save_LIBS +LDFLAGS=$boost_coroutine_save_LDFLAGS +])# BOOST_COROUTINE + + +# BOOST_CRC() +# ----------- +# Look for Boost.CRC +BOOST_DEFUN([CRC], +[BOOST_FIND_HEADER([boost/crc.hpp]) +])# BOOST_CRC + + +# BOOST_DATE_TIME([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------- +# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Date_Time], +[BOOST_FIND_LIB([date_time], [$1], + [boost/date_time/posix_time/posix_time.hpp], + [boost::posix_time::ptime t;], [], [], [$2]) +])# BOOST_DATE_TIME + + +# BOOST_EXCEPTION() +# ------------ +# Look for Boost.Exception +BOOST_DEFUN([Exception], +[BOOST_FIND_HEADER([boost/exception/all.hpp])]) + + +# BOOST_FILESYSTEM([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------------ +# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +# Do not check for boost/filesystem.hpp because this file was introduced in +# 1.34. +BOOST_DEFUN([Filesystem], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then + BOOST_SYSTEM([$1], [$2]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([filesystem], [$1], + [boost/filesystem/path.hpp], [boost::filesystem::path p;], + [], [], [$2]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_FILESYSTEM + + +# BOOST_FLYWEIGHT() +# ----------------- +# Look for Boost.Flyweight. +BOOST_DEFUN([Flyweight], +[dnl There's a hidden dependency on pthreads. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +BOOST_FIND_HEADER([boost/flyweight.hpp]) +AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) +]) + + +# BOOST_FOREACH() +# --------------- +# Look for Boost.Foreach. +BOOST_DEFUN([Foreach], +[BOOST_FIND_HEADER([boost/foreach.hpp])]) + + +# BOOST_FORMAT() +# -------------- +# Look for Boost.Format. +# Note: we can't check for boost/format/format_fwd.hpp because the header isn't +# standalone. It can't be compiled because it triggers the following error: +# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' +# does not name a type +BOOST_DEFUN([Format], +[BOOST_FIND_HEADER([boost/format.hpp])]) + + +# BOOST_FUNCTION() +# ---------------- +# Look for Boost.Function +BOOST_DEFUN([Function], +[BOOST_FIND_HEADER([boost/function.hpp])]) + + +# BOOST_FUSION() +# ----------------- +# Look for Boost.Fusion +BOOST_DEFUN([Fusion], +[BOOST_FIND_HEADER([boost/fusion/sequence.hpp])]) + + +# BOOST_GEOMETRY() +# ---------------- +# Look for Boost.Geometry (new since 1.47.0). +BOOST_DEFUN([Geometry], +[BOOST_FIND_HEADER([boost/geometry.hpp]) +])# BOOST_GEOMETRY + + +# BOOST_GRAPH([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------- +# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Graph], +[boost_graph_save_LIBS=$LIBS +boost_graph_save_LDFLAGS=$LDFLAGS +# Link-time dependency from graph to regex was added as of 1.40.0. +if test $boost_major_version -ge 140; then + BOOST_REGEX([$1], [$2]) + m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_REGEX_LIBS" + LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS" +fi +BOOST_FIND_LIB([graph], [$1], + [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;], + [], [], [$2]) +LIBS=$boost_graph_save_LIBS +LDFLAGS=$boost_graph_save_LDFLAGS +])# BOOST_GRAPH + + +# BOOST_HASH() +# ------------ +# Look for Boost.Functional/Hash +BOOST_DEFUN([Hash], +[BOOST_FIND_HEADER([boost/functional/hash.hpp])]) + + +# BOOST_IOSTREAMS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------- +# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([IOStreams], +[BOOST_FIND_LIB([iostreams], [$1], + [boost/iostreams/device/file_descriptor.hpp], + [boost::iostreams::file_descriptor fd; fd.close();], + [], [], [$2]) +])# BOOST_IOSTREAMS + + +# BOOST_ITERATOR() +# ------------ +# Look for Boost.Iterator +BOOST_DEFUN([Iterator], +[BOOST_FIND_HEADER([boost/iterator/iterator_adaptor.hpp])]) + + +# BOOST_LAMBDA() +# -------------- +# Look for Boost.Lambda +BOOST_DEFUN([Lambda], +[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) + + +# BOOST_LOCALE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# -------------- +# Look for Boost.Locale +BOOST_DEFUN([Locale], +[ +boost_locale_save_LIBS=$LIBS +boost_locale_save_LDFLAGS=$LDFLAGS +# require SYSTEM for boost-1.50.0 and up +if test $boost_major_version -ge 150; then + BOOST_SYSTEM([$1], [$2]) + m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_SYSTEM_LIBS" + LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +fi # end of the Boost.System check. +BOOST_FIND_LIB([locale], [$1], + [boost/locale.hpp], + [[boost::locale::generator gen; std::locale::global(gen(""));]], [], [], [$2]) +LIBS=$boost_locale_save_LIBS +LDFLAGS=$boost_locale_save_LDFLAGS +])# BOOST_LOCALE + +# BOOST_LOG([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------- +# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log], +[boost_log_save_LIBS=$LIBS +boost_log_save_LDFLAGS=$LDFLAGS +BOOST_SYSTEM([$1], [$2]) +BOOST_FILESYSTEM([$1], [$2]) +BOOST_DATE_TIME([$1], [$2]) +m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([log], [$1], + [boost/log/core/core.hpp], + [boost::log::attribute a; a.get_value();], [], [], [$2]) +LIBS=$boost_log_save_LIBS +LDFLAGS=$boost_log_save_LDFLAGS +])# BOOST_LOG + + +# BOOST_LOG_SETUP([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------- +# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log_Setup], +[boost_log_setup_save_LIBS=$LIBS +boost_log_setup_save_LDFLAGS=$LDFLAGS +BOOST_LOG([$1]) +m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_LOG_LIBS" +LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS" +BOOST_FIND_LIB([log_setup], [$1], + [boost/log/utility/setup/from_settings.hpp], + [boost::log::basic_settings bs; bs.empty();], [], [], [$2]) +LIBS=$boost_log_setup_save_LIBS +LDFLAGS=$boost_log_setup_save_LDFLAGS +])# BOOST_LOG_SETUP + + +# BOOST_MATH() +# ------------ +# Look for Boost.Math +# TODO: This library isn't header-only but it comes in multiple different +# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, +# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, +# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the +# right thing anyway. +BOOST_DEFUN([Math], +[BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) + + +# BOOST_MPI([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------- +# Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is +# set, otherwise tries CXX +# +BOOST_DEFUN([MPI], +[boost_save_CXX=${CXX} +boost_save_CXXCPP=${CXXCPP} +if test x"${MPICXX}" != x; then + CXX=${MPICXX} + CXXCPP="${MPICXX} -E" +fi +BOOST_FIND_LIB([mpi], [$1], + [boost/mpi.hpp], + [int argc = 0; + char **argv = 0; + boost::mpi::environment env(argc,argv);], + [], [], [$2]) +CXX=${boost_save_CXX} +CXXCPP=${boost_save_CXXCPP} +])# BOOST_MPI + + +# BOOST_MPL() +# ------------------ +# Look for Boost.MPL +BOOST_DEFUN([MPL], +[BOOST_FIND_HEADER([boost/mpl/for_each.hpp])]) + + +# BOOST_MULTIARRAY() +# ------------------ +# Look for Boost.MultiArray +BOOST_DEFUN([MultiArray], +[BOOST_FIND_HEADER([boost/multi_array.hpp])]) + + +# BOOST_MULTIINDEXCCONTAINER() +# ------------------ +# Look for Boost.MultiIndexContainer +BOOST_DEFUN([MultiIndexContainer], +[BOOST_FIND_HEADER([boost/multi_index_container.hpp])]) + + +# BOOST_NUMERIC_UBLAS() +# -------------------------- +# Look for Boost.NumericUblas (Basic Linear Algebra) +BOOST_DEFUN([Numeric_Ublas], +[BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) +])# BOOST_NUMERIC_UBLAS + + +# BOOST_NUMERIC_CONVERSION() +# -------------------------- +# Look for Boost.NumericConversion (policy-based numeric conversion) +BOOST_DEFUN([Numeric_Conversion], +[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) +])# BOOST_NUMERIC_CONVERSION + + +# BOOST_OPTIONAL() +# ---------------- +# Look for Boost.Optional +BOOST_DEFUN([Optional], +[BOOST_FIND_HEADER([boost/optional.hpp])]) + + +# BOOST_PREPROCESSOR() +# -------------------- +# Look for Boost.Preprocessor +BOOST_DEFUN([Preprocessor], +[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) + + +# BOOST_PROPERTY_TREE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------------- +# Look for Boost.Property_Tree. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Property_Tree], +[BOOST_FIND_LIB([property_tree], [$1], + [boost/property_tree/ptree.hpp], + [boost::property_tree::ptree pt; boost::property_tree::read_xml d("test", pt);], + [], [], [$2]) +])# BOOST_PROPERTY_TREE + + +# BOOST_RANDOM() +# -------------------- +# Look for Boost.Random +BOOST_DEFUN([Random], +[BOOST_FIND_HEADER([boost/random/random_number_generator.hpp])]) + + +# BOOST_RANGE() +# -------------------- +# Look for Boost.Range +BOOST_DEFUN([Range], +[BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) + +# BOOST_UNORDERED() +# ----------------- +# Look for Boost.Unordered +BOOST_DEFUN([Unordered], +[BOOST_FIND_HEADER([boost/unordered_map.hpp])]) + + +# BOOST_UUID() +# ------------ +# Look for Boost.Uuid +BOOST_DEFUN([Uuid], +[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) + + +# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ----------------------------------------- +# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Program_Options], +[BOOST_FIND_LIB([program_options], [$1], + [boost/program_options.hpp], + [boost::program_options::options_description d("test");], + [], [], [$2]) +])# BOOST_PROGRAM_OPTIONS + + + +# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) +# ------------------------------------ +# Save VARIABLE, and define it via `python-config --FLAG`. +# Substitute BOOST_PYTHON_VARIABLE. +m4_define([_BOOST_PYTHON_CONFIG], +[AC_SUBST([BOOST_PYTHON_$1], + [`python-config --$2 2>/dev/null`])dnl +boost_python_save_$1=$$1 +$1="$$1 $BOOST_PYTHON_$1"]) + + +# BOOST_PYTHON([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# -------------------------------- +# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Python], +[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) +_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) +_BOOST_PYTHON_CONFIG([LIBS], [libs]) +m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl +BOOST_FIND_LIBS([python], [python python3], [$1], + [boost/python.hpp], + [], [BOOST_PYTHON_MODULE(empty) {}], [], [$2]) +CPPFLAGS=$boost_python_save_CPPFLAGS +LDFLAGS=$boost_python_save_LDFLAGS +LIBS=$boost_python_save_LIBS +])# BOOST_PYTHON + + +# BOOST_REF() +# ----------- +# Look for Boost.Ref +BOOST_DEFUN([Ref], +[BOOST_FIND_HEADER([boost/ref.hpp])]) + + +# BOOST_REGEX([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------- +# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Regex], +[BOOST_FIND_LIB([regex], [$1], + [boost/regex.hpp], + [boost::regex exp("*"); boost::regex_match("foo", exp);], + [], [], [$2]) +])# BOOST_REGEX + + +# BOOST_SCOPE_EXIT() +# ------------ +# Look for Boost.ScopeExit. +BOOST_DEFUN([SCOPE_EXIT], +[BOOST_FIND_HEADER([boost/scope_exit.hpp])]) + + +# BOOST_SERIALIZATION([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# --------------------------------------- +# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Serialization], +[BOOST_FIND_LIB([serialization], [$1], + [boost/archive/text_oarchive.hpp], + [std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o);], + [], [], [$2]) +])# BOOST_SERIALIZATION + + +# BOOST_SIGNALS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# --------------------------------- +# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Signals], +[BOOST_FIND_LIB([signals], [$1], + [boost/signal.hpp], + [boost::signal s;], + [], [], [$2]) +])# BOOST_SIGNALS + + +# BOOST_SIGNALS2() +# ---------------- +# Look for Boost.Signals2 (new since 1.39.0). +BOOST_DEFUN([Signals2], +[BOOST_FIND_HEADER([boost/signals2.hpp]) +])# BOOST_SIGNALS2 + + +# BOOST_SMART_PTR() +# ----------------- +# Look for Boost.SmartPtr +BOOST_DEFUN([Smart_Ptr], +[BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) +BOOST_FIND_HEADER([boost/shared_ptr.hpp]) +]) + + +# BOOST_STATICASSERT() +# -------------------- +# Look for Boost.StaticAssert +BOOST_DEFUN([StaticAssert], +[BOOST_FIND_HEADER([boost/static_assert.hpp])]) + + +# BOOST_STRING_ALGO() +# ------------------- +# Look for Boost.StringAlgo +BOOST_DEFUN([String_Algo], +[BOOST_FIND_HEADER([boost/algorithm/string.hpp]) +]) + + +# BOOST_SYSTEM([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# -------------------------------- +# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.35.0. +BOOST_DEFUN([System], +[BOOST_FIND_LIB([system], [$1], + [boost/system/error_code.hpp], + [boost::system::error_code e; e.clear();], [], [], [$2]) +])# BOOST_SYSTEM + + +# BOOST_TEST([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------ +# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Test], +[m4_pattern_allow([^BOOST_CHECK$])dnl +BOOST_FIND_LIB([unit_test_framework], [$1], + [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], + [using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; }], [], [$2]) +])# BOOST_TEST + + +# BOOST_THREAD([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# --------------------------------- +# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Thread], +[dnl Having the pthread flag is required at least on GCC3 where +dnl boost/thread.hpp would complain if we try to compile without +dnl -pthread on GNU/Linux. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +boost_thread_save_LIBS=$LIBS +boost_thread_save_LDFLAGS=$LDFLAGS +boost_thread_save_CPPFLAGS=$CPPFLAGS +# Link-time dependency from thread to system was added as of 1.49.0. +if test $boost_major_version -ge 149; then +BOOST_SYSTEM([$1], [$2]) +fi # end of the Boost.System check. +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" + +# When compiling for the Windows platform, the threads library is named +# differently. This suffix doesn't exist in new versions of Boost, or +# possibly new versions of GCC on mingw I am assuming it's Boost's change for +# now and I am setting version to 1.48, for lack of knowledge as to when this +# change occurred. +if test $boost_major_version -lt 148; then + case $host_os in + (*mingw*) boost_thread_lib_ext=_win32;; + esac +fi +BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], + [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;], [], [], [$2]) + +case $host_os in + (*mingw*) boost_thread_w32_socket_link=-lws2_32;; +esac + +BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" +BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" +BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" +LIBS=$boost_thread_save_LIBS +LDFLAGS=$boost_thread_save_LDFLAGS +CPPFLAGS=$boost_thread_save_CPPFLAGS +])# BOOST_THREAD + +AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) + + +# BOOST_TOKENIZER() +# ----------------- +# Look for Boost.Tokenizer +BOOST_DEFUN([Tokenizer], +[BOOST_FIND_HEADER([boost/tokenizer.hpp])]) + + +# BOOST_TRIBOOL() +# --------------- +# Look for Boost.Tribool +BOOST_DEFUN([Tribool], +[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) +BOOST_FIND_HEADER([boost/logic/tribool.hpp]) +]) + + +# BOOST_TUPLE() +# ------------- +# Look for Boost.Tuple +BOOST_DEFUN([Tuple], +[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) + + +# BOOST_TYPETRAITS() +# -------------------- +# Look for Boost.TypeTraits +BOOST_DEFUN([TypeTraits], +[BOOST_FIND_HEADER([boost/type_traits.hpp])]) + + +# BOOST_UTILITY() +# --------------- +# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, +# etc.) +BOOST_DEFUN([Utility], +[BOOST_FIND_HEADER([boost/utility.hpp])]) + + +# BOOST_VARIANT() +# --------------- +# Look for Boost.Variant. +BOOST_DEFUN([Variant], +[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) +BOOST_FIND_HEADER([boost/variant.hpp])]) + + +# BOOST_POINTER_CONTAINER() +# ------------------------ +# Look for Boost.PointerContainer +BOOST_DEFUN([Pointer_Container], +[BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) +])# BOOST_POINTER_CONTAINER + + +# BOOST_WAVE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) +# ------------------------------ +# NOTE: If you intend to use Wave/Spirit with thread support, make sure you +# call BOOST_THREAD first. +# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Wave], +[AC_REQUIRE([BOOST_FILESYSTEM])dnl +AC_REQUIRE([BOOST_DATE_TIME])dnl +boost_wave_save_LIBS=$LIBS +boost_wave_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ +$BOOST_THREAD_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ +$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" +BOOST_FIND_LIB([wave], [$1], + [boost/wave.hpp], + [boost::wave::token_id id; get_token_name(id);], [], [], [$2]) +LIBS=$boost_wave_save_LIBS +LDFLAGS=$boost_wave_save_LDFLAGS +])# BOOST_WAVE + + +# BOOST_XPRESSIVE() +# ----------------- +# Look for Boost.Xpressive (new since 1.36.0). +BOOST_DEFUN([Xpressive], +[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) + + +# ----------------- # +# Internal helpers. # +# ----------------- # + + +# _BOOST_PTHREAD_FLAG() +# --------------------- +# Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag +# which must be used in CPPFLAGS and LIBS. +# +# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, +# boost/thread.hpp will trigger a #error if -pthread isn't used: +# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support +# is not turned on. Please set the correct command line options for +# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" +# +# Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html +AC_DEFUN([_BOOST_PTHREAD_FLAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_LANG_PUSH([C++])dnl +AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], +[ boost_cv_pthread_flag= + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + case $host_os in #( + *solaris*) + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( + *) + boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ + -pthreads -mthreads -lpthread --thread-safe -mt";; + esac + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) + for boost_pthread_flag in '' $boost_pthread_flags; do + boost_pthread_ok=false +dnl Re-use the test file already generated. + boost_pthreads__save_LIBS=$LIBS + LIBS="$LIBS $boost_pthread_flag" + AC_LINK_IFELSE([], + [if grep ".*$boost_pthread_flag" conftest.err; then + echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD + else + boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag + fi]) + LIBS=$boost_pthreads__save_LIBS + $boost_pthread_ok && break + done +]) +AC_LANG_POP([C++])dnl +])# _BOOST_PTHREAD_FLAG + + +# _BOOST_gcc_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_gcc_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl + +# _BOOST_mingw_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_mingw_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl + + +# _BOOST_FIND_COMPILER_TAG() +# -------------------------- +# Internal. When Boost is installed without --layout=system, each library +# filename will hold a suffix that encodes the compiler used during the +# build. The Boost build system seems to call this a `tag'. +AC_DEFUN([_BOOST_FIND_COMPILER_TAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], + [boost_cv_lib_tag], +[boost_cv_lib_tag=unknown +if test x$boost_cv_inc_path != xno; then + AC_LANG_PUSH([C++])dnl + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + for i in \ + "defined __clang__ && __clang_major__ == 8 && __clang_minor__ == 0 @ clang80" \ + "defined __clang__ && __clang_major__ == 7 && __clang_minor__ == 0 @ clang70" \ + "defined __clang__ && __clang_major__ == 6 && __clang_minor__ == 0 @ clang60" \ + "defined __clang__ && __clang_major__ == 5 && __clang_minor__ == 0 @ clang50" \ + "defined __clang__ && __clang_major__ == 4 && __clang_minor__ == 0 @ clang40" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 9 @ clang39" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 @ clang38" \ + "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 7 @ clang37" \ + _BOOST_mingw_test(9, 1) \ + _BOOST_gcc_test(9, 1) \ + _BOOST_mingw_test(9, 0) \ + _BOOST_gcc_test(9, 0) \ + _BOOST_mingw_test(8, 3) \ + _BOOST_gcc_test(8, 3) \ + _BOOST_mingw_test(8, 2) \ + _BOOST_gcc_test(8, 2) \ + _BOOST_mingw_test(8, 1) \ + _BOOST_gcc_test(8, 1) \ + _BOOST_mingw_test(8, 0) \ + _BOOST_gcc_test(8, 0) \ + _BOOST_mingw_test(7, 3) \ + _BOOST_gcc_test(7, 3) \ + _BOOST_mingw_test(7, 2) \ + _BOOST_gcc_test(7, 2) \ + _BOOST_mingw_test(7, 1) \ + _BOOST_gcc_test(7, 1) \ + _BOOST_mingw_test(7, 0) \ + _BOOST_gcc_test(7, 0) \ + _BOOST_mingw_test(6, 4) \ + _BOOST_gcc_test(6, 4) \ + _BOOST_mingw_test(6, 3) \ + _BOOST_gcc_test(6, 3) \ + _BOOST_mingw_test(6, 2) \ + _BOOST_gcc_test(6, 2) \ + _BOOST_mingw_test(6, 1) \ + _BOOST_gcc_test(6, 1) \ + _BOOST_mingw_test(6, 0) \ + _BOOST_gcc_test(6, 0) \ + _BOOST_mingw_test(5, 5) \ + _BOOST_gcc_test(5, 5) \ + _BOOST_mingw_test(5, 4) \ + _BOOST_gcc_test(5, 4) \ + _BOOST_mingw_test(5, 3) \ + _BOOST_gcc_test(5, 3) \ + _BOOST_mingw_test(5, 2) \ + _BOOST_gcc_test(5, 2) \ + _BOOST_mingw_test(5, 1) \ + _BOOST_gcc_test(5, 1) \ + _BOOST_mingw_test(5, 0) \ + _BOOST_gcc_test(5, 0) \ + _BOOST_mingw_test(4, 10) \ + _BOOST_gcc_test(4, 10) \ + _BOOST_mingw_test(4, 9) \ + _BOOST_gcc_test(4, 9) \ + _BOOST_mingw_test(4, 8) \ + _BOOST_gcc_test(4, 8) \ + _BOOST_mingw_test(4, 7) \ + _BOOST_gcc_test(4, 7) \ + _BOOST_mingw_test(4, 6) \ + _BOOST_gcc_test(4, 6) \ + _BOOST_mingw_test(4, 5) \ + _BOOST_gcc_test(4, 5) \ + _BOOST_mingw_test(4, 4) \ + _BOOST_gcc_test(4, 4) \ + _BOOST_mingw_test(4, 3) \ + _BOOST_gcc_test(4, 3) \ + _BOOST_mingw_test(4, 2) \ + _BOOST_gcc_test(4, 2) \ + _BOOST_mingw_test(4, 1) \ + _BOOST_gcc_test(4, 1) \ + _BOOST_mingw_test(4, 0) \ + _BOOST_gcc_test(4, 0) \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + _BOOST_gcc_test(3, 4) \ + _BOOST_gcc_test(3, 3) \ + "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ + "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ + _BOOST_gcc_test(3, 2) \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + _BOOST_gcc_test(3, 1) \ + _BOOST_gcc_test(3, 0) \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined __unix__) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + _BOOST_gcc_test(2, 95) \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` + boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif +]])], [boost_cv_lib_tag=$boost_tag; break], []) + done +AC_LANG_POP([C++])dnl + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + boost_tag_x= + case $host_os in #( + darwin*) + if test $boost_major_version -ge 136; then + # The `x' added in r46793 of Boost. + boost_tag_x=x + fi;; + esac + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" + ;; #( + unknown) + AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) + boost_cv_lib_tag= + ;; + esac +fi])dnl end of AC_CACHE_CHECK +])# _BOOST_FIND_COMPILER_TAG + + +# _BOOST_GUESS_WHETHER_TO_USE_MT() +# -------------------------------- +# Compile a small test to try to guess whether we should favor MT (Multi +# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. +AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], +[# Check whether we do better use `mt' even though we weren't ask to. +AC_LANG_PUSH([C++])dnl +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif +]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) +AC_LANG_POP([C++])dnl +]) + +# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# ------------------------------------------------------------------- +# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, +# will break when Autoconf changes its internals. Requires that you manually +# rm -f conftest.$ac_objext in between to really different tests, otherwise +# you will try to link a conftest.o left behind by a previous test. +# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this +# macro). +# +# Don't use "break" in the actions, as it would short-circuit some code +# this macro runs after the actions. +m4_define([_BOOST_AC_LINK_IFELSE], +[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl +rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) +AS_IF([_AC_DO_STDERR($ac_link) && { + test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext +dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. + }], + [$2], + [if $boost_use_source; then + _AC_MSG_LOG_CONFTEST + fi + $3]) +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) +dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), +dnl as it would interfere with the next link command. +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl +])# _BOOST_AC_LINK_IFELSE + +# Local Variables: +# mode: autoconf +# End: diff --git a/m4/libcurl.m4 b/m4/libcurl.m4 new file mode 100644 index 0000000..53d694d --- /dev/null +++ b/m4/libcurl.m4 @@ -0,0 +1,272 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 2006, David Shaw +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], +# [ACTION-IF-YES], [ACTION-IF-NO]) +# ---------------------------------------------------------- +# David Shaw May-09-2006 +# +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. +# +# This macro #defines HAVE_LIBCURL if a working libcurl setup is +# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary +# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are +# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy +# where yyy are the various protocols supported by libcurl. Both xxx +# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of +# the macro for the complete list of possible defines. Shell +# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also +# defined to 'yes' for those features and protocols that were found. +# Note that xxx and yyy keep the same capitalization as in the +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only guess what protocols are available, +# or use curl_version_info to figure it out at runtime. + +AC_DEFUN([LIBCURL_CHECK_CONFIG], +[ + AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) + AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) + AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) + AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) + AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) + AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) + AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) + AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) + + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) + AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) + AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) + AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3]) + AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP]) + AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) + + AC_ARG_WITH(libcurl, + AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), + [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) + + if test "$_libcurl_with" != "no" ; then + + AC_PROG_AWK + + _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" + + _libcurl_try_link=yes + + if test -d "$_libcurl_with" ; then + LIBCURL_CPPFLAGS="-I$withval/include" + _libcurl_ldflags="-L$withval/lib" + AC_PATH_PROG([_libcurl_config],[curl-config],[], + ["$withval/bin"]) + else + AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) + fi + + if test x$_libcurl_config != "x" ; then + AC_CACHE_CHECK([for the version of libcurl], + [libcurl_cv_lib_curl_version], + [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) + + _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` + _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` + + if test $_libcurl_wanted -gt 0 ; then + AC_CACHE_CHECK([for libcurl >= version $2], + [libcurl_cv_lib_version_ok], + [ + if test $_libcurl_version -ge $_libcurl_wanted ; then + libcurl_cv_lib_version_ok=yes + else + libcurl_cv_lib_version_ok=no + fi + ]) + fi + + if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then + if test x"$LIBCURL_CPPFLAGS" = "x" ; then + LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` + fi + if test x"$LIBCURL" = "x" ; then + LIBCURL=`$_libcurl_config --libs` + + # This is so silly, but Apple actually has a bug in their + # curl-config script. Fixed in Tiger, but there are still + # lots of Panther installs around. + case "${host}" in + powerpc-apple-darwin7*) + LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` + ;; + esac + fi + + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` + + # Is it modern enough to have --protocols? (7.12.4) + if test $_libcurl_version -ge 461828 ; then + _libcurl_protocols=`$_libcurl_config --protocols` + fi + else + _libcurl_try_link=no + fi + + unset _libcurl_wanted + fi + + if test $_libcurl_try_link = yes ; then + + # we didn't find curl-config, so let's see if the user-supplied + # link line (or failing that, "-lcurl") is enough. + LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} + + AC_CACHE_CHECK([whether libcurl is usable], + [libcurl_cv_lib_curl_usable], + [ + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBCURL $LIBS" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ +/* Try and use a few common options to force a failure if we are + missing symbols or can't link. */ +int x; +curl_easy_setopt(NULL,CURLOPT_URL,NULL); +x=CURL_ERROR_SIZE; +x=CURLOPT_WRITEFUNCTION; +x=CURLOPT_WRITEDATA; +x=CURLOPT_ERRORBUFFER; +x=CURLOPT_STDERR; +x=CURLOPT_VERBOSE; +if (x) {;} +]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + ]) + + if test $libcurl_cv_lib_curl_usable = yes ; then + + # Does curl_free() exist in this version of libcurl? + # If not, fake it with free() + + _libcurl_save_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" + _libcurl_save_libs=$LIBS + LIBS="$LIBS $LIBCURL" + + AC_CHECK_FUNC(curl_free,, + AC_DEFINE(curl_free,free, + [Define curl_free() as free() if our version of curl lacks curl_free.])) + + CPPFLAGS=$_libcurl_save_cppflags + LIBS=$_libcurl_save_libs + unset _libcurl_save_cppflags + unset _libcurl_save_libs + + AC_DEFINE(HAVE_LIBCURL,1, + [Define to 1 if you have a functional curl library.]) + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL) + + for _libcurl_feature in $_libcurl_features ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) + eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes + done + + if test "x$_libcurl_protocols" = "x" ; then + + # We don't have --protocols, so just assume that all + # protocols are available + _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" + + if test x$libcurl_feature_SSL = xyes ; then + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 (0x070b00 == 461568) + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi + fi + + # RTSP, IMAP, POP3 and SMTP were added in + # 7.20.0 (0x071400 == 463872) + if test $_libcurl_version -ge 463872; then + _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" + fi + fi + + for _libcurl_protocol in $_libcurl_protocols ; do + AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) + eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes + done + else + unset LIBCURL + unset LIBCURL_CPPFLAGS + fi + fi + + unset _libcurl_try_link + unset _libcurl_version_parse + unset _libcurl_config + unset _libcurl_feature + unset _libcurl_features + unset _libcurl_protocol + unset _libcurl_protocols + unset _libcurl_version + unset _libcurl_ldflags + fi + + if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then + # This is the IF-NO path + ifelse([$4],,:,[$4]) + else + # This is the IF-YES path + ifelse([$3],,:,[$3]) + fi + + unset _libcurl_with +])dnl diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..a3bc337 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8369 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file 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. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file 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. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file 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. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file 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. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file 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. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/pdns_check_bison.m4 b/m4/pdns_check_bison.m4 new file mode 100644 index 0000000..7f1c83c --- /dev/null +++ b/m4/pdns_check_bison.m4 @@ -0,0 +1,15 @@ +AC_DEFUN([PDNS_CHECK_BISON], [ + AC_REQUIRE([AC_PROG_YACC]) + AC_REQUIRE([AC_PROG_EGREP]) + + AC_CACHE_CHECK([if bison is the parser generator],[pdns_cv_prog_bison],[ + AS_IF([$YACC --version 2>/dev/null | $EGREP -q '^bison '], + [pdns_cv_prog_bison=yes], [pdns_cv_prog_bison=no]) + ]) + + AS_IF([test "x$pdns_cv_prog_bison" = "xno"], [ + AS_IF([test ! -f "${srcdir}/pdns/bindparser.cc"], + [AC_MSG_ERROR([bison is missing and you don't have ${srcdir}/pdns/bindparser.cc. Please install bison])] + )] + ) +]) diff --git a/m4/pdns_check_cdb.m4 b/m4/pdns_check_cdb.m4 new file mode 100644 index 0000000..fdc00e5 --- /dev/null +++ b/m4/pdns_check_cdb.m4 @@ -0,0 +1,14 @@ +AC_DEFUN([PDNS_CHECK_CDB],[ + PKG_CHECK_MODULES([CDB], [libcdb], + [], + [AC_CHECK_HEADERS([cdb.h], + [AC_CHECK_LIB([cdb], [cdb_find], + [CDB_LIBS="-lcdb"], + [AC_MSG_ERROR([Could not find libcdb])] + )], + [AC_MSG_ERROR([Could not find cdb.h])] + )] + ) + AC_SUBST(CDB_LIBS) + AC_SUBST(CDB_CFLAGS) +]) diff --git a/m4/pdns_check_clock_gettime.m4 b/m4/pdns_check_clock_gettime.m4 new file mode 100644 index 0000000..b2d3207 --- /dev/null +++ b/m4/pdns_check_clock_gettime.m4 @@ -0,0 +1,6 @@ +AC_DEFUN([PDNS_CHECK_CLOCK_GETTIME],[ + OLD_LIBS="$LIBS"; LIBS="" + AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE(HAVE_CLOCK_GETTIME, [1], [Define to 1 if you have clock_gettime])]) + AC_SUBST([RT_LIBS],[$LIBS]) + LIBS="$OLD_LIBS" +]) diff --git a/m4/pdns_check_curl_program.m4 b/m4/pdns_check_curl_program.m4 new file mode 100644 index 0000000..d6abe1c --- /dev/null +++ b/m4/pdns_check_curl_program.m4 @@ -0,0 +1,7 @@ +AC_DEFUN([PDNS_CHECK_CURL_PROGRAM], [ + AC_CHECK_PROG([CURL], [curl], [curl], [no]) + + AS_IF([test "x$CURL" = "xno"], [ + AC_MSG_ERROR([curl program is missing, required for running remotebackend unit tests]) + ]) +]) diff --git a/m4/pdns_check_flex.m4 b/m4/pdns_check_flex.m4 new file mode 100644 index 0000000..e6f46d4 --- /dev/null +++ b/m4/pdns_check_flex.m4 @@ -0,0 +1,15 @@ +AC_DEFUN([PDNS_CHECK_FLEX], [ + AC_REQUIRE([AC_PROG_LEX]) + AC_REQUIRE([AC_PROG_EGREP]) + + AC_CACHE_CHECK([if the lexer is flex],[pdns_cv_prog_flex],[ + AS_IF([$LEX --version 2>/dev/null | $EGREP -q '^flex '], + [pdns_cv_prog_flex=yes], [pdns_cv_prog_flex=no]) + ]) + + AS_IF([test "x$pdns_cv_prog_flex" = "xno"], [ + AS_IF([test ! -f "${srcdir}/pdns/bindlexer.c"], + [AC_MSG_ERROR([flex is missing and you don't have ${srcdir}/pdns/bindlexer.c. Please install flex])] + )] + ) +]) diff --git a/m4/pdns_check_ldap.m4 b/m4/pdns_check_ldap.m4 new file mode 100644 index 0000000..ddd1c88 --- /dev/null +++ b/m4/pdns_check_ldap.m4 @@ -0,0 +1,54 @@ +AC_DEFUN([PDNS_CHECK_LDAP],[ + AC_CHECK_HEADERS([ldap.h], + [], + [AC_MSG_ERROR([ldap header (ldap.h) not found])] + ) + + AC_CHECK_HEADERS([lber.h], + [], + [AC_MSG_ERROR([ldap header (lber.h) not found])] + ) + + AC_CHECK_LIB([ldap_r], [ldap_set_option], + [ + AC_DEFINE([HAVE_LIBLDAP_R], [1], [Have -lldap_r]) + LIBLDAP="ldap_r" + LDAP_LIBS="-lldap_r -llber" + ], + [ + AC_CHECK_LIB([ldap], [ldap_set_option], + [ + AC_DEFINE([HAVE_LIBLDAP], 1, [Have -lldap]) + LIBLDAP="ldap" + LDAP_LIBS="-lldap -llber" + ], + [AC_MSG_ERROR([ldap library (libldap) not found])] + ) + ] + ) + + AC_CHECK_LIB([$LIBLDAP], [ldap_initialize], + [AC_DEFINE([HAVE_LDAP_INITIALIZE], 1, [Define to 1 if you have ldap_initialize])] + ) + + AC_CHECK_LIB([$LIBLDAP], [ldap_sasl_bind], + [AC_DEFINE([HAVE_LDAP_SASL_BIND], 1, [Define to 1 if you have ldap_sasl_bind])] + ) + + AC_ARG_VAR([LDAP_LIBS], [linker flags for openldap]) + + AC_CHECK_HEADERS([krb5.h], + [], + [AC_MSG_ERROR([Kerberos header (krb5.h) not found])] + ) + + AC_ARG_VAR([KRB5_LIBS], [linker flag to add Kerberos 5 libraries]) + + AC_CHECK_LIB([krb5], [krb5_init_context], + [ + KRB5_LIBS="-lkrb5" + ] + ) + + AC_CHECK_FUNCS([krb5_get_init_creds_opt_set_default_flags]) +]) diff --git a/m4/pdns_check_libcrypto.m4 b/m4/pdns_check_libcrypto.m4 new file mode 100644 index 0000000..c71c98a --- /dev/null +++ b/m4/pdns_check_libcrypto.m4 @@ -0,0 +1,128 @@ +# SYNOPSIS +# +# PDNS_CHECK_LIBCRYPTO([action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Look for OpenSSL's libcrypto in a number of default spots, or in a +# user-selected spot (via --with-libcrypto). Sets +# +# LIBCRYPTO_INCLUDES to the include directives required +# LIBCRYPTO_LIBS to the -l directives required +# LIBCRYPTO_LDFLAGS to the -L or -R flags required +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# This macro sets LIBCRYPTO_INCLUDES such that source files should use the +# openssl/ directory in include directives: +# +# #include +# +# LICENSE +# +# Taken and modified from AX_CHECK_OPENSSL by: +# Copyright (c) 2009,2010 Zmanda Inc. +# Copyright (c) 2009,2010 Dustin J. Mitchell +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AU_ALIAS([CHECK_LIBCRYPTO], [PDNS_CHECK_LIBCRYPTO]) +AC_DEFUN([PDNS_CHECK_LIBCRYPTO], [ + found=false + AC_ARG_WITH([libcrypto], + [AS_HELP_STRING([--with-libcrypto=DIR], + [root of the OpenSSL directory])], + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([Invalid --with-libcrypto value]) + ;; + *) ssldirs="$withval" + ;; + esac + ], [ + # if pkg-config is installed and openssl has installed a .pc file, + # then use that information and don't search ssldirs + AC_CHECK_TOOL([PKG_CONFIG], [pkg-config]) + if test x"$PKG_CONFIG" != x""; then + LIBCRYPTO_LDFLAGS=`$PKG_CONFIG libcrypto --libs-only-L 2>/dev/null` + if test $? = 0; then + LIBCRYPTO_LIBS=`$PKG_CONFIG libcrypto --libs-only-l 2>/dev/null` + LIBCRYPTO_INCLUDES=`$PKG_CONFIG libcrypto --cflags-only-I 2>/dev/null` + ssldir=`$PKG_CONFIG libcrypto --variable=prefix 2>/dev/null` + found=true + fi + fi + + # no such luck; use some default ssldirs + if ! $found; then + ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" + fi + ] + ) + + + # note that we #include , so the OpenSSL headers have to be in + # an 'openssl' subdirectory + + if ! $found; then + LIBCRYPTO_INCLUDES= + for ssldir in $ssldirs; do + AC_MSG_CHECKING([for openssl/crypto.h in $ssldir]) + if test -f "$ssldir/include/openssl/crypto.h"; then + LIBCRYPTO_INCLUDES="-I$ssldir/include" + LIBCRYPTO_LDFLAGS="-L$ssldir/lib" + LIBCRYPTO_LIBS="-lcrypto" + found=true + AC_MSG_RESULT([yes]) + break + else + AC_MSG_RESULT([no]) + fi + done + + # if the file wasn't found, well, go ahead and try the link anyway -- maybe + # it will just work! + fi + + if $found; then + AC_DEFINE([HAVE_LIBCRYPTO], [1], [Define to 1 if you have OpenSSL libcrypto]) + fi + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([whether compiling and linking against OpenSSL's libcrypto works]) + echo "Trying link with LIBCRYPTO_LDFLAGS=$LIBCRYPTO_LDFLAGS;" \ + "LIBCRYPTO_LIBS=$LIBCRYPTO_LIBS; LIBCRYPTO_INCLUDES=$LIBCRYPTO_INCLUDES" >&AS_MESSAGE_LOG_FD + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS $LIBCRYPTO_LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], [ERR_load_CRYPTO_strings()])], + [ + AC_MSG_RESULT([yes]) + AC_CHECK_FUNCS([RAND_bytes RAND_pseudo_bytes]) + $1 + ], [ + AC_MSG_RESULT([no]) + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([LIBCRYPTO_INCLUDES]) + AC_SUBST([LIBCRYPTO_LIBS]) + AC_SUBST([LIBCRYPTO_LDFLAGS]) + AM_CONDITIONAL([HAVE_LIBCRYPTO], [test "x$LIBCRYPTO_LIBS" != "x"]) +]) diff --git a/m4/pdns_check_libcrypto_ecdsa.m4 b/m4/pdns_check_libcrypto_ecdsa.m4 new file mode 100644 index 0000000..8720a63 --- /dev/null +++ b/m4/pdns_check_libcrypto_ecdsa.m4 @@ -0,0 +1,33 @@ +AC_DEFUN([PDNS_CHECK_LIBCRYPTO_ECDSA], [ + AC_REQUIRE([PDNS_CHECK_LIBCRYPTO]) + + # Set the environment correctly for a possibly non-default OpenSSL path that was found by/supplied to PDNS_CHECK_LIBCRYPTO + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + LDFLAGS="$LIBCRYPTO_LDFLAGS $LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + + # Find the headers we need for ECDSA + libcrypto_ecdsa=yes + AC_CHECK_HEADER([$ssldir/include/openssl/ecdsa.h], [ + AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [ : ], [ + libcrypto_ecdsa=no + ], [AC_INCLUDES_DEFAULT +#include <$ssldir/include/openssl/evp.h> + ]) + ], [ + libcrypto_ecdsa=no + ]) + + AS_IF([test "x$libcrypto_ecdsa" = "xyes"], [ + AC_DEFINE([HAVE_LIBCRYPTO_ECDSA], [1], [define to 1 if OpenSSL ecdsa support is available.]) + ]) + + # Restore variables + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" +]) diff --git a/m4/pdns_check_libcrypto_eddsa.m4 b/m4/pdns_check_libcrypto_eddsa.m4 new file mode 100644 index 0000000..3607fcf --- /dev/null +++ b/m4/pdns_check_libcrypto_eddsa.m4 @@ -0,0 +1,36 @@ +AC_DEFUN([PDNS_CHECK_LIBCRYPTO_EDDSA], [ + AC_REQUIRE([PDNS_CHECK_LIBCRYPTO]) + + # Set the environment correctly for a possibly non-default OpenSSL path that was found by/supplied to PDNS_CHECK_LIBCRYPTO + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + + CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS" + LDFLAGS="$LIBCRYPTO_LDFLAGS $LDFLAGS" + LIBS="$LIBCRYPTO_LIBS $LIBS" + + libcrypto_ed25519=no + libcrypto_ed448=no + AC_CHECK_DECLS([NID_ED25519], [ + libcrypto_ed25519=yes + AC_DEFINE([HAVE_LIBCRYPTO_ED25519], [1], [define to 1 if OpenSSL ed25519 support is available.]) + ], [ : ], + [AC_INCLUDES_DEFAULT + #include <$ssldir/include/openssl/evp.h>]) + AC_CHECK_DECLS([NID_ED448], [ + libcrypto_ed448=yes + AC_DEFINE([HAVE_LIBCRYPTO_ED448], [1], [define to 1 if OpenSSL ed448 support is available.]) + ], [ : ], + [AC_INCLUDES_DEFAULT + #include <$ssldir/include/openssl/evp.h>]) + + AS_IF([test "$libcrypto_ed25519" = "yes" -o "$libcrypto_ed448" = "yes"], [ + AC_DEFINE([HAVE_LIBCRYPTO_EDDSA], [1], [define to 1 if OpenSSL EDDSA support is available.]) + ], [ : ]) + + # Restore variables + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" +]) diff --git a/m4/pdns_check_libcurl.m4 b/m4/pdns_check_libcurl.m4 new file mode 100644 index 0000000..43412de --- /dev/null +++ b/m4/pdns_check_libcurl.m4 @@ -0,0 +1,6 @@ +AC_DEFUN([PDNS_CHECK_LIBCURL], [ + AS_IF([test -n "$HAVE_LIBCURL"], [ : ], [ + LIBCURL_CHECK_CONFIG("yes", "7.21.3", [ HAVE_LIBCURL=y ], [ HAVE_LIBCURL=n ]) + ]) + AM_CONDITIONAL([HAVE_LIBCURL], [test "$HAVE_LIBCURL" = "y"]) +]) diff --git a/m4/pdns_check_lmdb.m4 b/m4/pdns_check_lmdb.m4 new file mode 100644 index 0000000..611f668 --- /dev/null +++ b/m4/pdns_check_lmdb.m4 @@ -0,0 +1,46 @@ +dnl invoking this makes lmdb a requirement +AC_DEFUN([PDNS_CHECK_LMDB], [ + AC_MSG_CHECKING([where to find the lmdb library and headers]) + AC_ARG_WITH([lmdb], + AC_HELP_STRING([--with-lmdb], [lmdb library to use @<:@default=auto@:>@]),[ + with_lmdb=$withval + ],[ + with_lmdb=auto + ]) + AC_MSG_RESULT([$with_lmdb]) + + AS_IF([test "$with_lmdb" != "no"], [ + AS_IF([test "x$with_lmdb" = "xyes" -o "x$with_lmdb" = "xauto"], [ + PKG_CHECK_MODULES([LMDB], [lmdb], [ : ], [ + AC_MSG_ERROR([lmdb not found via pkg-config, please install lmdb or set --with-lmdb to your lmdb installation directory]) + ]) + ], [ + save_CPPFLAGS=$CPPFLAGS + save_LIBS=$LIBS + AS_IF([test -d "$with_lmdb/include"], [ + LMDB_CFLAGS="-I$with_lmdb/include" + LMDB_LIBS="-L$with_lmdb/lib" + ],[ + LMDB_CFLAGS="-I$with_lmdb" + LMDB_LIBS="-L$with_lmdb" + ]) + CPPFLAGS="$LMDB_CFLAGS" + LIBS="$LMDB_LIBS" + + AC_SEARCH_LIBS([mdb_env_open], [lmdb], [ + AC_CHECK_HEADERS([lmdb.h], [ + dnl ac_cv_search_mdb_env_open contains '-llmdb' + LMDB_LIBS="$LMDB_LIBS $ac_cv_search_mdb_env_open" + ], [ + AC_MSG_ERROR([lmdb headers not found in $with_lmdb]) + ]) + CPPFLAGS="$save_CPPFLAGS" + LIBS="$save_LIBS" + AC_SUBST([LMDB_CFLAGS]) + AC_SUBST([LMDB_LIBS]) + ]) + ]) + ], [ + AC_MSG_ERROR([--with-lmdb is set to 'no', but lmdb support is required]) + ]) +]) diff --git a/m4/pdns_check_lua_hpp.m4 b/m4/pdns_check_lua_hpp.m4 new file mode 100644 index 0000000..7cc8f5e --- /dev/null +++ b/m4/pdns_check_lua_hpp.m4 @@ -0,0 +1,10 @@ +AC_DEFUN([PDNS_CHECK_LUA_HPP],[ + AC_REQUIRE([PDNS_WITH_LUA]) + AS_IF([test "x$LUAPC" != "x" ], [ + OLD_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LUA_CFLAGS" + AC_CHECK_HEADER([lua.hpp], [ have_lua_hpp=y ]) + CPPFLAGS="$OLD_CPPFLAGS" + ]) + AM_CONDITIONAL([HAVE_LUA_HPP], [ test x"$have_lua_hpp" = "xy" ]) +]) diff --git a/m4/pdns_check_network_libs.m4 b/m4/pdns_check_network_libs.m4 new file mode 100644 index 0000000..d8b020c --- /dev/null +++ b/m4/pdns_check_network_libs.m4 @@ -0,0 +1,7 @@ +AC_DEFUN([PDNS_CHECK_NETWORK_LIBS],[ + AC_SEARCH_LIBS([inet_aton], [resolv]) + AC_SEARCH_LIBS([gethostbyname], [nsl]) + AC_SEARCH_LIBS([socket], [socket]) + AC_SEARCH_LIBS([gethostent], [nsl]) + AC_CHECK_FUNCS([recvmmsg sendmmsg accept4]) +]) diff --git a/m4/pdns_check_opendbx.m4 b/m4/pdns_check_opendbx.m4 new file mode 100644 index 0000000..66327ce --- /dev/null +++ b/m4/pdns_check_opendbx.m4 @@ -0,0 +1,14 @@ +AC_DEFUN([PDNS_CHECK_OPENDBX], [ + PKG_CHECK_MODULES([OPENDBX], [opendbx], [], [ + AC_CHECK_HEADERS([odbx.h], [ + AC_CHECK_LIB([opendbx], [odbx_init], + [OPENDBX_LIBS="-lopendbx"], + [AC_MSG_ERROR([libopendbx not found])] + )], [ + AC_MSG_ERROR([opendbx header (odbx.h) not found]) + ] + ) + ]) + AC_SUBST([OPENDBX_LIBS]) +]) + diff --git a/m4/pdns_check_os.m4 b/m4/pdns_check_os.m4 new file mode 100644 index 0000000..da4bc8f --- /dev/null +++ b/m4/pdns_check_os.m4 @@ -0,0 +1,56 @@ +AC_DEFUN([PDNS_CHECK_OS],[ + THREADFLAGS="" + + case "$host_os" in + solaris2.1*) + LIBS="-lposix4 -lpthread $LIBS" + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + have_solaris="yes" + ;; + solaris2.8 | solaris2.9 ) + AC_DEFINE(NEED_POSIX_TYPEDEF,,[If POSIX typedefs need to be defined]) + AC_DEFINE(NEED_INET_NTOP_PROTO,,[If your OS is so broken that it needs an additional prototype]) + LIBS="-lposix4 -lpthread $LIBS" + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + have_solaris="yes" + ;; + linux*) + THREADFLAGS="-pthread" + have_linux="yes" + ;; + darwin*) + CXXFLAGS="-D__APPLE_USE_RFC_3542 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + freebsd*) + THREADFLAGS="-pthread" + have_freebsd="yes" + ;; + *) + LDFLAGS="-pthread $LDFLAGS" + CXXFLAGS="-pthread $CXXFLAGS" + ;; + esac + + AM_CONDITIONAL([HAVE_FREEBSD], [test "x$have_freebsd" = "xyes"]) + AM_CONDITIONAL([HAVE_LINUX], [test "x$have_linux" = "xyes"]) + AM_CONDITIONAL([HAVE_SOLARIS], [test "x$have_solaris" = "xyes"]) + + AC_MSG_CHECKING([whether -latomic is needed for __atomic builtins]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED);]] + )], + [AC_MSG_RESULT([no])], + [LIBS="$LIBS -latomic" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED);]] + )], + [AC_MSG_RESULT([yes])], + [AC_MSG_FAILURE([libatomic needed, but linking with -latomic failed, cannot continue])] + )] + ) + + AC_SUBST(THREADFLAGS) + AC_SUBST([DYNLINKFLAGS], [-export-dynamic]) +]) diff --git a/m4/pdns_check_ragel.m4 b/m4/pdns_check_ragel.m4 new file mode 100644 index 0000000..f06c7d7 --- /dev/null +++ b/m4/pdns_check_ragel.m4 @@ -0,0 +1,8 @@ +AC_DEFUN([PDNS_CHECK_RAGEL], [ + AC_CHECK_PROG([RAGEL], [ragel], [ragel]) + if test "x$RAGEL" = "x"; then + if test ! -f "${srcdir}/$1"; then + AC_MSG_ERROR([ragel is missing and you don't have ${srcdir}/$1. Install ragel or download sources from $2]) + fi + fi +]) diff --git a/m4/pdns_check_sqlite3.m4 b/m4/pdns_check_sqlite3.m4 new file mode 100644 index 0000000..e2a5e78 --- /dev/null +++ b/m4/pdns_check_sqlite3.m4 @@ -0,0 +1,8 @@ +AC_DEFUN([PDNS_CHECK_SQLITE3], [ + AS_IF([test "x$needsqlite3" = "xyes"], [ + PKG_CHECK_MODULES([SQLITE3], [sqlite3], + [AC_DEFINE([HAVE_SQLITE3], [1], [Define to 1 if you have sqlite3])], + [AC_MSG_ERROR([Could not find libsqlite3])] + ) + ]) +]) diff --git a/m4/pdns_check_virtualenv.m4 b/m4/pdns_check_virtualenv.m4 new file mode 100644 index 0000000..498cff7 --- /dev/null +++ b/m4/pdns_check_virtualenv.m4 @@ -0,0 +1,12 @@ +AC_DEFUN([PDNS_CHECK_VIRTUALENV], [ + AC_CHECK_PROG([VIRTUALENV], [virtualenv], [virtualenv], [no]) + + AS_IF([test "x$VIRTUALENV" = "xno"], [ + AS_IF([test ! -f "$srcdir/pdns_server.1"], + [AC_MSG_WARN([virtualenv is missing, unable to build manpages.])] + ) + ]) + AM_CONDITIONAL([HAVE_VIRTUALENV], [test "x$VIRTUALENV" != "xno"]) + AM_CONDITIONAL([HAVE_MANPAGES], [test -e "$srcdir/docs/pdns_server.1"]) +]) + diff --git a/m4/pdns_d_fortify_source.m4 b/m4/pdns_d_fortify_source.m4 new file mode 100644 index 0000000..68e9be5 --- /dev/null +++ b/m4/pdns_d_fortify_source.m4 @@ -0,0 +1,28 @@ +dnl +dnl Check for support D_FORTIFY_SOURCE +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([AC_CC_D_FORTIFY_SOURCE],[ + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="-Wall -W -Werror $CXXFLAGS" + gl_COMPILER_OPTION_IF([-D_FORTIFY_SOURCE=2], [ + CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" + CXXFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $OLD_CXXFLAGS" + ], [CXXFLAGS="$OLD_CXXFLAGS"], [AC_LANG_PROGRAM([[#include ]],[])]) +]) diff --git a/m4/pdns_enable_backend_unit_tests.m4 b/m4/pdns_enable_backend_unit_tests.m4 new file mode 100644 index 0000000..8d81897 --- /dev/null +++ b/m4/pdns_enable_backend_unit_tests.m4 @@ -0,0 +1,18 @@ +AC_DEFUN([PDNS_ENABLE_BACKEND_UNIT_TESTS], [ + AC_MSG_CHECKING([whether to enable backend unit test building]) + AC_ARG_ENABLE([backend-unit-tests], + AS_HELP_STRING([--enable-backend-unit-tests], + [enable backend unit test building @<:@default=no@:>@]), + [enable_backend_unit_tests=$enableval], + [enable_backend_unit_tests=no] + ) + AC_MSG_RESULT([$enable_backend_unit_tests]) + AM_CONDITIONAL([BACKEND_UNIT_TESTS], [test "x$enable_backend_unit_tests" != "xno"]) + + AS_IF([test "x$enable_backend_unit_tests" != "xno"], [ + BOOST_TEST([mt]) + AS_IF([test "$boost_cv_lib_unit_test_framework" = "no"], [ + AC_MSG_ERROR([Boost Unit Test library not found]) + ]) + ]) +]) diff --git a/m4/pdns_enable_coverage.m4 b/m4/pdns_enable_coverage.m4 new file mode 100644 index 0000000..17846ff --- /dev/null +++ b/m4/pdns_enable_coverage.m4 @@ -0,0 +1,17 @@ +AC_DEFUN([PDNS_ENABLE_COVERAGE], [ + AC_MSG_CHECKING([whether to enable code coverage]) + AC_ARG_ENABLE([coverage], + AS_HELP_STRING([--enable-coverage], + [enable code coverage @<:@default=no@:>@]), + [enable_coverage=$enableval], + [enable_coverage=no] + ) + AC_MSG_RESULT([$enable_coverage]) + AS_IF([test "x$enable_coverage" != "xno"], [ + gl_COMPILER_OPTION_IF([-fprofile-arcs -ftest-coverage], [ + CXXFLAGS="$CXXFLAGS -U_FORTIFY_SOURCE -g -O0 -fprofile-arcs -ftest-coverage" + ], [ + AC_MSG_ERROR([$CXX does not support gathering coverage data]) + ]) + ]) +]) diff --git a/m4/pdns_enable_fuzz_targets.m4 b/m4/pdns_enable_fuzz_targets.m4 new file mode 100644 index 0000000..9973fd9 --- /dev/null +++ b/m4/pdns_enable_fuzz_targets.m4 @@ -0,0 +1,11 @@ +AC_DEFUN([PDNS_ENABLE_FUZZ_TARGETS], [ + AC_MSG_CHECKING([whether to enable fuzzing targets]) + AC_ARG_ENABLE([fuzz_targets], + AS_HELP_STRING([--enable-fuzz-targets], + [enable fuzz targets @<:@default=no@:>@]), + [enable_fuzz_targets=$enableval], + [enable_fuzz_targets=no] + ) + AC_MSG_RESULT([$enable_fuzz_targets]) + AM_CONDITIONAL([FUZZ_TARGETS], [test "x$enable_fuzz_targets" != "xno"]) +]) diff --git a/m4/pdns_enable_gss_tsig.m4 b/m4/pdns_enable_gss_tsig.m4 new file mode 100644 index 0000000..9acd756 --- /dev/null +++ b/m4/pdns_enable_gss_tsig.m4 @@ -0,0 +1,24 @@ +AC_DEFUN([PDNS_ENABLE_GSS_TSIG],[ + AC_MSG_CHECKING([whether to enable experimental GSS-TSIG support]) + AC_ARG_ENABLE([experimental_gss_tsig], + AS_HELP_STRING([--enable-experimental-gss-tsig], + [enable experimental GSS-TSIG support @<:@default=no@:>@] + ), + [enable_experimental_gss_tsig=$enableval], + [enable_experimental_gss_tsig=no] + ) + + AC_MSG_RESULT([$enable_experimental_gss_tsig]) + + AM_CONDITIONAL([GSS_TSIG],[test "x$enable_experimental_gss_tsig" != "xno"]) + AC_SUBST(GSS_TSIG) + AS_IF([test "x$enable_experimental_gss_tsig" != "xno"], + [PKG_CHECK_MODULES([GSS], [krb5 krb5-gssapi gss], + [ + AC_DEFINE([ENABLE_GSS_TSIG], [1], [Define to 1 if you want to enable GSS-TSIG support]) + GSS_TSIG=yes + ], + [AC_MSG_ERROR([Required libraries for GSS-TSIG not found])] + )], + [GSS_TSIG=no]) +]) diff --git a/m4/pdns_enable_ixfrdist.m4 b/m4/pdns_enable_ixfrdist.m4 new file mode 100644 index 0000000..74e211d --- /dev/null +++ b/m4/pdns_enable_ixfrdist.m4 @@ -0,0 +1,18 @@ +AC_DEFUN([PDNS_ENABLE_IXFRDIST], [ + AC_MSG_CHECKING([whether we will be building ixfrdist]) + AC_ARG_ENABLE([ixfrdist], + [AS_HELP_STRING([--enable-ixfrdist], [if we should build and install ixfrdist @<:@default=no@:>@]) + ], [ + enable_ixfrdist=$enableval + ], [ + enable_ixfrdist=no + ]) + + AC_MSG_RESULT([$enable_ixfrdist]) + AM_CONDITIONAL([IXFRDIST], [test "x$enable_ixfrdist" != "xno"]) + AS_IF([test "x$enable_ixfrdist" != "xno"], [ + PKG_CHECK_MODULES([YAML], [yaml-cpp >= 0.5], [ : ], [ + AC_MSG_ERROR([Could not find yaml-cpp >= 0.5, required for ixfrdist]) + ]) + ]) +]) diff --git a/m4/pdns_enable_kiss.m4 b/m4/pdns_enable_kiss.m4 new file mode 100644 index 0000000..1f882d9 --- /dev/null +++ b/m4/pdns_enable_kiss.m4 @@ -0,0 +1,7 @@ +AC_DEFUN([PDNS_ENABLE_KISS], [ + AC_ARG_ENABLE([unsafe-rng-kiss], + AS_HELP_STRING([--enable-unsafe-rng-kiss], + [Enable unsafe rng KISS]), [ + AC_DEFINE([HAVE_KISS_RNG], [1], [Define to 1 to enable unsafe rng KISS]) + ]) +]) diff --git a/m4/pdns_enable_malloc_trace.m4 b/m4/pdns_enable_malloc_trace.m4 new file mode 100644 index 0000000..4987a53 --- /dev/null +++ b/m4/pdns_enable_malloc_trace.m4 @@ -0,0 +1,13 @@ +AC_DEFUN([PDNS_ENABLE_MALLOC_TRACE], [ + AC_MSG_CHECKING([whether to enable code malloc-trace]) + AC_ARG_ENABLE([malloc-trace], + AS_HELP_STRING([--enable-malloc-trace], + [enable malloc-trace @<:@default=no@:>@]), + [enable_malloc_trace=$enableval], + [enable_malloc_trace=no] + ) + AC_MSG_RESULT([$enable_malloc_trace]) + AM_CONDITIONAL([MALLOC_TRACE], [test "x$enable_malloc_trace" = "xyes"]) + AS_IF([test "x$enable_malloc_trace" = "xyes"], + AC_DEFINE([MALLOC_TRACE], [1], [Define to 1 if you want to benefit from malloc trace]) ) +]) diff --git a/m4/pdns_enable_p11kit.m4 b/m4/pdns_enable_p11kit.m4 new file mode 100644 index 0000000..afad79e --- /dev/null +++ b/m4/pdns_enable_p11kit.m4 @@ -0,0 +1,21 @@ +AC_DEFUN([PDNS_ENABLE_PKCS11],[ + AC_MSG_CHECKING([whether to enable PKCS11 support]) + AC_ARG_ENABLE([experimental-pkcs11], + [AS_HELP_STRING([--enable-experimental-pkcs11],[enable experimental PKCS11 support @<:@default=no@:>@])], + [enable_pkcs11=$enableval], + [enable_pkcs11=no] + ) + AC_MSG_RESULT([$enable_pkcs11]) + AM_CONDITIONAL([PKCS11], [test "x$enable_pkcs11" != "xno"]) + + AS_IF([test "x$enable_pkcs11" != "xno"], [ + PKG_CHECK_MODULES([P11KIT1], [p11-kit-1], + [ + AC_DEFINE([HAVE_P11KIT1],[1],[Define to 1 if you have p11-kit-1]) + AC_CHECK_LIB([p11-kit], [p11_kit_module_for_name], [AC_DEFINE([HAVE_P11KIT1_V2],[1],[Define to 1 if you have 0.20 or newer P11-kit])], [], [$P11KIT1_LIBS]) + ], + [AC_MSG_ERROR([Could not find p11-kit-1])] + )] + ) + +]) diff --git a/m4/pdns_enable_remotebackend_zeromq.m4 b/m4/pdns_enable_remotebackend_zeromq.m4 new file mode 100644 index 0000000..b20d1b2 --- /dev/null +++ b/m4/pdns_enable_remotebackend_zeromq.m4 @@ -0,0 +1,45 @@ +AC_DEFUN([PDNS_ENABLE_REMOTEBACKEND_ZEROMQ],[ + AC_MSG_CHECKING([whether to enable ZeroMQ connector in remotebackend]) + AC_ARG_ENABLE([remotebackend_zeromq], + AS_HELP_STRING([--enable-remotebackend-zeromq], + [enable ZeroMQ connector for remotebackend @<:@default=no@:>@] + ), + [enable_remotebackend_zeromq=$enableval], + [enable_remotebackend_zeromq=no] + ) + + AC_MSG_RESULT([$enable_remotebackend_zeromq]) + + AM_CONDITIONAL([REMOTEBACKEND_ZEROMQ],[test "x$enable_remotebackend_zeromq" != "xno"]) + AC_SUBST(REMOTEBACKEND_ZEROMQ) + + AS_IF([test "x$enable_remotebackend_zeromq" != "xno"], + [ + AS_IF([test "x$have_remotebackend" = "xyes"], + [ + PKG_CHECK_MODULES([LIBZMQ], [libzmq], + [ + AC_DEFINE([HAVE_LIBZMQ], [1], [Define to 1 if you have libzmq]) + AC_DEFINE([REMOTEBACKEND_ZEROMQ], [1], [Define to 1 if you have the ZeroMQ connector]) + REMOTEBACKEND_ZEROMQ=yes + ], + [AC_MSG_ERROR([Could not find libzmq])] + ) + + old_CXXFLAGS="$CXXFLAGS" + old_LDFLAGS="$LDFLAGS" + CXXFLAGS="$CFLAGS $LIBZMQ_CFLAGS" + LDFLAGS="$LDFLAGS $LIBZMQ_LIBS" + AC_CHECK_LIB([zmq], [zmq_msg_send], + [ + AC_DEFINE([HAVE_ZMQ_MSG_SEND], [1], [Define to 1 if the ZeroMQ 3.x or greater API is available]) + ] + ) + CXXFLAGS="$old_CXXFLAGS" + LDFLAGS="$old_LDFLAGS" + ], + [AC_MSG_ERROR([remotebackend \"zeromq\" selected but the \"remote\" backend itself is not selected. Please add \"remote\" to your modules or dynmodules list and re-run configure!])] + ) + ] + ) +]) diff --git a/m4/pdns_enable_reproducible.m4 b/m4/pdns_enable_reproducible.m4 new file mode 100644 index 0000000..7be3c5d --- /dev/null +++ b/m4/pdns_enable_reproducible.m4 @@ -0,0 +1,29 @@ +AC_DEFUN([PDNS_ENABLE_REPRODUCIBLE], [ + AC_REQUIRE([PDNS_CHECK_OS]) + AC_MSG_CHECKING([whether to enable reproducible builds.]) + AC_ARG_ENABLE([reproducible], + AS_HELP_STRING([--enable-reproducible], + [Create reproducible builds. Use this only if you are a distribution maintainer and need reproducible builds. If you compile PowerDNS yourself, leave this disabled, as it might make debugging harder. @<:@default=no@:>@]), + [enable_reproducible=$enableval], + [enable_reproducible=no]) + + AC_MSG_RESULT($enable_reproducible) + + AS_IF([test x"$enable_reproducible" = "xyes"],[ + AC_DEFINE([REPRODUCIBLE], [1], [Define to 1 for reproducible builds]) + ],[ + build_user=$(id -u -n) + + case "$host_os" in + solaris2.1* | SunOS | openbsd*) + build_host_host=$(hostname) + build_host_domain=$(domainname) + build_host="$build_host_host.$build_host_domain" + ;; + *) + build_host=$(hostname -f || hostname || echo 'localhost') + ;; + esac + AC_DEFINE_UNQUOTED([BUILD_HOST], ["$build_user@$build_host"], [Set to the user and host that builds PowerDNS]) + ]) +]) diff --git a/m4/pdns_enable_sanitizers.m4 b/m4/pdns_enable_sanitizers.m4 new file mode 100644 index 0000000..6773e1a --- /dev/null +++ b/m4/pdns_enable_sanitizers.m4 @@ -0,0 +1,167 @@ +AC_DEFUN([PDNS_ENABLE_SANITIZERS], [ + PDNS_ENABLE_ASAN + PDNS_ENABLE_MSAN + PDNS_ENABLE_TSAN + PDNS_ENABLE_LSAN + PDNS_ENABLE_UBSAN + + AS_IF([test "x$enable_asan" != "xno" -a "x$enable_tsan" != "xno"],[ + AC_MSG_ERROR([Address Sanitizer is not compatible with Thread Sanitizer]) + ]) + + AS_IF([test "x$enable_msan" != "xno" -a "x$enable_asan" != "xno"],[ + AC_MSG_ERROR([Memory Sanitizer is not compatible with Address Sanitizer]) + ]) + + AS_IF([test "x$enable_msan" != "xno" -a "x$enable_lsan" != "xno"],[ + AC_MSG_ERROR([Memory Sanitizer is not compatible with Leak Sanitizer]) + ]) + + AS_IF([test "x$enable_msan" != "xno" -a "x$enable_tsan" != "xno"],[ + AC_MSG_ERROR([Memory Sanitizer is not compatible with Thread Sanitizer]) + ]) + + AS_IF([test "x$enable_asan" != "xno" -o "x$enable_tsan" != "xno" -o "x$enable_lsan" != "xno" -o "x$enable_ubsan" != "xno" -o "x$enable_msan" != "xno"], [ + gl_WARN_ADD([-fno-omit-frame-pointer]) + ]) +]) + +AC_DEFUN([PDNS_ENABLE_ASAN], [ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AC_MSG_CHECKING([whether to enable AddressSanitizer]) + AC_ARG_ENABLE([asan], + AS_HELP_STRING([--enable-asan], + [enable AddressSanitizer @<:@default=no@:>@]), + [enable_asan=$enableval], + [enable_asan=no] + ) + AC_MSG_RESULT([$enable_asan]) + + AS_IF([test "x$enable_asan" != "xno"], [ + gl_COMPILER_OPTION_IF([-fsanitize=address], + [ + [SANITIZER_FLAGS="-fsanitize=address $SANITIZER_FLAGS"] + AC_CHECK_HEADERS([sanitizer/common_interface_defs.h], asan_headers=yes, asan_headers=no) + AS_IF([test x"$asan_headers" = "xyes" ], + [AC_CHECK_DECL(__sanitizer_start_switch_fiber, + [ + AC_MSG_CHECKING([for the exact signature of __sanitizer_finish_switch_fiber]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [#include ], + [ + __sanitizer_finish_switch_fiber(nullptr); + ]) + ], [ + AC_MSG_RESULT([a single pointer]) + AC_DEFINE([HAVE_FIBER_SANITIZER], [1], [Define if ASAN fiber annotation interface is available.]) + AC_DEFINE(HAVE_SANITIZER_FINISH_SWITCH_FIBER_SINGLE_PTR, [1], [Define to 1 if __sanitizer_finish_switch_fiber takes only a pointer]) + ], [ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [#include ], + [ + __sanitizer_finish_switch_fiber(nullptr, nullptr, nullptr); + ]) + ], [ + AC_MSG_RESULT([three pointers]) + AC_DEFINE([HAVE_FIBER_SANITIZER], [1], [Define if ASAN fiber annotation interface is available.]) + AC_DEFINE(HAVE_SANITIZER_FINISH_SWITCH_FIBER_THREE_PTRS, [1], [Define to 1 if __sanitizer_finish_switch_fiber takes three pointers]) + ], [ + AC_MSG_RESULT([unknown]) + AC_MSG_NOTICE([ASAN fiber switching is not available due to an unknown API version]) + ]) + ]) + ], [ + AC_MSG_NOTICE([ASAN fiber switching is not available]) + ], + [#include ] + )] + ) + ], + [AC_MSG_ERROR([Cannot enable AddressSanitizer])] + ) + ]) + AC_SUBST([SANITIZER_FLAGS]) +]) + +AC_DEFUN([PDNS_ENABLE_TSAN], [ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AC_MSG_CHECKING([whether to enable ThreadSanitizer]) + AC_ARG_ENABLE([tsan], + AS_HELP_STRING([--enable-tsan], + [enable ThreadSanitizer @<:@default=no@:>@]), + [enable_tsan=$enableval], + [enable_tsan=no] + ) + AC_MSG_RESULT([$enable_tsan]) + + AS_IF([test "x$enable_tsan" != "xno"], [ + gl_COMPILER_OPTION_IF([-fsanitize=thread], + [SANITIZER_FLAGS="-fsanitize=thread $SANITIZER_FLAGS"], + [AC_MSG_ERROR([Cannot enable ThreadSanitizer])] + ) + ]) + AC_SUBST([SANITIZER_FLAGS]) +]) + +AC_DEFUN([PDNS_ENABLE_LSAN], [ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AC_MSG_CHECKING([whether to enable LeakSanitizer]) + AC_ARG_ENABLE([lsan], + AS_HELP_STRING([--enable-lsan], + [enable LeakSanitizer @<:@default=no@:>@]), + [enable_lsan=$enableval], + [enable_lsan=no] + ) + AC_MSG_RESULT([$enable_lsan]) + + AS_IF([test "x$enable_lsan" != "xno"], [ + gl_COMPILER_OPTION_IF([-fsanitize=leak], + [SANITIZER_FLAGS="-fsanitize=leak $SANITIZER_FLAGS"], + [AC_MSG_ERROR([Cannot enable LeakSanitizer])] + ) + ]) + AC_SUBST([SANITIZER_FLAGS]) +]) + +AC_DEFUN([PDNS_ENABLE_UBSAN], [ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AC_MSG_CHECKING([whether to enable Undefined Behaviour Sanitizer]) + AC_ARG_ENABLE([ubsan], + AS_HELP_STRING([--enable-ubsan], + [enable Undefined Behaviour Sanitizer @<:@default=no@:>@]), + [enable_ubsan=$enableval], + [enable_ubsan=no] + ) + AC_MSG_RESULT([$enable_ubsan]) + + AS_IF([test "x$enable_ubsan" != "xno"], [ + gl_COMPILER_OPTION_IF([-fsanitize=undefined], + [SANITIZER_FLAGS="-fsanitize=undefined $SANITIZER_FLAGS"], + [AC_MSG_ERROR([Cannot enable Undefined Behaviour Sanitizer])] + ) + ]) + AC_SUBST([SANITIZER_FLAGS]) +]) + +AC_DEFUN([PDNS_ENABLE_MSAN], [ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + AC_MSG_CHECKING([whether to enable MemorySanitizer]) + AC_ARG_ENABLE([msan], + AS_HELP_STRING([--enable-msan], + [enable MemorySanitizer @<:@default=no@:>@]), + [enable_msan=$enableval], + [enable_msan=no] + ) + AC_MSG_RESULT([$enable_msan]) + + AS_IF([test "x$enable_msan" != "xno"], [ + gl_COMPILER_OPTION_IF([-fsanitize=memory], + [SANITIZER_FLAGS="-fsanitize=memory $SANITIZER_FLAGS"], + [AC_MSG_ERROR([Cannot enable MemorySanitizer])] + ) + ]) + AC_SUBST([SANITIZER_FLAGS]) +]) + diff --git a/m4/pdns_enable_tools.m4 b/m4/pdns_enable_tools.m4 new file mode 100644 index 0000000..4324f8e --- /dev/null +++ b/m4/pdns_enable_tools.m4 @@ -0,0 +1,12 @@ +AC_DEFUN([PDNS_ENABLE_TOOLS], [ + AC_REQUIRE([PDNS_CHECK_LIBCURL]) dnl We only care about the #define HAVE_LIBCURL and can build tools without DOH support. + AC_MSG_CHECKING([whether we will be building and installing the extra tools]) + AC_ARG_ENABLE([tools], + [AS_HELP_STRING([--enable-tools], [if we should build and install the tools @<:@default=no@:>@])], + [enable_tools=$enableval], + [enable_tools=no] + ) + AC_MSG_RESULT([$enable_tools]) + + AM_CONDITIONAL([TOOLS], [test "x$enable_tools" != "xno"]) +]) diff --git a/m4/pdns_enable_unit_tests.m4 b/m4/pdns_enable_unit_tests.m4 new file mode 100644 index 0000000..f34fbe0 --- /dev/null +++ b/m4/pdns_enable_unit_tests.m4 @@ -0,0 +1,18 @@ +AC_DEFUN([PDNS_ENABLE_UNIT_TESTS], [ + AC_MSG_CHECKING([whether to enable unit test building]) + AC_ARG_ENABLE([unit-tests], + AS_HELP_STRING([--enable-unit-tests], + [enable unit test building @<:@default=no@:>@]), + [enable_unit_tests=$enableval], + [enable_unit_tests=no] + ) + AC_MSG_RESULT([$enable_unit_tests]) + AM_CONDITIONAL([UNIT_TESTS], [test "x$enable_unit_tests" != "xno"]) + + AS_IF([test "x$enable_unit_tests" != "xno"], [ + BOOST_TEST([mt]) + AS_IF([test "$boost_cv_lib_unit_test_framework" = "no"], [ + AC_MSG_ERROR([Boost Unit Test library not found]) + ]) + ]) +]) diff --git a/m4/pdns_enable_verbose_logging.m4 b/m4/pdns_enable_verbose_logging.m4 new file mode 100644 index 0000000..0104f43 --- /dev/null +++ b/m4/pdns_enable_verbose_logging.m4 @@ -0,0 +1,17 @@ +AC_DEFUN([PDNS_ENABLE_VERBOSE_LOGGING],[ + AC_MSG_CHECKING([whether to enable verbose logging]) + + AC_ARG_ENABLE([verbose-logging], + AS_HELP_STRING([--enable-verbose-logging], + [enable verbose logging @<:@default=no@:>@] + ), + [enable_verbose_logging=$enableval], + [enable_verbose_logging=no] + ) + + AS_IF([test "x$enable_verbose_logging" != "xno"], + [AC_DEFINE([VERBOSELOG], [1], [Define to 1 if verbose logging is enabled])] + ) + + AC_MSG_RESULT([$enable_verbose_logging]) +]) diff --git a/m4/pdns_from_git.m4 b/m4/pdns_from_git.m4 new file mode 100644 index 0000000..18966a5 --- /dev/null +++ b/m4/pdns_from_git.m4 @@ -0,0 +1,3 @@ +AC_DEFUN([PDNS_FROM_GIT], [ + AM_CONDITIONAL([FROM_GIT], [test -d "$srcdir/.git"]) +]) diff --git a/m4/pdns_param_ssp_buffer_size.m4 b/m4/pdns_param_ssp_buffer_size.m4 new file mode 100644 index 0000000..05c1bae --- /dev/null +++ b/m4/pdns_param_ssp_buffer_size.m4 @@ -0,0 +1,26 @@ +dnl +dnl Check for support for ssp parameter buffer size +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([AC_CC_PARAM_SSP_BUFFER_SIZE],[ + gl_COMPILER_OPTION_IF([--param ssp-buffer-size=$1], [ + CFLAGS="--param ssp-buffer-size=$1 $CFLAGS" + CXXFLAGS="--param ssp-buffer-size=$1 $CXXFLAGS" + ]) +]) diff --git a/m4/pdns_pie.m4 b/m4/pdns_pie.m4 new file mode 100644 index 0000000..98d3923 --- /dev/null +++ b/m4/pdns_pie.m4 @@ -0,0 +1,55 @@ +dnl +dnl Check for support for position independent executables +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([AC_CC_PIE],[ + AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) + PIE_CFLAGS= + PIE_LDFLAGS= + OLD_CXXFLAGS=$CXXFLAGS + case "$host" in + *-*-mingw* | *-*-msvc* | *-*-cygwin* ) + ;; dnl All code is position independent on Win32 target + *) + CXXFLAGS="-fPIE -DPIE" + gl_COMPILER_OPTION_IF([-pie], [ + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-pie" + ], [ + dnl some versions of clang require -Wl,-pie instead of -pie + gl_COMPILER_OPTION_IF([[-Wl,-pie]], [ + PIE_CFLAGS="-fPIE -DPIE" + PIE_LDFLAGS="-Wl,-pie" + ], [], + [AC_LANG_PROGRAM([[ +#include +__thread unsigned int t_id; + ]], [[t_id = 1;]])] + ) + ], + [AC_LANG_PROGRAM([[ +#include +__thread unsigned int t_id; + ]], [[t_id = 1;]])] + ) + esac + CXXFLAGS=$OLD_CXXFLAGS + AC_SUBST([PIE_CFLAGS]) + AC_SUBST([PIE_LDFLAGS]) +]) diff --git a/m4/pdns_relro.m4 b/m4/pdns_relro.m4 new file mode 100644 index 0000000..4f93629 --- /dev/null +++ b/m4/pdns_relro.m4 @@ -0,0 +1,37 @@ +dnl +dnl Check for -z now and -z relro linker flags +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([AC_LD_RELRO],[ + AC_MSG_CHECKING([for how to force completely read-only GOT table]) + + RELRO_LDFLAGS= + ld_help=`$CXX -Wl,-help 2>&1` + case $ld_help in + *"-z relro"*) RELRO_LDFLAGS="-Wl,-z -Wl,relro" ;; + esac + case $ld_help in + *"-z now"*) RELRO_LDFLAGS="$RELRO_LDFLAGS -Wl,-z -Wl,now" ;; + esac + AC_SUBST([RELRO_LDFLAGS]) + AS_IF([test "x$RELRO_LDFLAGS" != "x"], + [AC_MSG_RESULT([$RELRO_LDFLAGS])], + [AC_MSG_RESULT([unknown])] + ) +]) diff --git a/m4/pdns_stack_protector.m4 b/m4/pdns_stack_protector.m4 new file mode 100644 index 0000000..388035c --- /dev/null +++ b/m4/pdns_stack_protector.m4 @@ -0,0 +1,26 @@ +dnl +dnl Check for support for enabling stack protector +dnl +dnl Copyright (C) 2013 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([AC_CC_STACK_PROTECTOR],[ + gl_COMPILER_OPTION_IF([-fstack-protector], [ + CFLAGS="-fstack-protector $CFLAGS" + CXXFLAGS="-fstack-protector $CXXFLAGS" + ]) +]) diff --git a/m4/pdns_with_geo.m4 b/m4/pdns_with_geo.m4 new file mode 100644 index 0000000..352da97 --- /dev/null +++ b/m4/pdns_with_geo.m4 @@ -0,0 +1,47 @@ +AC_DEFUN([PDNS_CHECK_GEOIP], [ + PKG_CHECK_MODULES([GEOIP], [geoip], AC_DEFINE([HAVE_GEOIP], [1], [Define this if you have GeoIP]), [have_geoip=0]) + AC_ARG_WITH([maxminddb_incdir], + AS_HELP_STRING([--with-maxminddb-includedir],[path to maxminddb include directory @<:@default=auto@:>@]), + [with_maxminddb_incdir=$withval], + [with_maxminddb_incdir=auto] + ) + AC_ARG_WITH([maxminddb_libdir], + AS_HELP_STRING([--with-maxminddb-libdir],[path to maxminddb library directory @<:@default=auto@:>@]), + [with_maxminddb_libdir=$withval], + [with_maxminddb_libdir=auto], + ) + + PKG_CHECK_MODULES([MMDB], [libmaxminddb], [ + AC_DEFINE([HAVE_MMDB], [1], [Define this if you have Maxmind DB]) + ], [ + AS_IF([test "x$with_maxminddb_incdir" = "xauto"], [ + AC_CHECK_HEADER([maxminddb.h], [have_mmdb=1], [have_mmdb=0]) + ], [ + OLD_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -I$with_maxminddb_incdir" + AC_CHECK_HEADER([maxminddb.h], [have_mmdb=1], [have_mmdb=0]) + CFLAGS="$OLD_CFLAGS" + ]) + + AS_IF([test "$have_mmdb" = "1"], [ + AS_IF([test "x$with_maxminddb_libdir" = "xauto"], [ + AC_CHECK_LIB([maxminddb], [MMDB_open], [ + AC_DEFINE([HAVE_MMDB], [1], [Define this if you have Maxmind DB]) + MMDB_LIBS="-lmaxminddb" + ]) + ], [ + OLD_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$with_maxminddb_libdir" + AC_CHECK_LIB([maxminddb], [MMDB_open], [ + AC_DEFINE([HAVE_MMDB], [1], [Define this if you have Maxmind DB]) + MMDB_CFLAGS="-I$with_maxminddb_incdir" + MMDB_LIBS="-L$with_maxminddb_libdir -lmaxminddb" + ]) + ]) + ]) + ]) + + PKG_CHECK_MODULES([YAML], [yaml-cpp >= 0.5],[], + AC_MSG_ERROR([Could not find yaml-cpp]) + ) +]) diff --git a/m4/pdns_with_libdecaf.m4 b/m4/pdns_with_libdecaf.m4 new file mode 100644 index 0000000..9710366 --- /dev/null +++ b/m4/pdns_with_libdecaf.m4 @@ -0,0 +1,23 @@ +AC_DEFUN([PDNS_WITH_LIBDECAF],[ + AC_MSG_CHECKING([whether we will be linking in libdecaf]) + AC_ARG_WITH([libdecaf], + [AS_HELP_STRING([--with-libdecaf],[use libdecaf @<:@default=no@:>@])], + [with_libdecaf=$withval], + [with_libdecaf=no] + ) + AC_MSG_RESULT([$with_libdecaf]) + + AM_CONDITIONAL([LIBDECAF],[test "x$with_libdecaf" != "xno"]) + + AS_IF([test "x$with_libdecaf" != "xno"],[ + save_LIBS=$LIBS + LIBS="" + AC_SEARCH_LIBS([decaf_ed25519_sign],[decaf],[ + AC_DEFINE([HAVE_LIBDECAF],[1],[Define to 1 if you have libdecaf]) + AC_SUBST([LIBDECAF_LIBS],["$LIBS"]) + ],[ + AC_MSG_ERROR([Could not find libdecaf]) + ]) + LIBS="$save_LIBS" + ]) +]) diff --git a/m4/pdns_with_libsodium.m4 b/m4/pdns_with_libsodium.m4 new file mode 100644 index 0000000..44e034b --- /dev/null +++ b/m4/pdns_with_libsodium.m4 @@ -0,0 +1,30 @@ +AC_DEFUN([PDNS_WITH_LIBSODIUM], [ + AC_MSG_CHECKING([whether we will be linking in libsodium]) + AC_ARG_WITH([libsodium], + AS_HELP_STRING([--with-libsodium],[use libsodium @<:@default=auto@:>@]), + [with_libsodium=$withval], + [with_libsodium=auto], + ) + AC_MSG_RESULT([$with_libsodium]) + + AS_IF([test "x$with_libsodium" != "xno"], [ + AS_IF([test "x$with_libsodium" = "xyes" -o "x$with_libsodium" = "xauto"], [ + PKG_CHECK_MODULES([LIBSODIUM], [libsodium], [ + AC_DEFINE([HAVE_LIBSODIUM], [1], [Define to 1 if you have libsodium]) + save_CFLAGS=$CFLAGS + save_LIBS=$LIBS + CFLAGS="$LIBSODIUM_CFLAGS $CFLAGS" + LIBS="$LIBSODIUM_LIBS $LIBS" + AC_CHECK_FUNCS([crypto_box_easy_afternm crypto_box_curve25519xchacha20poly1305_easy randombytes_stir]) + CFLAGS=$save_CFLAGS + LIBS=$save_LIBS + ], [ : ]) + ]) + ]) + AM_CONDITIONAL([LIBSODIUM], [test "x$LIBSODIUM_LIBS" != "x"]) + AS_IF([test "x$with_libsodium" = "xyes"], [ + AS_IF([test x"$LIBSODIUM_LIBS" = "x"], [ + AC_MSG_ERROR([libsodium requested but libraries were not found]) + ]) + ]) +]) diff --git a/m4/pdns_with_lua.m4 b/m4/pdns_with_lua.m4 new file mode 100644 index 0000000..e280c1b --- /dev/null +++ b/m4/pdns_with_lua.m4 @@ -0,0 +1,62 @@ +AC_DEFUN([PDNS_WITH_LUA],[ + AC_PROG_GREP()dnl Ensure we have grep + AC_MSG_CHECKING([which Lua implementation to use]) + AC_ARG_WITH([lua], + [AS_HELP_STRING([--with-lua], [select Lua implementation @<:@default=auto@:>@]) + ], [ + with_lua=$withval + ], [ + with_lua=auto + ]) + + AS_IF([test "x$with_lua" = "xyes"], [ + dnl --with-lua was passed, make it auto + with_lua=auto + ]) + + AC_MSG_RESULT([$with_lua]) + + AS_IF([test "x$with_lua" = "xno" -a "$1" = "mandatory"], [ + AC_MSG_ERROR([--without-lua specified, but Lua is not optional]) + ]) + + LUAPC="" + luajit_min_version='2.0.2' + lua_min_version='5.1' + + AS_IF([test "x$with_lua" != "xno"], [ + AS_IF([test "x$with_lua" != "xauto"], [ + with_lua_version=${lua_min_version} + AS_IF([echo "x$with_lua" | ${GREP} 'jit' >/dev/null 2>&1], [with_lua_version=${luajit_min_version}]) + PKG_CHECK_MODULES([LUA], $with_lua >= $with_lua_version, [ + AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have Lua]) + LUAPC=$with_lua + ], [ + AC_MSG_ERROR([Selected Lua ($with_lua) not found]) + ]) + ], [ + PKG_CHECK_MODULES([LUA], [luajit >= ${luajit_min_version}], [ + LUAPC=luajit + AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have Lua]) + ], [ : ]) + AS_IF([test -z "$LUAPC"], [ + found_lua=n + m4_foreach_w([luapc], [lua5.3 lua-5.3 lua53 lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua51 lua], [ + AS_IF([test "$found_lua" != "y"], [ + PKG_CHECK_MODULES([LUA], [luapc >= ${lua_min_version}], [ + AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have lua]) + found_lua=y + LUAPC=luapc + ], [ : ]) + ]) + ]) + ]) + ]) + ]) + + AS_IF([test -z "$LUAPC" -a "$1" = "mandatory"], [ + AC_MSG_ERROR([No Lua not found, but is mandatory]) + ]) + + AM_CONDITIONAL([LUA], [test -n "x$LUAPC"]) +]) diff --git a/m4/pdns_with_lua_records.m4 b/m4/pdns_with_lua_records.m4 new file mode 100644 index 0000000..763ee8f --- /dev/null +++ b/m4/pdns_with_lua_records.m4 @@ -0,0 +1,23 @@ +AC_DEFUN([PDNS_WITH_LUA_RECORDS], [ + AC_REQUIRE([PDNS_CHECK_LIBCURL]) + AC_MSG_CHECKING([whether we will enable LUA records]) + + AC_ARG_ENABLE([lua-records], + [AS_HELP_STRING([--disable-lua-records], [disable LUA records support @<:@default=no@:>@])], + [enable_lua_records=$enableval], + [enable_lua_records=yes] + ) + AC_MSG_RESULT([$enable_lua_records]) + + AS_IF([test "x$enable_lua_records" != "xno"], [ + AS_IF([test "x$LUAPC" = "x"], + AC_MSG_ERROR([LUA records need LUA. You can disable this feature with the --disable-lua-records switch or configure a proper LUA installation.]) + ) + AS_IF([test "$HAVE_LIBCURL" != "y"], [ + AC_MSG_ERROR([libcurl minimum version requirement not met. This is required for LUA records. You can disable it with the --disable-lua-records switch or use --with-libcurl to select another curl installation.]) + ]) + + AC_DEFINE([HAVE_LUA_RECORDS], [1], [Define if enabling LUA records.]) + ]) + AM_CONDITIONAL([HAVE_LUA_RECORDS], [test "x$enable_lua_records" != "xno"]) +]) diff --git a/m4/pdns_with_mysql.m4 b/m4/pdns_with_mysql.m4 new file mode 100644 index 0000000..036b963 --- /dev/null +++ b/m4/pdns_with_mysql.m4 @@ -0,0 +1,111 @@ +AC_DEFUN([PDNS_WITH_MYSQL],[ + AC_ARG_WITH([mysql], + [AS_HELP_STRING([--with-mysql=], [root directory path of MySQL installation])], + [ + if test "$withval" = "no"; then + modules_without_gmysql=$(echo $modules|sed -e 's/gmysql//;s/ */ /g;') + dynmodules_without_gmysql=$(echo $dynmodules|sed -e 's/gmysql//;s/ */ /g;') + AC_MSG_ERROR([instead of --without-mysql try --with-modules="$modules_without_gmysql" --with-dyn-modules="$dynmodules_without_gmysql"]) + fi + + MYSQL_LIBS_check="$withval/lib/mysql $with_mysql/lib" + MYSQL_CFLAGS_check="$withval/include/mysql" + MYSQL_config_check="$withval/bin/mysql_config" + ], + [ + MYSQL_LIBS_check="/usr/local/mysql/lib/mysql /usr/local/lib/mysql /opt/mysql/lib/mysql \ + /usr/lib/mysql /usr/lib64/mysql /usr/local/mysql/lib /usr/local/lib /opt/mysql/lib /usr/lib \ + /usr/sfw/lib/ $full_libdir" + MYSQL_CFLAGS_check="/usr/local/mysql/include/mysql /usr/local/include/mysql \ + /opt/mysql/include/mysql /opt/mysql/include /usr/include/mysql /usr/sfw/include/mysql" + ] + ) + + AC_ARG_WITH([mysql-config], + [AS_HELP_STRING([--with-mysql-config=], [file path to mysql_config])], + [MYSQL_config_check=$withval] + ) + + AC_ARG_WITH([mysql-lib], + [AS_HELP_STRING([--with-mysql-lib=], [directory path of MySQL library installation])], + [ + MYSQL_LIBS_check="$withval/lib/mysql $withval/mysql $withval" + MYSQL_config_check="skip" + ] + ) + + AC_ARG_WITH([mysql-includes], + [AS_HELP_STRING([--with-mysql-includes=], [directory path of MySQL header installation])], + [ + MYSQL_CFLAGS_check="$withval/include/mysql $withval/mysql $withval" + MYSQL_config_check="skip" + ] + ) + + MYSQL_config="" + if test "x$MYSQL_config_check" != "xskip"; then + if test "x$MYSQL_config_check" = "x"; then + AC_PATH_PROG([MYSQL_config], [mysql_config]) + else + AC_MSG_CHECKING([for $MYSQL_config_check]) + if test -x $MYSQL_config_check; then + MYSQL_config="$MYSQL_config_check" + AC_MSG_RESULT([yes]) + else + MYSQL_config="" + AC_MSG_ERROR([not found]) + fi + fi + fi + + if test "x$MYSQL_config" != "x"; then + # use this to configure everything + MYSQL_LIBS=`$MYSQL_config --libs` + MYSQL_CFLAGS=`$MYSQL_config --include` + else + AC_MSG_CHECKING([for MySQL library directory]) + MYSQL_libdir= + for m in $MYSQL_LIBS_check; do + if test -d "$m" && \ + (test -f "$m/libmysqlclient.so" || test -f "$m/libmysqlclient.a") + then + MYSQL_libdir=$m + break + fi + done + if test -z "$MYSQL_libdir"; then + AC_MSG_ERROR([Did not find the mysql library dir in '$MYSQL_LIBS_check']) + fi + case "$MYSQL_libdir" in + /*) MYSQL_LIBS="-L$MYSQL_libdir -lmysqlclient" + ;; + *) AC_MSG_ERROR([The MySQL library directory ($MYSQL_libdir) must be an absolute path.]) + ;; + esac + AC_MSG_RESULT([$MYSQL_libdir]) + AC_SUBST(MYSQL_LIBS) + AC_MSG_CHECKING([for MySQL include directory]) + MYSQL_CFLAGS= + for m in $MYSQL_CFLAGS_check; do + if test -d "$m" && test -f "$m/mysql.h" + then + MYSQL_CFLAGS="$m" + break + fi + done + if test -z "$MYSQL_CFLAGS"; then + AC_MSG_ERROR([Did not find the mysql include dir in '$MYSQL_CFLAGS_check']) + fi + + case "$MYSQL_CFLAGS" in + /*) AC_MSG_RESULT($MYSQL_CFLAGS) + ;; + *) AC_MSG_ERROR([The MySQL include directory ($MYSQL_CFLAGS) must be an absolute path.]) + ;; + esac + MYSQL_CFLAGS="-I$MYSQL_CFLAGS" + fi + AC_SUBST(MYSQL_LIBS) + AC_SUBST(MYSQL_CFLAGS) +]) + diff --git a/m4/pdns_with_oracle.m4 b/m4/pdns_with_oracle.m4 new file mode 100644 index 0000000..0f16fbd --- /dev/null +++ b/m4/pdns_with_oracle.m4 @@ -0,0 +1,62 @@ +AC_DEFUN([PDNS_WITH_ORACLE],[ + AC_ARG_WITH(oracle_includes, AS_HELP_STRING([--with-oracle-includes=],[instantclient sdk include dir])) + AC_ARG_WITH(oracle_libs, AS_HELP_STRING([--with-oracle-libs=],[instantclient oracle library dir])) + + if test x"$with_oracle_includes" = "x"; then + # check possible locations + for p1 in /usr/include/oracle /usr/local/include/oracle; do + for p2 in $p1/*/client*; do + if test -d "$p2"; then + with_oracle_includes=$p2 + fi + done + done + fi + + if test x"$with_oracle_includes" = x && test "$ORACLE_HOME/rdbms/public" != "/rdbms/public"; then + if test -d $ORACLE_HOME/rdbms/public; then + with_oracle_includes=$ORACLE_HOME/rdbms/public + fi + fi + + # test header + old_CXXFLAGS="$CXXFLAGS" + old_CFLAGS="$CFLAGS" + CXXFLAGS="$CXXFLAGS -I$with_oracle_includes" + CPPFLAGS="$CPPFLAGS -I$with_oracle_includes" + AC_CHECK_HEADER([oci.h], ORACLE_CFLAGS="-I$with_oracle_includes", AC_MSG_ERROR([Could not find oci.h])) + CXXFLAGS="$old_CXXFLAGS" + CPPFLAGS="$old_CPPFLAGS" + AC_SUBST([ORACLE_CFLAGS]) + AC_SUBST([ORACLE_LIBS]) + + if test x"$with_oracle_libs" = "x"; then + # check possible locations + for p1 in /usr/lib/oracle /usr/local/lib/oracle; do + for p2 in $p1/*/client*/lib; do + if test -d "$p2"; then + with_oracle_libs=$p2 + fi + done + done + fi + + if test x"$with_oracle_libs" = x && test "$ORACLE_HOME/lib" != "/lib"; then + if test -d $ORACLE_HOME/lib; then + with_oracle_libs=$ORACLE_HOME/lib + fi + fi + + # we have to check for client9 as well... + # test -lclntsh + old_LDFLAGS="$LDFLAGS" + LDFLAGS="-L$with_oracle_libs -locci" + AC_CHECK_LIB([clntsh],[OCIEnvInit], + [ORACLE_LIBS="-L$with_oracle_libs -lclntsh -locci"], + AC_CHECK_LIB([client9], [OCIEnvInit], + [ORACLE_LIBS="-L$with_oracle_libs -lclient9 -lclntsh9"], + [AC_MSG_ERROR([Could not find client libraries])] + ) + ) + LDFLAGS="$old_LDFLAGS" +]) diff --git a/m4/pdns_with_postgresql.m4 b/m4/pdns_with_postgresql.m4 new file mode 100644 index 0000000..a253fa5 --- /dev/null +++ b/m4/pdns_with_postgresql.m4 @@ -0,0 +1,35 @@ +dnl +dnl Attempt to detect the flags we need for the Postgresql client libraries +dnl First, use pkg-config +dnl If that yields no results, use (optionally find) pg_config and use it to +dnl determine the CFLAGS and LIBS +dnl +AC_DEFUN([PDNS_WITH_POSTGRESQL], [ + PG_CONFIG="" + AC_ARG_WITH([pg-config], + [AS_HELP_STRING([--with-pg-config=], [path to pg_config]) + ], [ + PG_CONFIG="$withval" + AS_IF([test "x$PG_CONFIG" = "xyes" -o ! -x "$PG_CONFIG"], [ + AC_MSG_ERROR([--with-pg-config must provide a valid path to the pg_config executable]) + ]) + ]) + + AS_IF([test "x$PG_CONFIG" = "x"], [ + PKG_CHECK_MODULES([PGSQL], [libpq], [ : ], [ : ]) + ]) + + AS_IF([test "x$PG_CONFIG" != "x" -o "x$PGSQL_LIBS" = "x"], [ + dnl Either a path was provided, or pkg-config failed to produce a result + AS_IF([test "x$PG_CONFIG" == "x"], [ + AC_PATH_PROG([PG_CONFIG], [pg_config]) + ]) + AS_IF([test "x$PG_CONFIG" == "x"], [ + AC_MSG_ERROR([Can not find pg_config, use --with-pg-config to specify the path to pg_config]) + ]) + PGSQL_LIBS="-L$($PG_CONFIG --libdir) -lpq" + PGSQL_CFLAGS="-I$($PG_CONFIG --includedir)" + ]) + AC_SUBST([PGSQL_LIBS]) + AC_SUBST([PGSQL_CFLAGS]) +]) diff --git a/m4/pdns_with_protobuf.m4 b/m4/pdns_with_protobuf.m4 new file mode 100644 index 0000000..f106c58 --- /dev/null +++ b/m4/pdns_with_protobuf.m4 @@ -0,0 +1,27 @@ +AC_DEFUN([PDNS_WITH_PROTOBUF], [ + AC_MSG_CHECKING([if we need to link in protobuf]) + AC_ARG_WITH([protobuf], + AS_HELP_STRING([--with-protobuf],[enable protobuf support @<:@default=auto@:>@]), + [with_protobuf=$withval], + [with_protobuf=auto], + ) + AC_MSG_RESULT([$with_protobuf]) + + AS_IF([test "x$with_protobuf" != "xno"], [ + AS_IF([test "x$with_protobuf" = "xyes" -o "x$with_protobuf" = "xauto"], [ + PKG_CHECK_MODULES([PROTOBUF], [protobuf], [ : ], [ : ]) + AC_CHECK_PROG([PROTOC], [protoc], [protoc]) + ]) + ]) + AS_IF([test "x$with_protobuf" = "xyes"], [ + AS_IF([test x"$PROTOBUF_LIBS" = "x"], [ + AC_MSG_ERROR([Protobuf requested but libraries were not found]) + ]) + AS_IF([test x"$PROTOC" = "x"], [ + AC_MSG_ERROR([Protobuf requested but the protobuf compiler was not found]) + ]) + ]) + AM_CONDITIONAL([HAVE_PROTOBUF], [test x"$PROTOBUF_LIBS" != "x"]) + AM_CONDITIONAL([HAVE_PROTOC], [test x"$PROTOC" != "x"]) + AS_IF([test x"$PROTOBUF_LIBS" != "x"], [AC_DEFINE([HAVE_PROTOBUF], [1], [Define if using protobuf.])]) +]) diff --git a/m4/pdns_with_sqlite3.m4 b/m4/pdns_with_sqlite3.m4 new file mode 100644 index 0000000..952ad10 --- /dev/null +++ b/m4/pdns_with_sqlite3.m4 @@ -0,0 +1,13 @@ +AC_DEFUN([PDNS_WITH_SQLITE3], [ + AC_MSG_CHECKING([whether user requires sqlite3]) + AC_ARG_WITH([sqlite3], + [AS_HELP_STRING([--with-sqlite3],[include sqlite3 driver @<:@default=no@:>@])], + [with_sqlite3=$withval], + [with_sqlite3=no] + ) + AC_MSG_RESULT([$with_sqlite3]) + + AS_IF([test "x$with_sqlite3" != "xno"], [ + needsqlite3=yes + ]) +]) diff --git a/m4/pdns_with_unixodbc.m4 b/m4/pdns_with_unixodbc.m4 new file mode 100644 index 0000000..95c26c9 --- /dev/null +++ b/m4/pdns_with_unixodbc.m4 @@ -0,0 +1,106 @@ +AC_DEFUN([PDNS_WITH_UNIXODBC],[ + AC_ARG_WITH([unixodbc], + [AS_HELP_STRING([--with-unixodbc=], [root directory path of unixODBC installation])], + [ + UNIXODBC_LIBS_check="$withval/lib/unixodbc $with_unixodbc/lib" + UNIXODBC_CFLAGS_check="$withval/include/unixodbc" + UNIXODBC_config_check="$withval/bin/odbc_config" + ], + [ + UNIXODBC_LIBS_check="/usr/local/unixodbc/lib/unixodbc /usr/local/lib/unixodbc /opt/unixodbc/lib/unixodbc \ + /usr/lib/unixodbc /usr/lib64/unixodbc /usr/local/unixodbc/lib /usr/local/lib /opt/unixodbc/lib /usr/lib \ + /usr/sfw/lib/ /usr/lib/odbc /usr/lib/x86_64-linux-gnu $full_libdir" + UNIXODBC_CFLAGS_check="/usr/local/unixodbc/include/unixodbc /usr/local/include/unixodbc \ + /opt/unixodbc/include/unixodbc /opt/unixodbc/include /usr/include/unixodbc /usr/sfw/include/unixodbc \ + /usr/include /usr/local/include" + ] + ) + + AC_ARG_WITH([odbc-config], + [AS_HELP_STRING([--with-odbc-config=], [file path to odbc_config])], + [UNIXODBC_config_check=$withval] + ) + + AC_ARG_WITH([unixodbc-lib], + [AS_HELP_STRING([--with-unixodbc-lib=], [directory path of unixODBC library installation])], + [ + UNIXODBC_LIBS_check="$withval/lib/unixodbc $withval/unixodbc $withval" + UNIXODBC_config_check="skip" + ] + ) + + AC_ARG_WITH([unixodbc-includes], + [AS_HELP_STRING([--with-unixodbc-includes=], [directory path of unixODBC header installation])], + [ + UNIXODBC_CFLAGS_check="$withval/include/unixodbc $withval/unixodbc $withval" + UNIXODBC_config_check="skip" + ] + ) + + UNIXODBC_config="" + if test "x$UNIXODBC_config_check" != "xskip"; then + if test "x$UNIXODBC_config_check" = "x"; then + AC_PATH_PROG([UNIXODBC_config], [odbc_config]) + else + AC_MSG_CHECKING([for $UNIXODBC_config_check]) + if test -x $UNIXODBC_config_check; then + UNIXODBC_config="$UNIXODBC_config_check" + AC_MSG_RESULT([yes]) + else + UNIXODBC_config="" + AC_MSG_ERROR([not found]) + fi + fi + fi + + if test "x$UNIXODBC_config" != "x"; then + # use this to configure everything + UNIXODBC_LIBS=`$UNIXODBC_config --libs` + UNIXODBC_CFLAGS=-I`$UNIXODBC_config --include-prefix` + else + AC_MSG_CHECKING([for unixODBC library directory]) + UNIXODBC_libdir= + for m in $UNIXODBC_LIBS_check; do + if test -d "$m" && \ + (test -f "$m/libodbc.so" || test -f "$m/libodbc.a") + then + UNIXODBC_libdir=$m + break + fi + done + if test -z "$UNIXODBC_libdir"; then + AC_MSG_ERROR([Did not find the unixodbc library dir in '$UNIXODBC_LIBS_check']) + fi + case "$UNIXODBC_libdir" in + /*) UNIXODBC_LIBS="-L$UNIXODBC_libdir -lodbc" + ;; + *) AC_MSG_ERROR([The unixODBC library directory ($UNIXODBC_libdir) must be an absolute path.]) + ;; + esac + AC_MSG_RESULT([$UNIXODBC_libdir]) + + AC_MSG_CHECKING([for unixODBC include directory]) + UNIXODBC_CFLAGS= + for m in $UNIXODBC_CFLAGS_check; do + if test -d "$m" && test -f "$m/sql.h" + then + UNIXODBC_CFLAGS="$m" + break + fi + done + if test -z "$UNIXODBC_CFLAGS"; then + AC_MSG_ERROR([Did not find the unixodbc include dir in '$UNIXODBC_CFLAGS_check']) + fi + + case "$UNIXODBC_CFLAGS" in + /*) AC_MSG_RESULT($UNIXODBC_CFLAGS) + ;; + *) AC_MSG_ERROR([The unixODBC include directory ($UNIXODBC_CFLAGS) must be an absolute path.]) + ;; + esac + UNIXODBC_CFLAGS="-I$UNIXODBC_CFLAGS" + fi + + AC_SUBST(UNIXODBC_CFLAGS) + AC_SUBST(UNIXODBC_LIBS) +]) diff --git a/m4/systemd.m4 b/m4/systemd.m4 new file mode 100644 index 0000000..be2bf7b --- /dev/null +++ b/m4/systemd.m4 @@ -0,0 +1,197 @@ +# systemd.m4 - Macros to check for and enable systemd -*- Autoconf -*- +# +# Copyright (C) 2014 Luis R. Rodriguez +# Copyright (C) 2016 Pieter Lexis +# +# This program 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 2 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#serial 2 + +dnl Some optional path options +AC_DEFUN([AX_SYSTEMD_OPTIONS], [ + AC_ARG_WITH(systemd, [ --with-systemd set directory for systemd service files], + SYSTEMD_DIR="$withval", SYSTEMD_DIR="") + AC_SUBST(SYSTEMD_DIR) + + AC_ARG_WITH(systemd, [ --with-systemd-modules-load set directory for systemd modules load files], + SYSTEMD_MODULES_LOAD="$withval", SYSTEMD_MODULES_LOAD="") + AC_SUBST(SYSTEMD_MODULES_LOAD) +]) + +AC_DEFUN([AX_ENABLE_SYSTEMD_OPTS], [ + AX_ARG_DEFAULT_ENABLE([systemd], [Disable systemd support]) + AX_SYSTEMD_OPTIONS() +]) + +AC_DEFUN([AX_ALLOW_SYSTEMD_OPTS], [ + AX_ARG_DEFAULT_DISABLE([systemd], [Enable systemd support], [$1]) + AX_SYSTEMD_OPTIONS() +]) + +AC_DEFUN([AX_CHECK_SYSTEMD_LIBS], [ + AC_REQUIRE([AX_CHECK_SYSTEMD_DETECT_AND_ENABLE]) + AS_IF([test "x$libsystemd" = x], [ + AC_MSG_ERROR([Unable to find a suitable libsystemd library]) + ]) + + PKG_CHECK_MODULES([SYSTEMD], [$libsystemd_daemon]) + dnl pkg-config older than 0.24 does not set these for + dnl PKG_CHECK_MODULES() worth also noting is that as of version 208 + dnl of systemd pkg-config --cflags currently yields no extra flags yet. + AC_SUBST([SYSTEMD_CFLAGS]) + AC_SUBST([SYSTEMD_LIBS]) + + AS_IF([test "x$SYSTEMD_DIR" = x], [ + dnl In order to use the line below we need to fix upstream systemd + dnl to properly ${prefix} for child variables in + dnl src/core/systemd.pc.in but this is a bit complex at the + dnl moment as they depend on another rootprefix, which can vary + dnl from prefix in practice. We provide our own definition as we + dnl *know* where systemd will dump this to, but this does limit + dnl us to stick to a non custom systemdsystemunitdir, dnl to work + dnl around this we provide the additional configure option + dnl --with-systemd where you can specify the directory for the unit + dnl files. It would also be best to just extend the upstream + dnl pkg-config pkg.m4 with an AC_DEFUN() to do this neatly. + dnl SYSTEMD_DIR="`$PKG_CONFIG --define-variable=prefix=$PREFIX --variable=systemdsystemunitdir systemd`" + SYSTEMD_DIR="\$(prefix)/lib/systemd/system/" + ], []) + + AS_IF([test "x$SYSTEMD_DIR" = x], [ + AC_MSG_ERROR([SYSTEMD_DIR is unset]) + ], []) + + dnl There is no variable for this yet for some reason + AS_IF([test "x$SYSTEMD_MODULES_LOAD" = x], [ + SYSTEMD_MODULES_LOAD="\$(prefix)/lib/modules-load.d/" + ], []) + + AS_IF([test "x$SYSTEMD_MODULES_LOAD" = x], [ + AC_MSG_ERROR([SYSTEMD_MODULES_LOAD is unset]) + ], []) +]) + +AC_DEFUN([AX_CHECK_SYSTEMD], [ + dnl Respect user override to disable + AS_IF([test "x$enable_systemd" != "xno"], [ + AS_IF([test "x$systemd" = "xy" ], [ + AC_DEFINE([HAVE_SYSTEMD], [1], [Systemd available and enabled]) + systemd=y + AX_CHECK_SYSTEMD_LIBS() + ],[systemd=n]) + ],[systemd=n]) +]) + +AC_DEFUN([AX_CHECK_SYSTEMD_DETECT_AND_ENABLE], [ + AC_CHECK_HEADER([systemd/sd-daemon.h], [ + for libname in systemd-daemon systemd; do + AC_CHECK_LIB([$libname], [sd_listen_fds], [ + libsystemd_daemon="lib$libname" + systemd=y + libsystemd=y + ]) + done + ]) +]) + +dnl Enables systemd by default and requires a --disable-systemd option flag +dnl to configure if you want to disable. +AC_DEFUN([AX_ENABLE_SYSTEMD], [ + AX_ENABLE_SYSTEMD_OPTS() + AX_CHECK_SYSTEMD() +]) + +dnl Systemd will be disabled by default and requires you to run configure with +dnl --enable-systemd to look for and enable systemd. +AC_DEFUN([AX_ALLOW_SYSTEMD], [ + AX_ALLOW_SYSTEMD_OPTS() + AX_CHECK_SYSTEMD() +]) + +dnl Systemd will be disabled by default but if your build system is detected +dnl to have systemd build libraries it will be enabled. You can always force +dnl disable with --disable-systemd +AC_DEFUN([AX_AVAILABLE_SYSTEMD], [ + AX_ALLOW_SYSTEMD_OPTS([, but will be enabled when libraries are found]) + AX_CHECK_SYSTEMD_DETECT_AND_ENABLE() + AX_CHECK_SYSTEMD() +]) + +AC_DEFUN([AX_CHECK_SYSTEMD_FEATURES], [ + AS_IF([test x"$systemd" = "xy"], [ + AC_PATH_PROG([SYSTEMCTL], [systemctl], [no]) + AS_IF([test "$SYSTEMCTL" = "no"], + [AC_MSG_ERROR([systemctl not found])], [ + _systemd_version=`${SYSTEMCTL} --version|head -1 |cut -d" " -f 2` + if test $_systemd_version -ge 183; then + systemd_private_tmp=y + fi + if test $_systemd_version -ge 209; then + systemd_system_call_architectures=y + systemd_private_devices=y + fi + if test $_systemd_version -ge 211; then + systemd_restrict_address_families=y + fi + if test $_systemd_version -ge 214; then + systemd_protect_system=y + systemd_protect_home=y + fi + if test $_systemd_version -ge 231; then + systemd_restrict_realtime=y + systemd_memory_deny_write_execute=y + fi + if test $_systemd_version -ge 232; then + systemd_protect_control_groups=y + systemd_protect_kernel_modules=y + systemd_protect_kernel_tunables=y + systemd_remove_ipc=y + systemd_dynamic_user=y + systemd_private_users=y + systemd_protect_system_strict=y + fi + if test $_systemd_version -ge 233; then + systemd_restrict_namespaces=y + fi + if test $_systemd_version -ge 235; then + systemd_lock_personality=y + # while SystemCallFilter is technically available starting with 187, + # we use the pre-defined call filter sets that have been introduced later. + # Initial support for these landed in 231 + # @filesystem @reboot @swap in 233 + # @aio, @sync, @chown, @setuid, @memlock, @signal and @timer in 235 + systemd_system_call_filter=y + fi + ]) + ]) + AM_CONDITIONAL([HAVE_SYSTEMD_DYNAMIC_USER], [ test x"$systemd_dynamic_user" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_LOCK_PERSONALITY], [ test x"$systemd_lock_personality" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_MEMORY_DENY_WRITE_EXECUTE], [ test x"$systemd_memory_deny_write_execute" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PRIVATE_DEVICES], [ test x"$systemd_private_devices" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PRIVATE_TMP], [ test x"$systemd_private_tmp" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PRIVATE_USERS], [ test x"$systemd_private_users" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS], [ test x"$systemd_protect_control_groups" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_HOME], [ test x"$systemd_protect_home" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_KERNEL_MODULES], [ test x"$systemd_protect_kernel_modules" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES], [ test x"$systemd_protect_kernel_tunables" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_SYSTEM], [ test x"$systemd_protect_system" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_PROTECT_SYSTEM_STRICT], [ test x"$systemd_protect_system_strict" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_REMOVE_IPC], [ test x"$systemd_remove_ipc" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES], [ test x"$systemd_restrict_address_families" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_RESTRICT_NAMESPACES], [ test x"$systemd_restrict_namespaces" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_RESTRICT_REALTIME], [ test x"$systemd_restrict_realtime" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES], [ test x"$systemd_system_call_architectures" = "xy" ]) + AM_CONDITIONAL([HAVE_SYSTEMD_SYSTEM_CALL_FILTER], [ test x"$systemd_system_call_filter" = "xy" ]) +]) diff --git a/m4/tm-gmtoff.m4 b/m4/tm-gmtoff.m4 new file mode 100644 index 0000000..e265585 --- /dev/null +++ b/m4/tm-gmtoff.m4 @@ -0,0 +1,14 @@ +dnl Check for the tm_gmtoff field in struct tm +dnl (Borrowed from the Gaim project) +dnl The Gaim Project (now know as Pidgin) is licensed under the GPLv2 + +AC_DEFUN([MC_TM_GMTOFF], +[AC_REQUIRE([AC_STRUCT_TM])dnl +AC_CACHE_CHECK([for tm_gmtoff in struct tm], ac_cv_struct_tm_gmtoff, +[AC_TRY_COMPILE([#include +#include <$ac_cv_struct_tm>], [struct tm tm; tm.tm_gmtoff;], + ac_cv_struct_tm_gmtoff=yes, ac_cv_struct_tm_gmtoff=no)]) +if test "$ac_cv_struct_tm_gmtoff" = yes; then + AC_DEFINE(HAVE_TM_GMTOFF, 1, [tm_gmtoff is available.]) +fi +]) diff --git a/m4/warnings.m4 b/m4/warnings.m4 new file mode 100644 index 0000000..5ae01de --- /dev/null +++ b/m4/warnings.m4 @@ -0,0 +1,79 @@ +# warnings.m4 serial 11 +dnl Copyright (C) 2008-2015 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Simon Josefsson + +# gl_AS_VAR_APPEND(VAR, VALUE) +# ---------------------------- +# Provide the functionality of AS_VAR_APPEND if Autoconf does not have it. +m4_ifdef([AS_VAR_APPEND], +[m4_copy([AS_VAR_APPEND], [gl_AS_VAR_APPEND])], +[m4_define([gl_AS_VAR_APPEND], +[AS_VAR_SET([$1], [AS_VAR_GET([$1])$2])])]) + + +# gl_COMPILER_OPTION_IF(OPTION, [IF-SUPPORTED], [IF-NOT-SUPPORTED], +# [PROGRAM = AC_LANG_PROGRAM()]) +# ----------------------------------------------------------------- +# Check if the compiler supports OPTION when compiling PROGRAM. +# +# FIXME: gl_Warn must be used unquoted until we can assume Autoconf +# 2.64 or newer. +AC_DEFUN([gl_COMPILER_OPTION_IF], +[AS_VAR_PUSHDEF([gl_Warn], [gl_cv_warn_[]_AC_LANG_ABBREV[]_$1])dnl +AS_VAR_PUSHDEF([gl_Flags], [_AC_LANG_PREFIX[]FLAGS])dnl +AS_LITERAL_IF([$1], + [m4_pushdef([gl_Positive], m4_bpatsubst([$1], [^-Wno-], [-W]))], + [gl_positive="$1" +case $gl_positive in + -Wno-*) gl_positive=-W`expr "X$gl_positive" : 'X-Wno-\(.*\)'` ;; +esac +m4_pushdef([gl_Positive], [$gl_positive])])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler handles $1], m4_defn([gl_Warn]), [ + gl_save_compiler_FLAGS="$gl_Flags" + gl_AS_VAR_APPEND(m4_defn([gl_Flags]), + [" $gl_unknown_warnings_are_errors ]m4_defn([gl_Positive])["]) + AC_LINK_IFELSE([m4_default([$4], [AC_LANG_PROGRAM([])])], + [AS_VAR_SET(gl_Warn, [yes])], + [AS_VAR_SET(gl_Warn, [no])]) + gl_Flags="$gl_save_compiler_FLAGS" +]) +AS_VAR_IF(gl_Warn, [yes], [$2], [$3]) +m4_popdef([gl_Positive])dnl +AS_VAR_POPDEF([gl_Flags])dnl +AS_VAR_POPDEF([gl_Warn])dnl +]) + +# gl_UNKNOWN_WARNINGS_ARE_ERRORS +# ------------------------------ +# Clang doesn't complain about unknown warning options unless one also +# specifies -Wunknown-warning-option -Werror. Detect this. +AC_DEFUN([gl_UNKNOWN_WARNINGS_ARE_ERRORS], +[gl_COMPILER_OPTION_IF([-Werror -Wunknown-warning-option], + [gl_unknown_warnings_are_errors='-Wunknown-warning-option -Werror'], + [gl_unknown_warnings_are_errors=])]) + +# gl_WARN_ADD(OPTION, [VARIABLE = WARN_CFLAGS], +# [PROGRAM = AC_LANG_PROGRAM()]) +# --------------------------------------------- +# Adds parameter to WARN_CFLAGS if the compiler supports it when +# compiling PROGRAM. For example, gl_WARN_ADD([-Wparentheses]). +# +# If VARIABLE is a variable name, AC_SUBST it. +AC_DEFUN([gl_WARN_ADD], +[AC_REQUIRE([gl_UNKNOWN_WARNINGS_ARE_ERRORS]) +gl_COMPILER_OPTION_IF([$1], + [gl_AS_VAR_APPEND(m4_if([$2], [], [[WARN_CFLAGS]], [[$2]]), [" $1"])], + [], + [$3]) +m4_ifval([$2], + [AS_LITERAL_IF([$2], [AC_SUBST([$2])])], + [AC_SUBST([WARN_CFLAGS])])dnl +]) + +# Local Variables: +# mode: autoconf +# End: diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 0000000..65887fb --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS= @moduledirs@ + +DIST_SUBDIRS = \ + bindbackend \ + geoipbackend \ + gmysqlbackend \ + godbcbackend \ + goraclebackend \ + gpgsqlbackend \ + gsqlite3backend \ + ldapbackend \ + lmdbbackend \ + luabackend \ + lua2backend \ + mydnsbackend \ + opendbxbackend \ + oraclebackend \ + pipebackend \ + randombackend \ + remotebackend \ + tinydnsbackend diff --git a/modules/Makefile.in b/modules/Makefile.in new file mode 100644 index 0000000..67effd6 --- /dev/null +++ b/modules/Makefile.in @@ -0,0 +1,792 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-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 +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = @moduledirs@ +DIST_SUBDIRS = \ + bindbackend \ + geoipbackend \ + gmysqlbackend \ + godbcbackend \ + goraclebackend \ + gpgsqlbackend \ + gsqlite3backend \ + ldapbackend \ + lmdbbackend \ + luabackend \ + lua2backend \ + mydnsbackend \ + opendbxbackend \ + oraclebackend \ + pipebackend \ + randombackend \ + remotebackend \ + tinydnsbackend + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || 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; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/bindbackend/Makefile.am b/modules/bindbackend/Makefile.am new file mode 100644 index 0000000..aaf88be --- /dev/null +++ b/modules/bindbackend/Makefile.am @@ -0,0 +1,25 @@ +pkglib_LTLIBRARIES = libbindbackend.la +AM_CPPFLAGS += -I../../pdns + +AM_LFLAGS = -i +AM_YFLAGS = -d --verbose --debug + +BUILT_SOURCES = \ + ../../pdns/bind-dnssec.schema.sqlite3.sql.h \ + ../../pdns/bindlexer.l \ + ../../pdns/bindparser.yy + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +libbindbackend_la_SOURCES = \ + bindbackend2.cc bindbackend2.hh \ + binddnssec.cc + +libbindbackend_la_LDFLAGS = -module -avoid-version + +../../pdns/bind-dnssec.schema.sqlite3.sql.h: ../../pdns/bind-dnssec.schema.sqlite3.sql + ( echo 'static char sqlCreate[] __attribute__((unused))=' ; sed 's/$$/"/g' $< | sed 's/^/"/g' ; echo ';' ) > $@ + +# for bindparser.h/hh +.hh.h: + cp $< $@ diff --git a/modules/bindbackend/Makefile.in b/modules/bindbackend/Makefile.in new file mode 100644 index 0000000..ae88cc3 --- /dev/null +++ b/modules/bindbackend/Makefile.in @@ -0,0 +1,846 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/bindbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +libbindbackend_la_LIBADD = +am_libbindbackend_la_OBJECTS = bindbackend2.lo binddnssec.lo +libbindbackend_la_OBJECTS = $(am_libbindbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libbindbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libbindbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libbindbackend_la_SOURCES) +DIST_SOURCES = $(libbindbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ -I../../pdns +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libbindbackend.la +AM_LFLAGS = -i +AM_YFLAGS = -d --verbose --debug +BUILT_SOURCES = \ + ../../pdns/bind-dnssec.schema.sqlite3.sql.h \ + ../../pdns/bindlexer.l \ + ../../pdns/bindparser.yy + +EXTRA_DIST = OBJECTFILES OBJECTLIBS +libbindbackend_la_SOURCES = \ + bindbackend2.cc bindbackend2.hh \ + binddnssec.cc + +libbindbackend_la_LDFLAGS = -module -avoid-version +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .h .hh .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/bindbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/bindbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libbindbackend.la: $(libbindbackend_la_OBJECTS) $(libbindbackend_la_DEPENDENCIES) $(EXTRA_libbindbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libbindbackend_la_LINK) -rpath $(pkglibdir) $(libbindbackend_la_OBJECTS) $(libbindbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bindbackend2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binddnssec.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +../../pdns/bind-dnssec.schema.sqlite3.sql.h: ../../pdns/bind-dnssec.schema.sqlite3.sql + ( echo 'static char sqlCreate[] __attribute__((unused))=' ; sed 's/$$/"/g' $< | sed 's/^/"/g' ; echo ';' ) > $@ + +# for bindparser.h/hh +.hh.h: + cp $< $@ + +# 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. +.NOEXPORT: diff --git a/modules/bindbackend/OBJECTFILES b/modules/bindbackend/OBJECTFILES new file mode 100644 index 0000000..e76b376 --- /dev/null +++ b/modules/bindbackend/OBJECTFILES @@ -0,0 +1 @@ +bindbackend2.lo binddnssec.lo diff --git a/modules/bindbackend/OBJECTLIBS b/modules/bindbackend/OBJECTLIBS new file mode 100644 index 0000000..e69de29 diff --git a/modules/bindbackend/bindbackend2.cc b/modules/bindbackend/bindbackend2.cc new file mode 100644 index 0000000..de0f6c4 --- /dev/null +++ b/modules/bindbackend/bindbackend2.cc @@ -0,0 +1,1424 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pdns/dnsseckeeper.hh" +#include "pdns/dnssecinfra.hh" +#include "pdns/base32.hh" +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "bindbackend2.hh" +#include "pdns/dnspacket.hh" +#include "pdns/zoneparser-tng.hh" +#include "pdns/bindparserclasses.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/qtype.hh" +#include "pdns/misc.hh" +#include "pdns/dynlistener.hh" +#include "pdns/lock.hh" +#include "pdns/namespaces.hh" + +/* + All instances of this backend share one s_state, which is indexed by zone name and zone id. + The s_state is protected by a read/write lock, and the goal it to only interact with it briefly. + When a query comes in, we take a read lock and COPY the best zone to answer from s_state (BB2DomainInfo object) + All answers are served from this copy. + + To interact with s_state, use safeGetBBDomainInfo (search on name or id), safePutBBDomainInfo (to update) + or safeRemoveBBDomainInfo. These all lock as they should. + + Several functions need to traverse s_state to get data for the rest of PowerDNS. When doing so, + you need to manually take the s_state_lock (read). + + Parsing zones happens with parseZone(), which fills a BB2DomainInfo object. This can then be stored with safePutBBDomainInfo. + + Finally, the BB2DomainInfo contains all records as a LookButDontTouch object. This makes sure you only look, but don't touch, since + the records might be in use in other places. +*/ + +Bind2Backend::state_t Bind2Backend::s_state; +int Bind2Backend::s_first=1; +bool Bind2Backend::s_ignore_broken_records=false; + +pthread_rwlock_t Bind2Backend::s_state_lock=PTHREAD_RWLOCK_INITIALIZER; +pthread_mutex_t Bind2Backend::s_supermaster_config_lock=PTHREAD_MUTEX_INITIALIZER; // protects writes to config file +pthread_mutex_t Bind2Backend::s_startup_lock=PTHREAD_MUTEX_INITIALIZER; +string Bind2Backend::s_binddirectory; + +BB2DomainInfo::BB2DomainInfo() +{ + d_loaded=false; + d_lastcheck=0; + d_checknow=false; + d_status="Unknown"; +} + +void BB2DomainInfo::setCheckInterval(time_t seconds) +{ + d_checkinterval=seconds; +} + +bool BB2DomainInfo::current() +{ + if(d_checknow) { + return false; + } + + if(!d_checkinterval) + return true; + + if(time(0) - d_lastcheck < d_checkinterval) + return true; + + if(d_filename.empty()) + return true; + + return (getCtime()==d_ctime); +} + +time_t BB2DomainInfo::getCtime() +{ + struct stat buf; + + if(d_filename.empty() || stat(d_filename.c_str(),&buf)<0) + return 0; + d_lastcheck=time(0); + return buf.st_ctime; +} + +void BB2DomainInfo::setCtime() +{ + struct stat buf; + if(stat(d_filename.c_str(),&buf)<0) + return; + d_ctime=buf.st_ctime; +} + +bool Bind2Backend::safeGetBBDomainInfo(int id, BB2DomainInfo* bbd) +{ + ReadLock rl(&s_state_lock); + state_t::const_iterator iter = s_state.find(id); + if(iter == s_state.end()) + return false; + *bbd=*iter; + return true; +} + +bool Bind2Backend::safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd) +{ + ReadLock rl(&s_state_lock); + typedef state_t::index::type nameindex_t; + nameindex_t& nameindex = boost::multi_index::get(s_state); + + nameindex_t::const_iterator iter = nameindex.find(name); + if(iter == nameindex.end()) + return false; + *bbd=*iter; + return true; +} + +bool Bind2Backend::safeRemoveBBDomainInfo(const DNSName& name) +{ + WriteLock rl(&s_state_lock); + typedef state_t::index::type nameindex_t; + nameindex_t& nameindex = boost::multi_index::get(s_state); + + nameindex_t::iterator iter = nameindex.find(name); + if(iter == nameindex.end()) + return false; + nameindex.erase(iter); + return true; +} + +void Bind2Backend::safePutBBDomainInfo(const BB2DomainInfo& bbd) +{ + WriteLock rl(&s_state_lock); + replacing_insert(s_state, bbd); +} + +void Bind2Backend::setNotified(uint32_t id, uint32_t serial) +{ + BB2DomainInfo bbd; + if (!safeGetBBDomainInfo(id, &bbd)) + return; + bbd.d_lastnotified = serial; + safePutBBDomainInfo(bbd); +} + +void Bind2Backend::setFresh(uint32_t domain_id) +{ + BB2DomainInfo bbd; + if(safeGetBBDomainInfo(domain_id, &bbd)) { + bbd.d_lastcheck=time(0); + safePutBBDomainInfo(bbd); + } +} + +bool Bind2Backend::startTransaction(const DNSName &qname, int id) +{ + if(id < 0) { + d_transaction_tmpname.clear(); + d_transaction_id=id; + return false; + } + if(id == 0) { + throw DBException("domain_id 0 is invalid for this backend."); + } + + d_transaction_id=id; + BB2DomainInfo bbd; + if(safeGetBBDomainInfo(id, &bbd)) { + d_transaction_tmpname = bbd.d_filename + "XXXXXX"; + int fd = mkstemp(&d_transaction_tmpname.at(0)); + if (fd == -1) { + throw DBException("Unable to create a unique temporary zonefile '"+d_transaction_tmpname+"': "+stringerror()); + return false; + } + + d_of = std::unique_ptr(new ofstream(d_transaction_tmpname.c_str())); + if(!*d_of) { + unlink(d_transaction_tmpname.c_str()); + close(fd); + fd = -1; + d_of.reset(); + throw DBException("Unable to open temporary zonefile '"+d_transaction_tmpname+"': "+stringerror()); + } + close(fd); + fd = -1; + + *d_of<<"; Written by PowerDNS, don't edit!"<0 = actual transaction + if(d_transaction_id > 0) { + unlink(d_transaction_tmpname.c_str()); + d_of.reset(); + d_transaction_id=0; + } + + return true; +} + +bool Bind2Backend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3) +{ + BB2DomainInfo bbd; + if (!safeGetBBDomainInfo(d_transaction_id, &bbd)) + return false; + + string qname; + string name = bbd.d_name.toString(); + if (bbd.d_name.empty()) { + qname = rr.qname.toString(); + } + else if (rr.qname.isPartOf(bbd.d_name)) { + if (rr.qname == bbd.d_name) { + qname = "@"; + } + else { + DNSName relName = rr.qname.makeRelative(bbd.d_name); + qname = relName.toStringNoDot(); + } + } + else { + throw DBException("out-of-zone data '"+rr.qname.toLogString()+"' during AXFR of zone '"+bbd.d_name.toLogString()+"'"); + } + + shared_ptr drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); + string content = drc->getZoneRepresentation(); + + // SOA needs stripping too! XXX FIXME - also, this should not be here I think + switch(rr.qtype.getCode()) { + case QType::MX: + case QType::SRV: + case QType::CNAME: + case QType::DNAME: + case QType::NS: + stripDomainSuffix(&content, name); + // fallthrough + default: + if (d_of && *d_of) { + *d_of< *changedDomains) +{ + vector consider; + { + ReadLock rl(&s_state_lock); + + for(state_t::const_iterator i = s_state.begin(); i != s_state.end() ; ++i) { + if(i->d_kind != DomainInfo::Master && this->alsoNotify.empty() && i->d_also_notify.empty()) + continue; + + DomainInfo di; + di.id=i->d_id; + di.zone=i->d_name; + di.last_check=i->d_lastcheck; + di.notified_serial=i->d_lastnotified; + di.backend=this; + di.kind=DomainInfo::Master; + consider.push_back(di); + } + } + + SOAData soadata; + for(DomainInfo& di : consider) { + soadata.serial=0; + try { + this->getSOA(di.zone, soadata); // we might not *have* a SOA yet, but this might trigger a load of it + } + catch(...) { + continue; + } + if(di.notified_serial != soadata.serial) { + BB2DomainInfo bbd; + if(safeGetBBDomainInfo(di.id, &bbd)) { + bbd.d_lastnotified=soadata.serial; + safePutBBDomainInfo(bbd); + } + if(di.notified_serial) { // don't do notification storm on startup + di.serial=soadata.serial; + changedDomains->push_back(di); + } + } + } +} + +void Bind2Backend::getAllDomains(vector *domains, bool include_disabled) +{ + SOAData soadata; + + // prevent deadlock by using getSOA() later on + { + ReadLock rl(&s_state_lock); + + for(state_t::const_iterator i = s_state.begin(); i != s_state.end() ; ++i) { + DomainInfo di; + di.id=i->d_id; + di.zone=i->d_name; + di.last_check=i->d_lastcheck; + di.kind=i->d_kind; + di.masters=i->d_masters; + di.backend=this; + domains->push_back(di); + }; + } + + for(DomainInfo &di : *domains) { + // do not corrupt di if domain supplied by another backend. + if (di.backend != this) + continue; + try { + this->getSOA(di.zone, soadata); + } catch(...) { + continue; + } + di.serial=soadata.serial; + } +} + +void Bind2Backend::getUnfreshSlaveInfos(vector *unfreshDomains) +{ + vector domains; + { + ReadLock rl(&s_state_lock); + for(state_t::const_iterator i = s_state.begin(); i != s_state.end() ; ++i) { + if(i->d_kind != DomainInfo::Slave) + continue; + DomainInfo sd; + sd.id=i->d_id; + sd.zone=i->d_name; + sd.masters=i->d_masters; + sd.last_check=i->d_lastcheck; + sd.backend=this; + sd.kind=DomainInfo::Slave; + domains.push_back(sd); + } + } + + for(DomainInfo &sd : domains) { + SOAData soadata; + soadata.refresh=0; + soadata.serial=0; + try { + getSOA(sd.zone,soadata); // we might not *have* a SOA yet + } + catch(...){} + sd.serial=soadata.serial; + if(sd.last_check+soadata.refresh < (unsigned int)time(0)) + unfreshDomains->push_back(sd); + } +} + +bool Bind2Backend::getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial) +{ + BB2DomainInfo bbd; + if(!safeGetBBDomainInfo(domain, &bbd)) + return false; + + di.id=bbd.d_id; + di.zone=domain; + di.masters=bbd.d_masters; + di.last_check=bbd.d_lastcheck; + di.backend=this; + di.kind=bbd.d_kind; + di.serial=0; + if(getSerial) { + try { + SOAData sd; + sd.serial=0; + + getSOA(bbd.d_name,sd); // we might not *have* a SOA yet + di.serial=sd.serial; + } + catch(...){} + } + + return true; +} + +void Bind2Backend::alsoNotifies(const DNSName& domain, set *ips) +{ + // combine global list with local list + for(set::iterator i = this->alsoNotify.begin(); i != this->alsoNotify.end(); i++) { + (*ips).insert(*i); + } + // check metadata too if available + vector meta; + if (getDomainMetadata(domain, "ALSO-NOTIFY", meta)) { + for(const auto& str: meta) { + (*ips).insert(str); + } + } + ReadLock rl(&s_state_lock); + for(state_t::const_iterator i = s_state.begin(); i != s_state.end() ; ++i) { + if(i->d_name == domain) { + for(set::iterator it = i->d_also_notify.begin(); it != i->d_also_notify.end(); it++) { + (*ips).insert(*it); + } + return; + } + } +} + +// only parses, does NOT add to s_state! +void Bind2Backend::parseZoneFile(BB2DomainInfo *bbd) +{ + NSEC3PARAMRecordContent ns3pr; + bool nsec3zone; + if (d_hybrid) { + DNSSECKeeper dk; + nsec3zone=dk.getNSEC3PARAM(bbd->d_name, &ns3pr); + } else + nsec3zone=getNSEC3PARAM(bbd->d_name, &ns3pr); + + bbd->d_records = shared_ptr(new recordstorage_t()); + + ZoneParserTNG zpt(bbd->d_filename, bbd->d_name, s_binddirectory); + DNSResourceRecord rr; + string hashed; + while(zpt.get(rr)) { + if(rr.qtype.getCode() == QType::NSEC || rr.qtype.getCode() == QType::NSEC3 || rr.qtype.getCode() == QType::NSEC3PARAM) + continue; // we synthesise NSECs on demand + + insertRecord(*bbd, rr.qname, rr.qtype, rr.content, rr.ttl, ""); + } + fixupOrderAndAuth(*bbd, nsec3zone, ns3pr); + doEmptyNonTerminals(*bbd, nsec3zone, ns3pr); + bbd->setCtime(); + bbd->d_loaded=true; + bbd->d_checknow=false; + bbd->d_status="parsed into memory at "+nowTime(); +} + +/** THIS IS AN INTERNAL FUNCTION! It does moadnsparser prio impedance matching + Much of the complication is due to the efforts to benefit from std::string reference counting copy on write semantics */ +void Bind2Backend::insertRecord(BB2DomainInfo& bb2, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed, bool *auth) +{ + Bind2DNSRecord bdr; + shared_ptr records = bb2.d_records.getWRITABLE(); + bdr.qname=qname; + + if(bb2.d_name.empty()) + ; + else if(bdr.qname.isPartOf(bb2.d_name)) + bdr.qname = bdr.qname.makeRelative(bb2.d_name); + else { + string msg = "Trying to insert non-zone data, name='"+bdr.qname.toLogString()+"', qtype="+qtype.getName()+", zone='"+bb2.d_name.toLogString()+"'"; + if(s_ignore_broken_records) { + g_log<empty() && bdr.qname==boost::prior(records->end())->qname) + bdr.qname=boost::prior(records->end())->qname; + + bdr.qname=bdr.qname; + bdr.qtype=qtype.getCode(); + bdr.content=content; + bdr.nsec3hash = hashed; + + if (auth) // Set auth on empty non-terminals + bdr.auth=*auth; + else + bdr.auth=true; + + bdr.ttl=ttl; + records->insert(bdr); +} + +string Bind2Backend::DLReloadNowHandler(const vector&parts, Utility::pid_t ppid) +{ + ostringstream ret; + + for(vector::const_iterator i=parts.begin()+1;i&parts, Utility::pid_t ppid) +{ + ostringstream ret; + + if(parts.size() > 1) { + for(vector::const_iterator i=parts.begin()+1;id_name << ": "<< (i->d_loaded ? "": "[rejected]") <<"\t"<d_status<<"\n"; + } + } + + if(ret.str().empty()) + ret<<"no domains passed"; + + return ret.str(); +} + +string Bind2Backend::DLListRejectsHandler(const vector&parts, Utility::pid_t ppid) +{ + ostringstream ret; + ReadLock rl(&s_state_lock); + for(state_t::const_iterator i = s_state.begin(); i != s_state.end() ; ++i) { + if(!i->d_loaded) + ret<d_name<<"\t"<d_status<&parts, Utility::pid_t ppid) +{ + if(parts.size() < 3) + return "ERROR: Domain name and zone filename are required"; + + DNSName domainname(parts[1]); + const string &filename = parts[2]; + BB2DomainInfo bbd; + if(safeGetBBDomainInfo(domainname, &bbd)) + return "Already loaded"; + + if (!boost::starts_with(filename, "/") && ::arg()["chroot"].empty()) + return "Unable to load zone " + domainname.toLogString() + " from " + filename + " as the filename is not absolute."; + + struct stat buf; + if (stat(filename.c_str(), &buf) != 0) + return "Unable to load zone " + domainname.toLogString() + " from " + filename + ": " + strerror(errno); + + Bind2Backend bb2; // createdomainentry needs access to our configuration + bbd=bb2.createDomainEntry(domainname, filename); + bbd.d_filename=filename; + bbd.d_checknow=true; + bbd.d_loaded=true; + bbd.d_lastcheck=0; + bbd.d_status="parsing into memory"; + bbd.setCtime(); + + safePutBBDomainInfo(bbd); + + g_log<registerFunc("BIND-RELOAD-NOW", &DLReloadNowHandler, "bindbackend: reload domains", ""); + dl->registerFunc("BIND-DOMAIN-STATUS", &DLDomStatusHandler, "bindbackend: list status of all domains", "[domains]"); + dl->registerFunc("BIND-LIST-REJECTS", &DLListRejectsHandler, "bindbackend: list rejected domains"); + dl->registerFunc("BIND-ADD-ZONE", &DLAddDomainHandler, "bindbackend: add zone", " "); +} + +Bind2Backend::~Bind2Backend() +{ freeStatements(); } // deallocate statements + +void Bind2Backend::rediscover(string *status) +{ + loadConfig(status); +} + +void Bind2Backend::reload() +{ + WriteLock rwl(&s_state_lock); + for(state_t::iterator i = s_state.begin(); i != s_state.end() ; ++i) { + i->d_checknow=true; // being a bit cheeky here, don't index state_t on this (mutable) + } +} + +void Bind2Backend::fixupOrderAndAuth(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr) +{ + shared_ptr records = bbd.d_records.getWRITABLE(); + + bool skip; + DNSName shorter; + set nssets, dssets; + + for(const auto& bdr: *records) { + if(!bdr.qname.isRoot() && bdr.qtype == QType::NS) + nssets.insert(bdr.qname); + else if(bdr.qtype == QType::DS) + dssets.insert(bdr.qname); + } + + for(auto iter = records->begin(); iter != records->end(); iter++) { + skip = false; + shorter = iter->qname; + + if (!iter->qname.isRoot() && shorter.chopOff() && !iter->qname.isRoot()) { + do { + if(nssets.count(shorter)) { + skip = true; + break; + } + } while(shorter.chopOff() && !iter->qname.isRoot()); + } + + iter->auth = (!skip && (iter->qtype == QType::DS || iter->qtype == QType::RRSIG || !nssets.count(iter->qname))); + + if(!skip && nsec3zone && iter->qtype != QType::RRSIG && (iter->auth || (iter->qtype == QType::NS && !ns3pr.d_flags) || dssets.count(iter->qname))) { + Bind2DNSRecord bdr = *iter; + bdr.nsec3hash = toBase32Hex(hashQNameWithSalt(ns3pr, bdr.qname+bbd.d_name)); + records->replace(iter, bdr); + } + + // cerr<qname<<"\t"<qtype).getName()<<"\t"<nsec3hash<<"\t"<auth< records = bbd.d_records.get(); + + bool auth; + DNSName shorter; + set qnames; + map nonterm; + + uint32_t maxent = ::arg().asNum("max-ent-entries"); + + for(const auto& bdr : *records) + qnames.insert(bdr.qname); + + for(const auto& bdr : *records) { + + if (!bdr.auth && bdr.qtype == QType::NS) + auth = (!nsec3zone || !ns3pr.d_flags); + else + auth = bdr.auth; + + shorter = bdr.qname; + while(shorter.chopOff()) + { + if(!qnames.count(shorter)) + { + if(!(maxent)) + { + g_log<(shorter, auth)); + --maxent; + } else if (auth) + nonterm[shorter] = true; + } + } + } + + DNSResourceRecord rr; + rr.qtype = "#0"; + rr.content = ""; + rr.ttl = 0; + for(auto& nt : nonterm) + { + string hashed; + rr.qname = nt.first + bbd.d_name; + if(nsec3zone && nt.second) + hashed = toBase32Hex(hashQNameWithSalt(ns3pr, rr.qname)); + insertRecord(bbd, rr.qname, rr.qtype, rr.content, rr.ttl, hashed, &nt.second); + + // cerr< domains=BP.getDomains(); + this->alsoNotify = BP.getAlsoNotify(); + + s_binddirectory=BP.getDirectory(); + // ZP.setDirectory(d_binddirectory); + + g_log< oldnames, newnames; + { + ReadLock rl(&s_state_lock); + for(const BB2DomainInfo& bbd : s_state) { + oldnames.insert(bbd.d_name); + } + } + int rejected=0; + int newdomains=0; + + struct stat st; + + for(vector::iterator i=domains.begin(); i!=domains.end(); ++i) + { + if(stat(i->filename.c_str(), &st) == 0) { + i->d_dev = st.st_dev; + i->d_ino = st.st_ino; + } + } + + sort(domains.begin(), domains.end()); // put stuff in inode order + for(vector::const_iterator i=domains.begin(); + i!=domains.end(); + ++i) + { + if (!(i->hadFileDirective)) { + g_log<name<<"' has no 'file' directive set in "<type == "") + g_log<name<<"' has no type specified, assuming 'native'"<type!="master" && i->type!="slave" && i->type != "native" && i->type != "") { + g_log<name<<"' because type '"<type<<"' is invalid"<name, &bbd)) { + isNew = true; + bbd.d_id=domain_id++; + bbd.setCheckInterval(getArgAsNum("check-interval")); + bbd.d_lastnotified=0; + bbd.d_loaded=false; + } + + // overwrite what we knew about the domain + bbd.d_name=i->name; + bool filenameChanged = (bbd.d_filename!=i->filename); + bbd.d_filename=i->filename; + bbd.d_masters=i->masters; + bbd.d_also_notify=i->alsoNotify; + + bbd.d_kind = DomainInfo::Native; + if (i->type == "master") + bbd.d_kind = DomainInfo::Master; + if (i->type == "slave") + bbd.d_kind = DomainInfo::Slave; + + newnames.insert(bbd.d_name); + if(filenameChanged || !bbd.d_loaded || !bbd.current()) { + g_log<name<<"' from file '"<filename<<"'"<name<<"' from file '"<filename<<"': "<type == "slave") + msg<<" error at "+nowTime()<<" no file found for new slave domain '"<name<<"'. Has not been AXFR'd yet"; + else + msg<<" error at "+nowTime()+" parsing '"<name<<"' from file '"<filename<<"': "<name<<"' from file '"<filename<<"': "< diff; + + set_difference(oldnames.begin(), oldnames.end(), newnames.begin(), newnames.end(), back_inserter(diff)); + unsigned int remdomains=diff.size(); + + for(const DNSName& name: diff) { + safeRemoveBBDomainInfo(name); + } + + // count number of entirely new domains + diff.clear(); + set_difference(newnames.begin(), newnames.end(), oldnames.begin(), oldnames.end(), back_inserter(diff)); + newdomains=diff.size(); + + ostringstream msg; + msg<<" Done parsing domains, "< records = bbd.d_records.get(); + + // for(const auto& record: *records) + // cerr<upper_bound(qname.makeLowerCase()); + + if(iterBefore != records->begin()) + --iterBefore; + while((!iterBefore->auth && iterBefore->qtype != QType::NS) || !iterBefore->qtype) + --iterBefore; + before=iterBefore->qname; + + if(iterAfter == records->end()) { + iterAfter = records->begin(); + } else { + while((!iterAfter->auth && iterAfter->qtype != QType::NS) || !iterAfter->qtype) { + ++iterAfter; + if(iterAfter == records->end()) { + iterAfter = records->begin(); + break; + } + } + } + after = iterAfter->qname; + + return true; +} + +bool Bind2Backend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) +{ + BB2DomainInfo bbd; + if (!safeGetBBDomainInfo(id, &bbd)) + return false; + + NSEC3PARAMRecordContent ns3pr; + + bool nsec3zone; + if (d_hybrid) { + DNSSECKeeper dk; + nsec3zone=dk.getNSEC3PARAM(bbd.d_name, &ns3pr); + } else + nsec3zone=getNSEC3PARAM(bbd.d_name, &ns3pr); + + if(!nsec3zone) { + return findBeforeAndAfterUnhashed(bbd, qname, unhashed, before, after); + } + else { + auto& hashindex=boost::multi_index::get(*bbd.d_records.getWRITABLE()); + + // for(auto iter = first; iter != hashindex.end(); iter++) + // cerr<nsec3hash<nsec3hash); + after = DNSName(first->nsec3hash); + } else { + after = DNSName(iter->nsec3hash); + if (iter != first) + --iter; + else + iter = --hashindex.end(); + before = DNSName(iter->nsec3hash); + } + unhashed = iter->qname+bbd.d_name; + + return true; + } +} + +void Bind2Backend::lookup(const QType &qtype, const DNSName &qname, DNSPacket *pkt_p, int zoneId ) +{ + d_handle.reset(); + + static bool mustlog=::arg().mustDo("query-logging"); + + bool found; + DNSName domain; + BB2DomainInfo bbd; + + if(mustlog) + g_log<= 0) { + if ((found = (safeGetBBDomainInfo(zoneId, &bbd) && qname.isPartOf(bbd.d_name)))) { + domain = bbd.d_name; + } + } else { + domain = qname; + do { + found = safeGetBBDomainInfo(domain, &bbd); + } while (!found && qtype != QType::SOA && domain.chopOff()); + } + + if(!found) { + if(mustlog) + g_log<empty()) + DLOG(g_log<<"Query with no results"<(*d_handle.d_records); + auto range = hashedidx.equal_range(d_handle.qname); + + if(range.first==range.second) { + d_handle.d_list=false; + d_handle.d_iter = d_handle.d_end_iter = range.first; + return; + } + else { + d_handle.d_iter=range.first; + d_handle.d_end_iter=range.second; + } + + d_handle.d_list=false; +} + +Bind2Backend::handle::handle() +{ + mustlog=false; +} + +bool Bind2Backend::get(DNSResourceRecord &r) +{ + if(!d_handle.d_records) { + if(d_handle.mustlog) + g_log<size()<<" available in total!"<qtype==qtype.getCode())) { + DLOG(g_log<qtype).getName()<<": '"<content<<"'"<qtype).getCode()<content; + // r.domain_id=(d_iter)->domain_id; + r.qtype=(d_iter)->qtype; + r.ttl=(d_iter)->ttl; + + //if(!d_iter->auth && r.qtype.getCode() != QType::A && r.qtype.getCode()!=QType::AAAA && r.qtype.getCode() != QType::NS) + // cerr<<"Warning! Unauth response for qtype "<< r.qtype.getName() << " for '"<auth; + + d_iter++; + + return true; +} + +bool Bind2Backend::list(const DNSName& target, int id, bool include_disabled) +{ + BB2DomainInfo bbd; + + if(!safeGetBBDomainInfo(id, &bbd)) + return false; + + d_handle.reset(); + DLOG(g_log<<"Bind2Backend constructing handle for list of "<begin(); + d_handle.d_qname_end=d_handle.d_records->end(); // iter now points to a vector of pointers to vector + + d_handle.id=id; + d_handle.domain=bbd.d_name; + d_handle.d_list=true; + return true; +} + +bool Bind2Backend::handle::get_list(DNSResourceRecord &r) +{ + if(d_qname_iter!=d_qname_end) { + r.qname=d_qname_iter->qname.empty() ? domain : (d_qname_iter->qname+domain); + r.domain_id=id; + r.content=(d_qname_iter)->content; + r.qtype=(d_qname_iter)->qtype; + r.ttl=(d_qname_iter)->ttl; + r.auth = d_qname_iter->auth; + d_qname_iter++; + return true; + } + return false; +} + +bool Bind2Backend::superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) +{ + // Check whether we have a configfile available. + if (getArg("supermaster-config").empty()) + return false; + + ifstream c_if(getArg("supermasters").c_str(), std::ios::in); // this was nocreate? + if (!c_if) { + g_log << Logger::Error << "Unable to open supermasters file for read: " << stringerror() << endl; + return false; + } + + // Format: + // + string line, sip, saccount; + while (getline(c_if, line)) { + std::istringstream ii(line); + ii >> sip; + if (sip == ip) { + ii >> saccount; + break; + } + } + c_if.close(); + + if (sip != ip) // ip not found in authorization list - reject + return false; + + // ip authorized as supermaster - accept + *db = this; + if (saccount.length() > 0) + *account = saccount.c_str(); + + return true; +} + +BB2DomainInfo Bind2Backend::createDomainEntry(const DNSName& domain, const string &filename) +{ + int newid=1; + { // Find a free zone id nr. + ReadLock rl(&s_state_lock); + if (!s_state.empty()) { + newid = s_state.rbegin()->d_id+1; + } + } + + BB2DomainInfo bbd; + bbd.d_kind = DomainInfo::Native; + bbd.d_id = newid; + bbd.d_records = shared_ptr(new recordstorage_t); + bbd.d_name = domain; + bbd.setCheckInterval(getArgAsNum("check-interval")); + bbd.d_filename = filename; + + return bbd; +} + +bool Bind2Backend::createSlaveDomain(const string &ip, const DNSName& domain, const string &nameserver, const string &account) +{ + string filename = getArg("supermaster-destdir")+'/'+domain.toStringNoDot(); + + g_log << Logger::Warning << d_logprefix + << " Writing bind config zone statement for superslave zone '" << domain + << "' from supermaster " << ip << endl; + + { + Lock l2(&s_supermaster_config_lock); + + ofstream c_of(getArg("supermaster-config").c_str(), std::ios::app); + if (!c_of) { + g_log << Logger::Error << "Unable to open supermaster configfile for append: " << stringerror() << endl; + throw DBException("Unable to open supermaster configfile for append: "+stringerror()); + } + + c_of << endl; + c_of << "# Superslave zone '" << domain.toString() << "' (added: " << nowTime() << ") (account: " << account << ')' << endl; + c_of << "zone \"" << domain.toStringNoDot() << "\" {" << endl; + c_of << "\ttype slave;" << endl; + c_of << "\tfile \"" << filename << "\";" << endl; + c_of << "\tmasters { " << ip << "; };" << endl; + c_of << "};" << endl; + c_of.close(); + } + + BB2DomainInfo bbd = createDomainEntry(domain, filename); + bbd.d_kind = DomainInfo::Slave; + bbd.d_masters.push_back(ComboAddress(ip, 53)); + bbd.setCtime(); + safePutBBDomainInfo(bbd); + return true; +} + +bool Bind2Backend::searchRecords(const string &pattern, int maxResults, vector& result) +{ + SimpleMatch sm(pattern,true); + static bool mustlog=::arg().mustDo("query-logging"); + if(mustlog) + g_log<d_id, &h)) { + continue; + } + + shared_ptr rhandle = h.d_records.get(); + + for(recordstorage_t::const_iterator ri = rhandle->begin(); result.size() < static_cast::size_type>(maxResults) && ri != rhandle->end(); ri++) { + DNSName name = ri->qname.empty() ? i->d_name : (ri->qname+i->d_name); + if (sm.match(name) || sm.match(ri->content)) { + DNSResourceRecord r; + r.qname=name; + r.domain_id=i->d_id; + r.content=ri->content; + r.qtype=ri->qtype; + r.ttl=ri->ttl; + r.auth = ri->auth; + result.push_back(r); + } + } + } + } + + return true; +} + +class Bind2Factory : public BackendFactory +{ + public: + Bind2Factory() : BackendFactory("bind") {} + + void declareArguments(const string &suffix="") + { + declare(suffix,"ignore-broken-records","Ignore records that are out-of-bound for the zone.","no"); + declare(suffix,"config","Location of named.conf",""); + declare(suffix,"check-interval","Interval for zonefile changes","0"); + declare(suffix,"supermaster-config","Location of (part of) named.conf where pdns can write zone-statements to",""); + declare(suffix,"supermasters","List of IP-addresses of supermasters",""); + declare(suffix,"supermaster-destdir","Destination directory for newly added slave zones",::arg()["config-dir"]); + declare(suffix,"dnssec-db","Filename to store & access our DNSSEC metadatabase, empty for none", ""); + declare(suffix,"dnssec-db-journal-mode","SQLite3 journal mode", "WAL"); + declare(suffix,"hybrid","Store DNSSEC metadata in other backend","no"); + } + + DNSBackend *make(const string &suffix="") + { + assertEmptySuffix(suffix); + return new Bind2Backend(suffix); + } + + DNSBackend *makeMetadataOnly(const string &suffix="") + { + assertEmptySuffix(suffix); + return new Bind2Backend(suffix, false); + } + private: + void assertEmptySuffix(const string &suffix) + { + if(suffix.length()) + throw PDNSException("launch= suffixes are not supported on the bindbackend"); + } +}; + +//! Magic class that is activated when the dynamic library is loaded +class Bind2Loader +{ +public: + Bind2Loader() + { + BackendMakers().report(new Bind2Factory); + g_log << Logger::Info << "[bind2backend] This is the bind backend version " << VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif +#ifdef HAVE_SQLITE3 + << " (with bind-dnssec-db support)" +#endif + << " reporting" << endl; + } +}; +static Bind2Loader bind2loader; diff --git a/modules/bindbackend/bindbackend2.hh b/modules/bindbackend/bindbackend2.hh new file mode 100644 index 0000000..ee545d6 --- /dev/null +++ b/modules/bindbackend/bindbackend2.hh @@ -0,0 +1,331 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef PDNS_BINDBACKEND_HH +#define PDNS_BINDBACKEND_HH + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pdns/lock.hh" +#include "pdns/misc.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/namespaces.hh" +#include "pdns/backends/gsql/ssql.hh" + +using namespace ::boost::multi_index; + +/** + This struct is used within the Bind2Backend to store DNS information. It is + almost identical to a DNSResourceRecord, but then a bit smaller and with + different sorting rules, which make sure that the SOA record comes up front. +*/ + +struct Bind2DNSRecord +{ + DNSName qname; + string content; + string nsec3hash; + uint32_t ttl; + uint16_t qtype; + mutable bool auth; + bool operator<(const Bind2DNSRecord& rhs) const + { + if(qname.canonCompare(rhs.qname)) + return true; + if(rhs.qname.canonCompare(qname)) + return false; + if(qtype==QType::SOA && rhs.qtype!=QType::SOA) + return true; + return tie(qtype,content, ttl) < tie(rhs.qtype, rhs.content, rhs.ttl); + } +}; + +struct Bind2DNSCompare : std::less +{ + using std::less::operator(); + // use operator< + bool operator() (const DNSName& a, const Bind2DNSRecord& b) const + {return a.canonCompare(b.qname);} + bool operator() (const Bind2DNSRecord& a, const DNSName& b) const + {return a.qname.canonCompare(b);} + bool operator() (const Bind2DNSRecord& a, const Bind2DNSRecord& b) const + {return a.qname.canonCompare(b.qname);} +}; + +struct NSEC3Tag{}; +struct UnorderedNameTag{}; + +typedef multi_index_container< + Bind2DNSRecord, + indexed_by < + ordered_non_unique, Bind2DNSCompare >, + hashed_non_unique, member >, + ordered_non_unique, member > + > +> recordstorage_t; + +template +class LookButDontTouch // : public boost::noncopyable +{ +public: + LookButDontTouch() + { + pthread_mutex_init(&d_lock, 0); + pthread_mutex_init(&d_swaplock, 0); + } + LookButDontTouch(shared_ptr records) : d_records(records) + { + pthread_mutex_init(&d_lock, 0); + pthread_mutex_init(&d_swaplock, 0); + } + + shared_ptr get() + { + shared_ptr ret; + { + Lock l(&d_lock); + ret = d_records; + } + return ret; + } + + shared_ptr getWRITABLE() + { + shared_ptr ret; + { + Lock l(&d_lock); + ret = d_records; + } + return ret; + } + + + void swap(shared_ptr records) + { + Lock l(&d_lock); + Lock l2(&d_swaplock); + d_records.swap(records); + } + pthread_mutex_t d_lock; + pthread_mutex_t d_swaplock; +private: + shared_ptr d_records; +}; + + +/** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */ +class BB2DomainInfo +{ +public: + BB2DomainInfo(); + void setCtime(); + bool current(); + //! configure how often this domain should be checked for changes (on disk) + void setCheckInterval(time_t seconds); + + DNSName d_name; //!< actual name of the domain + DomainInfo::DomainKind d_kind; //!< the kind of domain + string d_filename; //!< full absolute filename of the zone on disk + string d_status; //!< message describing status of a domain, for human consumption + vector d_masters; //!< IP address of the master of this domain + set d_also_notify; //!< IP list of hosts to also notify + LookButDontTouch d_records; //!< the actual records belonging to this domain + time_t d_ctime{0}; //!< last known ctime of the file on disk + time_t d_lastcheck{0}; //!< last time domain was checked for freshness + uint32_t d_lastnotified{0}; //!< Last serial number we notified our slaves of + unsigned int d_id; //!< internal id of the domain + mutable bool d_checknow; //!< if this domain has been flagged for a check + bool d_loaded; //!< if a domain is loaded + bool d_wasRejectedLastReload{false}; //!< if the domain was rejected during Bind2Backend::queueReloadAndStore + +private: + time_t getCtime(); + time_t d_checkinterval; +}; + +class SSQLite3; +class NSEC3PARAMRecordContent; + +struct NameTag +{}; + +class Bind2Backend : public DNSBackend +{ +public: + Bind2Backend(const string &suffix="", bool loadZones=true); + ~Bind2Backend(); + void getUnfreshSlaveInfos(vector *unfreshDomains) override; + void getUpdatedMasters(vector *changedDomains) override; + bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true ) override; + time_t getCtime(const string &fname); + // DNSSEC + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; + void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1) override; + bool list(const DNSName &target, int id, bool include_disabled=false) override; + bool get(DNSResourceRecord &) override; + void getAllDomains(vector *domains, bool include_disabled=false) override; + + static DNSBackend *maker(); + static pthread_mutex_t s_startup_lock; + + void setFresh(uint32_t domain_id) override; + void setNotified(uint32_t id, uint32_t serial) override; + bool startTransaction(const DNSName &qname, int id) override; + bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + bool commitTransaction() override; + bool abortTransaction() override; + void alsoNotifies(const DNSName &domain, set *ips) override; + bool searchRecords(const string &pattern, int maxResults, vector& result) override; + +// the DNSSEC related (getDomainMetadata has broader uses too) + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; + bool getDomainKeys(const DNSName& name, std::vector& keys) override; + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; + bool deleteTSIGKey(const DNSName& name) override; + bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + bool doesDNSSEC() override; + // end of DNSSEC + + typedef multi_index_container < BB2DomainInfo , + indexed_by < ordered_unique >, + ordered_unique, member > + > > state_t; + static state_t s_state; + static pthread_rwlock_t s_state_lock; + + void parseZoneFile(BB2DomainInfo *bbd); + void insertRecord(BB2DomainInfo& bbd, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed=string(), bool *auth=0); + void rediscover(string *status=0) override; + + + // for supermaster support + bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) override; + static pthread_mutex_t s_supermaster_config_lock; + bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) override; + +private: + void setupDNSSEC(); + void setupStatements(); + void freeStatements(); + void release(SSqlStatement**); + static bool safeGetBBDomainInfo(int id, BB2DomainInfo* bbd); + static void safePutBBDomainInfo(const BB2DomainInfo& bbd); + static bool safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd); + static bool safeRemoveBBDomainInfo(const DNSName& name); + bool GetBBDomainInfo(int id, BB2DomainInfo** bbd); + shared_ptr d_dnssecdb; + bool getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p); + class handle + { + public: + bool get(DNSResourceRecord &); + void reset(); + + handle(); + + shared_ptr d_records; + recordstorage_t::index::type::const_iterator d_iter, d_end_iter; + + recordstorage_t::const_iterator d_qname_iter, d_qname_end; + + DNSName qname; + DNSName domain; + + int id; + QType qtype; + bool d_list; + bool mustlog; + + private: + bool get_normal(DNSResourceRecord &); + bool get_list(DNSResourceRecord &); + + void operator=(const handle& ); // don't go copying this + handle(const handle &); + }; + + unique_ptr d_getAllDomainMetadataQuery_stmt; + unique_ptr d_getDomainMetadataQuery_stmt; + unique_ptr d_deleteDomainMetadataQuery_stmt; + unique_ptr d_insertDomainMetadataQuery_stmt; + unique_ptr d_getDomainKeysQuery_stmt; + unique_ptr d_deleteDomainKeyQuery_stmt; + unique_ptr d_insertDomainKeyQuery_stmt; + unique_ptr d_GetLastInsertedKeyIdQuery_stmt; + unique_ptr d_activateDomainKeyQuery_stmt; + unique_ptr d_deactivateDomainKeyQuery_stmt; + unique_ptr d_getTSIGKeyQuery_stmt; + unique_ptr d_setTSIGKeyQuery_stmt; + unique_ptr d_deleteTSIGKeyQuery_stmt; + unique_ptr d_getTSIGKeysQuery_stmt; + + string d_transaction_tmpname; + string d_logprefix; + set alsoNotify; //!< this is used to store the also-notify list of interested peers. + std::unique_ptr d_of; + handle d_handle; + static string s_binddirectory; //!< this is used to store the 'directory' setting of the bind configuration + static int s_first; //!< this is raised on construction to prevent multiple instances of us being generated + int d_transaction_id; + static bool s_ignore_broken_records; + bool d_hybrid; + + BB2DomainInfo createDomainEntry(const DNSName& domain, const string &filename); //!< does not insert in s_state + + void queueReloadAndStore(unsigned int id); + bool findBeforeAndAfterUnhashed(BB2DomainInfo& bbd, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after); + void reload() override; + static string DLDomStatusHandler(const vector&parts, Utility::pid_t ppid); + static string DLListRejectsHandler(const vector&parts, Utility::pid_t ppid); + static string DLReloadNowHandler(const vector&parts, Utility::pid_t ppid); + static string DLAddDomainHandler(const vector&parts, Utility::pid_t ppid); + static void fixupOrderAndAuth(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr); + void doEmptyNonTerminals(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr); + void loadConfig(string *status=0); + static void nukeZoneRecords(BB2DomainInfo *bbd); + +}; + +#endif /* PDNS_BINDBACKEND_HH */ diff --git a/modules/bindbackend/binddnssec.cc b/modules/bindbackend/binddnssec.cc new file mode 100644 index 0000000..9399698 --- /dev/null +++ b/modules/bindbackend/binddnssec.cc @@ -0,0 +1,478 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "bindbackend2.hh" +#include "pdns/arguments.hh" +#include "pdns/dnsrecords.hh" + +#ifndef HAVE_SQLITE3 + +void Bind2Backend::setupDNSSEC() +{ + if(!getArg("dnssec-db").empty()) + throw runtime_error("bind-dnssec-db requires building PowerDNS with SQLite3"); +} + +bool Bind2Backend::doesDNSSEC() +{ return d_hybrid; } + +bool Bind2Backend::getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p) +{ return false; } + +bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map >& meta) +{ return false; } + +bool Bind2Backend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ return false; } + +bool Bind2Backend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ return false; } + +bool Bind2Backend::getDomainKeys(const DNSName& name, std::vector& keys) +{ return false; } + +bool Bind2Backend::removeDomainKey(const DNSName& name, unsigned int id) +{ return false; } + +bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) +{ return false; } + +bool Bind2Backend::activateDomainKey(const DNSName& name, unsigned int id) +{ return false; } + +bool Bind2Backend::deactivateDomainKey(const DNSName& name, unsigned int id) +{ return false; } + +bool Bind2Backend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) +{ return false; } + +bool Bind2Backend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ return false; } + +bool Bind2Backend::deleteTSIGKey(const DNSName& name) +{ return false; } + +bool Bind2Backend::getTSIGKeys(std::vector &keys) +{ return false; } + +void Bind2Backend::setupStatements() +{ return; } + +void Bind2Backend::freeStatements() +{ return; } + +#else + +#include "pdns/bind-dnssec.schema.sqlite3.sql.h" +#include "pdns/logger.hh" +#include "pdns/ssqlite3.hh" + +#define ASSERT_ROW_COLUMNS(query, row, num) { if (row.size() != num) { throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); } } + +void Bind2Backend::setupDNSSEC() +{ + if(getArg("dnssec-db").empty() || d_hybrid) + return; + try { + d_dnssecdb = shared_ptr(new SSQLite3(getArg("dnssec-db"), getArg("dnssec-db-journal-mode"))); + setupStatements(); + } + catch(SSqlException& se) { + // this error is meant to kill the server dead - it makes no sense to continue.. + throw runtime_error("Error opening DNSSEC database in BIND backend: "+se.txtReason()); + } + + d_dnssecdb->setLog(::arg().mustDo("query-logging")); +} + +void Bind2Backend::setupStatements() +{ + d_getAllDomainMetadataQuery_stmt = d_dnssecdb->prepare("select kind, content from domainmetadata where domain=:domain",1); + d_getDomainMetadataQuery_stmt = d_dnssecdb->prepare("select content from domainmetadata where domain=:domain and kind=:kind",2); + d_deleteDomainMetadataQuery_stmt = d_dnssecdb->prepare("delete from domainmetadata where domain=:domain and kind=:kind",2); + d_insertDomainMetadataQuery_stmt = d_dnssecdb->prepare("insert into domainmetadata (domain, kind, content) values (:domain,:kind,:content)",3); + d_getDomainKeysQuery_stmt = d_dnssecdb->prepare("select id,flags, active, content from cryptokeys where domain=:domain",1); + d_deleteDomainKeyQuery_stmt = d_dnssecdb->prepare("delete from cryptokeys where domain=:domain and id=:key_id",2); + d_insertDomainKeyQuery_stmt = d_dnssecdb->prepare("insert into cryptokeys (domain, flags, active, content) values (:domain, :flags, :active, :content)", 4); + d_GetLastInsertedKeyIdQuery_stmt = d_dnssecdb->prepare("select last_insert_rowid()", 0); + d_activateDomainKeyQuery_stmt = d_dnssecdb->prepare("update cryptokeys set active=1 where domain=:domain and id=:key_id", 2); + d_deactivateDomainKeyQuery_stmt = d_dnssecdb->prepare("update cryptokeys set active=0 where domain=:domain and id=:key_id", 2); + d_getTSIGKeyQuery_stmt = d_dnssecdb->prepare("select algorithm, secret from tsigkeys where name=:key_name", 1); + d_setTSIGKeyQuery_stmt = d_dnssecdb->prepare("replace into tsigkeys (name,algorithm,secret) values(:key_name, :algorithm, :content)", 3); + d_deleteTSIGKeyQuery_stmt = d_dnssecdb->prepare("delete from tsigkeys where name=:key_name", 1); + d_getTSIGKeysQuery_stmt = d_dnssecdb->prepare("select name,algorithm,secret from tsigkeys", 0); +} + +void Bind2Backend::release(SSqlStatement** stmt) { + delete *stmt; + *stmt = NULL; +} + +void Bind2Backend::freeStatements() +{ + d_getAllDomainMetadataQuery_stmt.reset(); + d_getDomainMetadataQuery_stmt.reset(); + d_deleteDomainMetadataQuery_stmt.reset(); + d_insertDomainMetadataQuery_stmt.reset(); + d_getDomainKeysQuery_stmt.reset(); + d_deleteDomainKeyQuery_stmt.reset(); + d_insertDomainKeyQuery_stmt.reset(); + d_GetLastInsertedKeyIdQuery_stmt.reset(); + d_activateDomainKeyQuery_stmt.reset(); + d_deactivateDomainKeyQuery_stmt.reset(); + d_getTSIGKeyQuery_stmt.reset(); + d_setTSIGKeyQuery_stmt.reset(); + d_deleteTSIGKeyQuery_stmt.reset(); + d_getTSIGKeysQuery_stmt.reset(); +} + +bool Bind2Backend::doesDNSSEC() +{ + return d_dnssecdb || d_hybrid; +} + +bool Bind2Backend::getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + string value; + vector meta; + getDomainMetadata(name, "NSEC3PARAM", meta); + if(!meta.empty()) + value=*meta.begin(); + else + return false; // No NSEC3 zone + + static int maxNSEC3Iterations=::arg().asNum("max-nsec3-iterations"); + if(ns3p) { + auto tmp=std::dynamic_pointer_cast(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, value)); + *ns3p = *tmp; + + if (ns3p->d_iterations > maxNSEC3Iterations) { + ns3p->d_iterations = maxNSEC3Iterations; + g_log<d_algorithm != 1) { + g_log<d_algorithm)<<"', setting to 1 for zone '"<d_algorithm = 1; + } + } + + return true; +} + +bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map >& meta) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_getAllDomainMetadataQuery_stmt-> + bind("domain", name)-> + execute(); + + SSqlStatement::row_t row; + while(d_getAllDomainMetadataQuery_stmt->hasNextRow()) { + d_getAllDomainMetadataQuery_stmt->nextRow(row); + meta[row[0]].push_back(row[1]); + } + + d_getAllDomainMetadataQuery_stmt->reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getAllDomainMetadata(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_getDomainMetadataQuery_stmt-> + bind("domain", name)-> + bind("kind", kind)-> + execute(); + + SSqlStatement::row_t row; + while(d_getDomainMetadataQuery_stmt->hasNextRow()) { + d_getDomainMetadataQuery_stmt->nextRow(row); + meta.push_back(row[0]); + } + + d_getDomainMetadataQuery_stmt->reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainMetadata(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_deleteDomainMetadataQuery_stmt-> + bind("domain", name)-> + bind("kind", kind)-> + execute()-> + reset(); + if(!meta.empty()) { + for(const auto& value: meta) { + d_insertDomainMetadataQuery_stmt-> + bind("domain", name)-> + bind("kind", kind)-> + bind("content", value)-> + execute()-> + reset(); + } + } + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, setDomainMetadata(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_getDomainKeysQuery_stmt-> + bind("domain", name)-> + execute(); + + KeyData kd; + SSqlStatement::row_t row; + while(d_getDomainKeysQuery_stmt->hasNextRow()) { + d_getDomainKeysQuery_stmt->nextRow(row); + kd.id = pdns_stou(row[0]); + kd.flags = pdns_stou(row[1]); + kd.active = (row[2] == "1"); + kd.content = row[3]; + keys.push_back(kd); + } + + d_getDomainKeysQuery_stmt->reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainKeys(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::removeDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_deleteDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, removeDomainKeys(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_insertDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("flags", key.flags)-> + bind("active", key.active)-> + bind("content", key.content)-> + execute()-> + reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, addDomainKey(): "+se.txtReason()); + } + + try { + d_GetLastInsertedKeyIdQuery_stmt->execute(); + if (!d_GetLastInsertedKeyIdQuery_stmt->hasNextRow()) { + id = -2; + return true; + } + SSqlStatement::row_t row; + d_GetLastInsertedKeyIdQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-last-inserted-key-id-query", row, 1); + id = std::stoi(row[0]); + d_GetLastInsertedKeyIdQuery_stmt->reset(); + return true; + } + catch (SSqlException &e) { + id = -2; + return true; + } + + return false; +} + +bool Bind2Backend::activateDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_activateDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, activateDomainKey(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::deactivateDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_deactivateDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch(SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, deactivateDomainKey(): "+se.txtReason()); + } + return true; +} + +bool Bind2Backend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_getTSIGKeyQuery_stmt-> + bind("key_name", name)-> + execute(); + + SSqlStatement::row_t row; + content->clear(); + while(d_getTSIGKeyQuery_stmt->hasNextRow()) { + d_getTSIGKeyQuery_stmt->nextRow(row); + if(row.size() >= 2 && (algorithm->empty() || *algorithm == DNSName(row[0]))) { + *algorithm = DNSName(row[0]); + *content = row[1]; + } + } + + d_getTSIGKeyQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKey(): "+e.txtReason()); + } + return !content->empty(); +} + +bool Bind2Backend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_setTSIGKeyQuery_stmt-> + bind("key_name", name)-> + bind("algorithm", algorithm)-> + bind("content", content)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, setTSIGKey(): "+e.txtReason()); + } + return true; +} + +bool Bind2Backend::deleteTSIGKey(const DNSName& name) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_deleteTSIGKeyQuery_stmt-> + bind("key_name", name)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, deleteTSIGKey(): "+e.txtReason()); + } + return true; +} + +bool Bind2Backend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +{ + if(!d_dnssecdb || d_hybrid) + return false; + + try { + d_getTSIGKeysQuery_stmt-> + execute(); + + SSqlStatement::row_t row; + while(d_getTSIGKeysQuery_stmt->hasNextRow()) { + d_getTSIGKeysQuery_stmt->nextRow(row); + struct TSIGKey key; + key.name = DNSName(row[0]); + key.algorithm = DNSName(row[1]); + key.key = row[2]; + keys.push_back(key); + } + + d_getTSIGKeysQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKeys(): "+e.txtReason()); + } + return !keys.empty(); +} + +#endif diff --git a/modules/geoipbackend/Makefile.am b/modules/geoipbackend/Makefile.am new file mode 100644 index 0000000..be692ef --- /dev/null +++ b/modules/geoipbackend/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS += $(YAML_CFLAGS) $(GEOIP_CFLAGS) $(MMDB_CFLAGS) + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +pkglib_LTLIBRARIES = libgeoipbackend.la + +libgeoipbackend_la_SOURCES = geoipbackend.cc geoipbackend.hh \ + geoipinterface.cc geoipinterface.hh \ + geoipinterface-dat.cc \ + geoipinterface-mmdb.cc +libgeoipbackend_la_LDFLAGS = -module -avoid-version +libgeoipbackend_la_LIBADD = $(YAML_LIBS) $(GEOIP_LIBS) $(MMDB_LIBS) diff --git a/modules/geoipbackend/Makefile.in b/modules/geoipbackend/Makefile.in new file mode 100644 index 0000000..52a55fa --- /dev/null +++ b/modules/geoipbackend/Makefile.in @@ -0,0 +1,836 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/geoipbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgeoipbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libgeoipbackend_la_OBJECTS = geoipbackend.lo geoipinterface.lo \ + geoipinterface-dat.lo geoipinterface-mmdb.lo +libgeoipbackend_la_OBJECTS = $(am_libgeoipbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgeoipbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgeoipbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgeoipbackend_la_SOURCES) +DIST_SOURCES = $(libgeoipbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(YAML_CFLAGS) $(GEOIP_CFLAGS) \ + $(MMDB_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = OBJECTFILES OBJECTLIBS +pkglib_LTLIBRARIES = libgeoipbackend.la +libgeoipbackend_la_SOURCES = geoipbackend.cc geoipbackend.hh \ + geoipinterface.cc geoipinterface.hh \ + geoipinterface-dat.cc \ + geoipinterface-mmdb.cc + +libgeoipbackend_la_LDFLAGS = -module -avoid-version +libgeoipbackend_la_LIBADD = $(YAML_LIBS) $(GEOIP_LIBS) $(MMDB_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/geoipbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/geoipbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgeoipbackend.la: $(libgeoipbackend_la_OBJECTS) $(libgeoipbackend_la_DEPENDENCIES) $(EXTRA_libgeoipbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgeoipbackend_la_LINK) -rpath $(pkglibdir) $(libgeoipbackend_la_OBJECTS) $(libgeoipbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoipbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoipinterface-dat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoipinterface-mmdb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoipinterface.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/geoipbackend/OBJECTFILES b/modules/geoipbackend/OBJECTFILES new file mode 100644 index 0000000..fc3a1ad --- /dev/null +++ b/modules/geoipbackend/OBJECTFILES @@ -0,0 +1 @@ +geoipbackend.lo geoipinterface-dat.lo geoipinterface.lo geoipinterface-mmdb.lo diff --git a/modules/geoipbackend/OBJECTLIBS b/modules/geoipbackend/OBJECTLIBS new file mode 100644 index 0000000..dfc2624 --- /dev/null +++ b/modules/geoipbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(YAML_LIBS) $(GEOIP_LIBS) $(MMDB_LIBS) diff --git a/modules/geoipbackend/geoipbackend.cc b/modules/geoipbackend/geoipbackend.cc new file mode 100644 index 0000000..c077570 --- /dev/null +++ b/modules/geoipbackend/geoipbackend.cc @@ -0,0 +1,946 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "geoipbackend.hh" +#include "geoipinterface.hh" +#include "pdns/dns_random.hh" +#include +#include +#include +#include +#include +#include + +pthread_rwlock_t GeoIPBackend::s_state_lock=PTHREAD_RWLOCK_INITIALIZER; + +struct GeoIPDNSResourceRecord: DNSResourceRecord { + int weight; + bool has_weight; +}; + +struct GeoIPService { + NetmaskTree > masks; + unsigned int netmask4; + unsigned int netmask6; +}; + +struct GeoIPDomain { + int id; + DNSName domain; + int ttl; + map services; + map > records; +}; + +static vector s_domains; +static int s_rc = 0; // refcount - always accessed under lock + +static string GeoIP_WEEKDAYS[] = { "mon", "tue", "wed", "thu", "fri", "sat", "sun" }; +static string GeoIP_MONTHS[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; + +/* So how does it work - we have static records and services. Static records "win". + We also insert empty non terminals for records and services. + + If a service makes an internal reference to a domain also hosted within geoip, we give a direct + answers, no CNAMEs involved. + + If the reference is external, we spoof up a CNAME, and good luck with that +*/ + +GeoIPBackend::GeoIPBackend(const string& suffix) { + WriteLock wl(&s_state_lock); + d_dnssec = false; + setArgPrefix("geoip" + suffix); + if (getArg("dnssec-keydir").empty() == false) { + DIR *d = opendir(getArg("dnssec-keydir").c_str()); + if (d == NULL) { + throw PDNSException("dnssec-keydir " + getArg("dnssec-keydir") + " does not exist"); + } + d_dnssec = true; + closedir(d); + } + if (s_rc == 0) { // first instance gets to open everything + initialize(); + } + s_rc++; +} + +static vector > s_geoip_files; + +string getGeoForLua(const std::string& ip, int qaint); +static string queryGeoIP(const string &ip, bool v6, GeoIPInterface::GeoIPQueryAttribute attribute, GeoIPNetmask& gl); + +void GeoIPBackend::initialize() { + YAML::Node config; + vector tmp_domains; + + s_geoip_files.clear(); // reset pointers + + if (getArg("database-files").empty() == false) { + vector files; + stringtok(files, getArg("database-files"), " ,\t\r\n"); + for(auto const& file: files) { + s_geoip_files.push_back(GeoIPInterface::makeInterface(file)); + } + } + + if (s_geoip_files.empty()) + g_log<()); + dom.ttl = domain["ttl"].as(); + + for(YAML::const_iterator recs = domain["records"].begin(); recs != domain["records"].end(); recs++) { + DNSName qname = DNSName(recs->first.as()); + vector rrs; + + for(YAML::Node item : recs->second) { + YAML::const_iterator rec = item.begin(); + GeoIPDNSResourceRecord rr; + rr.domain_id = dom.id; + rr.ttl = dom.ttl; + rr.qname = qname; + if (rec->first.IsNull()) { + rr.qtype = QType(0); + } else { + string qtype = boost::to_upper_copy(rec->first.as()); + rr.qtype = qtype; + } + rr.has_weight = false; + rr.weight = 100; + if (rec->second.IsNull()) { + rr.content = ""; + } else if (rec->second.IsMap()) { + for(YAML::const_iterator iter = rec->second.begin(); iter != rec->second.end(); iter++) { + string attr = iter->first.as(); + if (attr == "content") { + string content = iter->second.as(); + rr.content = content; + } else if (attr == "weight") { + rr.weight = iter->second.as(); + if (rr.weight <= 0) { + g_log<second.as(); + } else { + g_log<second.as(); + rr.content = content; + rr.weight = 100; + } + rr.auth = 1; + rrs.push_back(rr); + } + std::swap(dom.records[qname], rrs); + } + + for(YAML::const_iterator service = domain["services"].begin(); service != domain["services"].end(); service++) { + unsigned int netmask4 = 0, netmask6 = 0; + DNSName srvName{service->first.as()}; + NetmaskTree > nmt; + + // if it's an another map, we need to iterate it again, otherwise we just add two root entries. + if (service->second.IsMap()) { + for(YAML::const_iterator net = service->second.begin(); net != service->second.end(); net++) { + vector value; + if (net->second.IsSequence()) { + value = net->second.as >(); + } else { + value.push_back(net->second.as()); + } + if (net->first.as() == "default") { + nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end()); + nmt.insert(Netmask("::/0")).second.swap(value); + } else { + Netmask nm{net->first.as()}; + nmt.insert(nm).second.swap(value); + if (nm.isIpv6() == true && netmask6 < nm.getBits()) + netmask6 = nm.getBits(); + if (nm.isIpv6() == false && netmask4 < nm.getBits()) + netmask4 = nm.getBits(); + } + } + } else { + vector value; + if (service->second.IsSequence()) { + value = service->second.as >(); + } else { + value.push_back(service->second.as()); + } + nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end()); + nmt.insert(Netmask("::/0")).second.swap(value); + } + + dom.services[srvName].netmask4 = netmask4; + dom.services[srvName].netmask6 = netmask6; + dom.services[srvName].masks.swap(nmt); + } + + // rectify the zone, first static records + for(auto &item : dom.records) { + // ensure we have parent in records + DNSName name = item.first; + while(name.chopOff() && name.isPartOf(dom.domain)) { + if (dom.records.find(name) == dom.records.end() && !dom.services.count(name)) { // don't ENT out a service! + GeoIPDNSResourceRecord rr; + vector rrs; + rr.domain_id = dom.id; + rr.ttl = dom.ttl; + rr.qname = name; + rr.qtype = QType(0); // empty non terminal + rr.content = ""; + rr.auth = 1; + rr.weight = 100; + rr.has_weight = false; + rrs.push_back(rr); + std::swap(dom.records[name], rrs); + } + } + } + + // then services + for(auto &item : dom.services) { + // ensure we have parent in records + DNSName name = item.first; + while(name.chopOff() && name.isPartOf(dom.domain)) { + if (dom.records.find(name) == dom.records.end()) { + GeoIPDNSResourceRecord rr; + vector rrs; + rr.domain_id = dom.id; + rr.ttl = dom.ttl; + rr.qname = name; + rr.qtype = QType(0); + rr.content = ""; + rr.auth = 1; + rr.weight = 100; + rr.has_weight = false; + rrs.push_back(rr); + std::swap(dom.records[name], rrs); + } + } + } + + // finally fix weights + for(auto &item: dom.records) { + map weights; + map sums; + map lasts; + bool has_weight=false; + // first we look for used weight + for(const auto &rr: item.second) { + weights[rr.qtype.getCode()] += rr.weight; + if (rr.has_weight) has_weight = true; + } + if (has_weight) { + // put them back as probabilities and values.. + for(auto &rr: item.second) { + uint16_t rr_type = rr.qtype.getCode(); + rr.weight=static_cast((static_cast(rr.weight) / weights[rr_type])*1000.0); + sums[rr_type] += rr.weight; + rr.has_weight = has_weight; + lasts[rr_type] = rr; + } + // remove rounding gap + for(auto &x: lasts) { + float sum = sums[x.first]; + if (sum < 1000) + x.second.weight += (1000-sum); + } + } + } + + tmp_domains.push_back(std::move(dom)); + } + + s_domains.clear(); + std::swap(s_domains, tmp_domains); + + extern std::function g_getGeo; + g_getGeo = getGeoForLua; +} + +GeoIPBackend::~GeoIPBackend() { + try { + WriteLock wl(&s_state_lock); + s_rc--; + if (s_rc == 0) { // last instance gets to cleanup + s_geoip_files.clear(); + s_domains.clear(); + } + } + catch(...) { + } +} + +bool GeoIPBackend::lookup_static(const GeoIPDomain &dom, const DNSName &search, const QType &qtype, const DNSName& qdomain, const std::string &ip, GeoIPNetmask &gl, bool v6) { + const auto& i = dom.records.find(search); + map cumul_probabilities; + int probability_rnd = 1+(dns_random(1000)); // setting probability=0 means it never is used + + if (i != dom.records.end()) { // return static value + for(const auto& rr : i->second) { + if (qtype != QType::ANY && rr.qtype != qtype) continue; + + if (rr.has_weight) { + gl.netmask = (v6?128:32); + int comp = cumul_probabilities[rr.qtype.getCode()]; + cumul_probabilities[rr.qtype.getCode()] += rr.weight; + if (rr.weight == 0 || probability_rnd < comp || probability_rnd > (comp + rr.weight)) + continue; + } + const string& content = format2str(rr.content, ip, v6, gl); + if (rr.qtype != QType::ENT && rr.qtype != QType::TXT && content.empty()) continue; + d_result.push_back(rr); + d_result.back().content = content; + d_result.back().qname = qdomain; + } + // ensure we get most strict netmask + for(DNSResourceRecord& rr: d_result) { + rr.scopeMask = gl.netmask; + } + return true; // no need to go further + } + + return false; +}; + +void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, DNSPacket *pkt_p, int zoneId) { + ReadLock rl(&s_state_lock); + const GeoIPDomain* dom; + GeoIPNetmask gl; + bool found = false; + + if (d_result.size()>0) + throw PDNSException("Cannot perform lookup while another is running"); + + d_result.clear(); + + if (zoneId > -1 && zoneId < static_cast(s_domains.size())) + dom = &(s_domains[zoneId]); + else { + for(const GeoIPDomain& i : s_domains) { // this is arguably wrong, we should probably find the most specific match + if (qdomain.isPartOf(i.domain)) { + dom = &i; + found = true; + break; + } + } + if (!found) return; // not found + } + + string ip = "0.0.0.0"; + bool v6 = false; + if (pkt_p != NULL) { + ip = pkt_p->getRealRemote().toStringNoMask(); + v6 = pkt_p->getRealRemote().isIpv6(); + } + + gl.netmask = 0; + + (void)this->lookup_static(*dom, qdomain, qtype, qdomain, ip, gl, v6); + + const auto& target = (*dom).services.find(qdomain); + if (target == (*dom).services.end()) return; // no hit + + const NetmaskTree >::node_type* node = target->second.masks.lookup(ComboAddress(ip)); + if (node == NULL) return; // no hit, again. + + DNSName sformat; + gl.netmask = node->first.getBits(); + // figure out smallest sensible netmask + if (gl.netmask == 0) { + GeoIPNetmask tmp_gl; + tmp_gl.netmask = 0; + // get netmask from geoip backend + if (queryGeoIP(ip, v6, GeoIPInterface::Name, tmp_gl) == "unknown") { + if (v6) + gl.netmask = target->second.netmask6; + else + gl.netmask = target->second.netmask4; + } + } else { + if (v6) + gl.netmask = target->second.netmask6; + else + gl.netmask = target->second.netmask4; + } + + // note that this means the array format won't work with indirect + for(auto it = node->second.begin(); it != node->second.end(); it++) { + sformat = DNSName(format2str(*it, ip, v6, gl)); + + // see if the record can be found + if (this->lookup_static((*dom), sformat, qtype, qdomain, ip, gl, v6)) + return; + } + + if (!d_result.empty()) { + g_log<id; + rr.qtype = QType::CNAME; + rr.qname = qdomain; + rr.content = sformat.toString(); + rr.auth = 1; + rr.ttl = dom->ttl; + rr.scopeMask = gl.netmask; + d_result.push_back(rr); +} + +bool GeoIPBackend::get(DNSResourceRecord &r) { + if (d_result.empty()) return false; + + r = d_result.back(); + d_result.pop_back(); + + return true; +} + +static string queryGeoIP(const string &ip, bool v6, GeoIPInterface::GeoIPQueryAttribute attribute, GeoIPNetmask& gl) { + string ret = "unknown"; + + for(auto const& gi: s_geoip_files) { + string val; + bool found = false; + + switch(attribute) { + case GeoIPInterface::ASn: + if (v6) found = gi->queryASnumV6(val, gl, ip); + else found =gi->queryASnum(val, gl, ip); + break; + case GeoIPInterface::Name: + if (v6) found = gi->queryNameV6(val, gl, ip); + else found = gi->queryName(val, gl, ip); + break; + case GeoIPInterface::Continent: + if (v6) found = gi->queryContinentV6(val, gl, ip); + else found = gi->queryContinent(val, gl, ip); + break; + case GeoIPInterface::Region: + if (v6) found = gi->queryRegionV6(val, gl, ip); + else found = gi->queryRegion(val, gl, ip); + break; + case GeoIPInterface::Country: + if (v6) found = gi->queryCountryV6(val, gl, ip); + else found = gi->queryCountry(val, gl, ip); + break; + case GeoIPInterface::Country2: + if (v6) found = gi->queryCountry2V6(val, gl, ip); + else found = gi->queryCountry2(val, gl, ip); + break; + case GeoIPInterface::City: + if (v6) found = gi->queryCityV6(val, gl, ip); + else found = gi->queryCity(val, gl, ip); + break; + case GeoIPInterface::Location: + double lat=0, lon=0; + boost::optional alt, prec; + if (v6) found = gi->queryLocationV6(gl, ip, lat, lon, alt, prec); + else found = gi->queryLocation(gl, ip, lat, lon, alt, prec); + val = std::to_string(lat)+" "+std::to_string(lon); + break; + } + + if (!found || val.empty() || val == "--") continue; // try next database + ret = val; + std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower); + break; + } + + if (ret == "unknown") gl.netmask = (v6?128:32); // prevent caching + return ret; +} + +string getGeoForLua(const std::string& ip, int qaint) +{ + GeoIPInterface::GeoIPQueryAttribute qa((GeoIPInterface::GeoIPQueryAttribute)qaint); + try { + GeoIPNetmask gl; + string res=queryGeoIP(ip, false, qa, gl); + // cout<<"Result for "<& alt, boost::optional& prec) +{ + for(auto const& gi: s_geoip_files) { + string val; + if (v6) { + if (gi->queryLocationV6(gl, ip, lat, lon, alt, prec)) + return true; + } else if (gi->queryLocation(gl, ip, lat, lon, alt, prec)) + return true; + } + return false; +} + +string GeoIPBackend::format2str(string sformat, const string& ip, bool v6, GeoIPNetmask& gl) { + string::size_type cur,last; + boost::optional alt, prec; + double lat, lon; + time_t t = time((time_t*)NULL); + GeoIPNetmask tmp_gl; // largest wins + struct tm gtm; + gmtime_r(&t, >m); + last=0; + + while((cur = sformat.find("%", last)) != string::npos) { + string rep; + int nrep=3; + tmp_gl.netmask = 0; + if (!sformat.compare(cur,3,"%cn")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::Continent, tmp_gl); + } else if (!sformat.compare(cur,3,"%co")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::Country, tmp_gl); + } else if (!sformat.compare(cur,3,"%cc")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::Country2, tmp_gl); + } else if (!sformat.compare(cur,3,"%af")) { + rep = (v6?"v6":"v4"); + } else if (!sformat.compare(cur,3,"%as")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::ASn, tmp_gl); + } else if (!sformat.compare(cur,3,"%re")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::Region, tmp_gl); + } else if (!sformat.compare(cur,3,"%na")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::Name, tmp_gl); + } else if (!sformat.compare(cur,3,"%ci")) { + rep = queryGeoIP(ip, v6, GeoIPInterface::City, tmp_gl); + } else if (!sformat.compare(cur,4,"%loc")) { + char ns, ew; + int d1, d2, m1, m2; + double s1, s2; + if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) { + rep = ""; + } else { + ns = (lat>0) ? 'N' : 'S'; + ew = (lon>0) ? 'E' : 'W'; + /* remove sign */ + lat = fabs(lat); + lon = fabs(lon); + d1 = static_cast(lat); + d2 = static_cast(lon); + m1 = static_cast((lat - d1)*60.0); + m2 = static_cast((lon - d2)*60.0); + s1 = static_cast(lat - d1 - m1/60.0)*3600.0; + s2 = static_cast(lon - d2 - m2/60.0)*3600.0; + rep = str(boost::format("%d %d %0.3f %c %d %d %0.3f %c") % + d1 % m1 % s1 % ns % d2 % m2 % s2 % ew); + if (alt) + rep = rep + str(boost::format(" %d.00") % *alt); + else + rep = rep + string(" 0.00"); + if (prec) + rep = rep + str(boost::format(" %dm") % *prec); + } + nrep = 4; + } else if (!sformat.compare(cur,4,"%lat")) { + if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) { + rep = ""; + } else { + rep = str(boost::format("%lf") % lat); + } + nrep = 4; + } else if (!sformat.compare(cur,4,"%lon")) { + if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) { + rep = ""; + } else { + rep = str(boost::format("%lf") % lon); + } + nrep = 4; + } else if (!sformat.compare(cur,3,"%hh")) { + rep = boost::str(boost::format("%02d") % gtm.tm_hour); + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,3,"%yy")) { + rep = boost::str(boost::format("%02d") % (gtm.tm_year + 1900)); + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,3,"%dd")) { + rep = boost::str(boost::format("%02d") % (gtm.tm_yday + 1)); + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,4,"%wds")) { + nrep=4; + rep = GeoIP_WEEKDAYS[gtm.tm_wday]; + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,4,"%mos")) { + nrep=4; + rep = GeoIP_MONTHS[gtm.tm_mon]; + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,3,"%wd")) { + rep = boost::str(boost::format("%02d") % (gtm.tm_wday + 1)); + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,3,"%mo")) { + rep = boost::str(boost::format("%02d") % (gtm.tm_mon + 1)); + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,4,"%ip6")) { + nrep = 4; + if (v6) + rep = ip; + else + rep = ""; + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,4,"%ip4")) { + nrep = 4; + if (!v6) + rep = ip; + else + rep = ""; + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,3,"%ip")) { + rep = ip; + tmp_gl.netmask = (v6?128:32); + } else if (!sformat.compare(cur,2,"%%")) { + last = cur + 2; continue; + } else { + last = cur + 1; continue; + } + if (tmp_gl.netmask > gl.netmask) gl.netmask = tmp_gl.netmask; + sformat.replace(cur, nrep, rep); + last = cur + rep.size(); // move to next attribute + } + return sformat; +} + +void GeoIPBackend::reload() { + WriteLock wl(&s_state_lock); + + try { + initialize(); + } catch (PDNSException &pex) { + g_log<getSOA(domain, sd); + di.id = dom.id; + di.zone = dom.domain; + di.serial = sd.serial; + di.kind = DomainInfo::Native; + di.backend = this; + return true; + } + } + return false; +} + +bool GeoIPBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { + if (!d_dnssec) return false; + + ReadLock rl(&s_state_lock); + for(GeoIPDomain dom : s_domains) { + if (dom.domain == name) { + if (hasDNSSECkey(dom.domain)) { + meta[string("NSEC3NARROW")].push_back("1"); + meta[string("NSEC3PARAM")].push_back("1 0 1 f95a"); + } + return true; + } + } + return false; +} + +bool GeoIPBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { + if (!d_dnssec) return false; + + ReadLock rl(&s_state_lock); + for(GeoIPDomain dom : s_domains) { + if (dom.domain == name) { + if (hasDNSSECkey(dom.domain)) { + if (kind == "NSEC3NARROW") + meta.push_back(string("1")); + if (kind == "NSEC3PARAM") + meta.push_back(string("1 0 1 f95a")); + } + return true; + } + } + return false; +} + +bool GeoIPBackend::getDomainKeys(const DNSName& name, std::vector& keys) { + if (!d_dnssec) return false; + ReadLock rl(&s_state_lock); + for(GeoIPDomain dom : s_domains) { + if (dom.domain == name) { + regex_t reg; + regmatch_t regm[5]; + regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE|REG_EXTENDED); + ostringstream pathname; + pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "*.key"; + glob_t glob_result; + if (glob(pathname.str().c_str(),GLOB_ERR,NULL,&glob_result) == 0) { + for(size_t i=0;i0) { + content << string(buffer, ifs.gcount()); + } + } + ifs.close(); + kd.content = content.str(); + keys.push_back(kd); + } + } + } + regfree(®); + globfree(&glob_result); + return true; + } + } + return false; +} + +bool GeoIPBackend::removeDomainKey(const DNSName& name, unsigned int id) { + if (!d_dnssec) return false; + WriteLock rl(&s_state_lock); + ostringstream path; + + for(GeoIPDomain dom : s_domains) { + if (dom.domain == name) { + regex_t reg; + regmatch_t regm[5]; + regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE|REG_EXTENDED); + ostringstream pathname; + pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "*.key"; + glob_t glob_result; + if (glob(pathname.str().c_str(),GLOB_ERR,NULL,&glob_result) == 0) { + for(size_t i=0;i= nextid) nextid = kid+1; + } + } + } + regfree(®); + globfree(&glob_result); + pathname.str(""); + pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "." << key.flags << "." << nextid << "." << (key.active?"1":"0") << ".key"; + ofstream ofs(pathname.str().c_str()); + ofs.write(key.content.c_str(), key.content.size()); + ofs.close(); + id = nextid; + return true; + } + } + return false; + +} + +bool GeoIPBackend::activateDomainKey(const DNSName& name, unsigned int id) { + if (!d_dnssec) return false; + WriteLock rl(&s_state_lock); + for(GeoIPDomain dom : s_domains) { + if (dom.domain == name) { + regex_t reg; + regmatch_t regm[5]; + regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE|REG_EXTENDED); + ostringstream pathname; + pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "*.key"; + glob_t glob_result; + if (glob(pathname.str().c_str(),GLOB_ERR,NULL,&glob_result) == 0) { + for(size_t i=0;i +#include +#include +#include +#include +#include + +#include "pdns/dnspacket.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/lock.hh" + +class GeoIPInterface; + +struct GeoIPDomain; + +struct GeoIPNetmask { + int netmask; +}; + +class GeoIPBackend: public DNSBackend { +public: + GeoIPBackend(const std::string& suffix=""); + ~GeoIPBackend(); + + void lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1) override; + bool list(const DNSName &target, int domain_id, bool include_disabled=false) override { return false; } // not supported + bool get(DNSResourceRecord &r) override; + void reload() override; + void rediscover(string *status = 0) override; + bool getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial=true) override; + + // dnssec support + bool doesDNSSEC() override { return d_dnssec; }; + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool getDomainKeys(const DNSName& name, std::vector& keys) override; + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + +private: + static pthread_rwlock_t s_state_lock; + + void initialize(); + string format2str(string format, const string& ip, bool v6, GeoIPNetmask& gl); + bool d_dnssec; + bool hasDNSSECkey(const DNSName& name); + bool lookup_static(const GeoIPDomain &dom, const DNSName &search, const QType &qtype, const DNSName& qdomain, const std::string &ip, GeoIPNetmask& gl, bool v6); + vector d_result; + vector d_files; +}; + +#endif /* PDNS_GEOIPBACKEND_HH */ diff --git a/modules/geoipbackend/geoipinterface-dat.cc b/modules/geoipbackend/geoipinterface-dat.cc new file mode 100644 index 0000000..87e261c --- /dev/null +++ b/modules/geoipbackend/geoipinterface-dat.cc @@ -0,0 +1,481 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "geoipbackend.hh" +#include "geoipinterface.hh" +#ifdef HAVE_GEOIP +#include "GeoIPCity.h" +#include "GeoIP.h" + +struct geoip_deleter { + void operator()(GeoIP* ptr) { + if (ptr) { + GeoIP_delete(ptr); + } + }; +}; + +struct geoiprecord_deleter { + void operator()(GeoIPRecord* ptr) { + if (ptr) { + GeoIPRecord_delete(ptr); + } + } +}; + +struct geoipregion_deleter { + void operator()(GeoIPRegion* ptr) { + if (ptr) { + GeoIPRegion_delete(ptr); + } + } +}; + +class GeoIPInterfaceDAT : public GeoIPInterface { +public: + GeoIPInterfaceDAT(const string &fname, const string &modeStr) { + int flags; + if (modeStr == "standard") + flags = GEOIP_STANDARD; + else if (modeStr == "memory") + flags = GEOIP_MEMORY_CACHE; + else if (modeStr == "index") + flags = GEOIP_INDEX_CACHE; +#ifdef HAVE_MMAP + else if (modeStr == "mmap") + flags = GEOIP_MMAP_CACHE; +#endif + else + throw PDNSException("Invalid cache mode " + modeStr + " for GeoIP backend"); + + d_gi = std::unique_ptr(GeoIP_open(fname.c_str(), flags)); + if (d_gi.get() == nullptr) + throw PDNSException("Cannot open GeoIP database " + fname); + d_db_type = GeoIP_database_edition(d_gi.get()); + } + + bool queryCountry(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + int id; + if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_code3_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_code3_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + ret = gir->country_code3; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryCountryV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + int id; + if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_code3_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_code3_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + ret = gir->country_code3; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryCountry2(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + int id; + if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_code_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_code_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + ret = gir->country_code; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryCountry2V6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + int id; + if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_code_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_code_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + ret = gir->country_code; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryContinent(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + int id; + if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_continent_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + ret = ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryContinentV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || + d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + int id; + if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { + ret = GeoIP_continent_by_id(id); + gl.netmask = tmp_gl.netmask; + return true; + } + } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryName(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_ISP_EDITION || + d_db_type == GEOIP_ORG_EDITION) { + char* result = GeoIP_name_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl); + if (result != nullptr) { + ret = result; + free(result); + gl.netmask = tmp_gl.netmask; + // reduce space to dash + ret = boost::replace_all_copy(ret, " ", "-"); + return true; + } + + } + return false; + } + + bool queryNameV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_ISP_EDITION_V6 || + d_db_type == GEOIP_ORG_EDITION_V6) { + char* result = GeoIP_name_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl); + if (result != nullptr) { + ret = result; + free(result); + gl.netmask = tmp_gl.netmask; + // reduce space to dash + ret = boost::replace_all_copy(ret, " ", "-"); + return true; + } + } + return false; + } + + bool queryASnum(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_ASNUM_EDITION) { + char* result = GeoIP_name_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl); + if (result != nullptr) { + std::string val(result); + vector asnr; + free(result); + stringtok(asnr, val); + if(asnr.size()>0) { + gl.netmask = tmp_gl.netmask; + ret = asnr[0]; + return true; + } + } + } + return false; + } + + bool queryASnumV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_ASNUM_EDITION_V6) { + char* result = GeoIP_name_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl); + if (result != nullptr) { + std::string val(result); + vector asnr; + free(result); + stringtok(asnr, val); + if(asnr.size()>0) { + gl.netmask = tmp_gl.netmask; + ret = asnr[0]; + return true; + } + } + } + return false; + } + + bool queryRegion(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = valueOrEmpty(gir->region); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + ret = valueOrEmpty(gir->region); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryRegionV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + GeoIPLookup tmp_gl = { + .netmask = gl.netmask, + }; + if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + if (gir) { + gl.netmask = tmp_gl.netmask; + ret = valueOrEmpty(gir->region); + return true; + } + } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + ret = valueOrEmpty(gir->region); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryCity(string &ret, GeoIPNetmask& gl, const string &ip) override { + if (d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + ret = valueOrEmpty(gir->city); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryCityV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + ret = valueOrEmpty(gir->city); + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryLocationV6(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1 || + d_db_type == GEOIP_CITY_EDITION_REV0_V6 || + d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); + if (gir) { + latitude = gir->latitude; + longitude = gir->longitude; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + bool queryLocation(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || + d_db_type == GEOIP_REGION_EDITION_REV1 || + d_db_type == GEOIP_CITY_EDITION_REV0 || + d_db_type == GEOIP_CITY_EDITION_REV1) { + std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); + if (gir) { + latitude = gir->latitude; + longitude = gir->longitude; + gl.netmask = gir->netmask; + return true; + } + } + return false; + } + + ~GeoIPInterfaceDAT() { } +private: + unsigned int d_db_type; + unique_ptr d_gi; +}; + +unique_ptr GeoIPInterface::makeDATInterface(const string &fname, const map& opts) { + string mode = "standard"; + const auto &opt = opts.find("mode"); + if (opt != opts.end()) + mode = opt->second; + return unique_ptr(new GeoIPInterfaceDAT(fname, mode)); +} + +#else + +unique_ptr GeoIPInterface::makeDATInterface(const string &fname, const map& opts) { + throw PDNSException("libGeoIP support not compiled in"); +} + +#endif diff --git a/modules/geoipbackend/geoipinterface-mmdb.cc b/modules/geoipbackend/geoipinterface-mmdb.cc new file mode 100644 index 0000000..44cb98a --- /dev/null +++ b/modules/geoipbackend/geoipinterface-mmdb.cc @@ -0,0 +1,278 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "geoipbackend.hh" +#include "geoipinterface.hh" + +#ifdef HAVE_MMDB + +#include "maxminddb.h" + +class GeoIPInterfaceMMDB : public GeoIPInterface { +public: + GeoIPInterfaceMMDB(const string &fname, const string &modeStr, const string& language) { + int ec; + int flags = 0; + if (modeStr == "") + /* for the benefit of ifdef */ + ; +#ifdef HAVE_MMAP + else if (modeStr == "mmap") + flags |= MMDB_MODE_MMAP; +#endif + else + throw PDNSException(string("Unsupported mode ") + modeStr + ("for geoipbackend-mmdb")); + memset(&d_s, 0, sizeof(d_s)); + if ((ec = MMDB_open(fname.c_str(), flags, &d_s)) < 0) + throw PDNSException(string("Cannot open ") + fname + string(": ") + string(MMDB_strerror(ec))); + d_lang = language; + g_log<& alt, boost::optional& prec) override { + MMDB_entry_data_s data; + MMDB_lookup_result_s res; + if (!mmdbLookup(ip, false, gl, res)) + return false; + if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + latitude = data.double_value; + if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + longitude = data.double_value; + if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + prec = data.uint16; + return true; + } + + bool queryLocationV6(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override { + MMDB_entry_data_s data; + MMDB_lookup_result_s res; + if (!mmdbLookup(ip, true, gl, res)) + return false; + if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + latitude = data.double_value; + if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + longitude = data.double_value; + if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data) + return false; + prec = data.uint16; + return true; + } + + ~GeoIPInterfaceMMDB() { MMDB_close(&d_s); }; +private: + MMDB_s d_s; + string d_lang; + + bool mmdbLookup(const string &ip, bool v6, GeoIPNetmask& gl, MMDB_lookup_result_s& res) { + int gai_ec = 0, mmdb_ec = 0; + res = MMDB_lookup_string(&d_s, ip.c_str(), &gai_ec, &mmdb_ec); + + if (gai_ec != 0) + g_log< [0,32] range */ + if (!v6 && gl.netmask > 32) + gl.netmask -= 96; + return true; + } + return false; + } +}; + +unique_ptr GeoIPInterface::makeMMDBInterface(const string &fname, const map& opts) { + string mode = ""; + string language = "en"; + const auto &opt_mode = opts.find("mode"); + if (opt_mode != opts.end()) + mode = opt_mode->second; + const auto &opt_lang = opts.find("language"); + if (opt_lang != opts.end()) + language = opt_lang->second; + return unique_ptr(new GeoIPInterfaceMMDB(fname, mode, language)); +} + +#else + +unique_ptr GeoIPInterface::makeMMDBInterface(const string &fname, const map& opts) { + throw PDNSException("libmaxminddb support not compiled in"); +} + +#endif diff --git a/modules/geoipbackend/geoipinterface.cc b/modules/geoipbackend/geoipinterface.cc new file mode 100644 index 0000000..0f0f8a2 --- /dev/null +++ b/modules/geoipbackend/geoipinterface.cc @@ -0,0 +1,67 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "geoipbackend.hh" +#include "geoipinterface.hh" + +unique_ptr GeoIPInterface::makeInterface(const string& dbStr) { + /* parse dbStr */ + map opts; + vector parts1, parts2; + string driver; + string filename; + stringtok(parts1, dbStr, ":"); + + if (parts1.size() == 1) { + stringtok(parts2, parts1[0], ";"); + /* try extension */ + filename = parts2[0]; + size_t pos = filename.find_last_of("."); + if (pos != string::npos) + driver = filename.substr(pos+1); + else + driver = "unknown"; + } else { + driver = parts1[0]; + stringtok(parts2, parts1[1], ";"); + filename = parts2[0]; + } + + if (parts2.size() > 1) { + parts2.erase(parts2.begin(), parts2.begin()+1); + for(const auto &opt: parts2) { + vector kv; + stringtok(kv, opt, "="); + opts[kv[0]] = kv[1]; + } + } + + if (driver == "dat") { + return makeDATInterface(filename, opts); + } else if (driver == "mmdb") { + return makeMMDBInterface(filename, opts); + } else { + throw PDNSException(string("Unsupported file type '") + driver + string("' (use type: prefix to force type)")); + } +} diff --git a/modules/geoipbackend/geoipinterface.hh b/modules/geoipbackend/geoipinterface.hh new file mode 100644 index 0000000..7b1e180 --- /dev/null +++ b/modules/geoipbackend/geoipinterface.hh @@ -0,0 +1,71 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_GEOIPINTERFACE_HH +#define PDNS_GEOIPINTERFACE_HH + +#include "boost/optional.hpp" + +#include "geoipbackend.hh" + +class GeoIPInterface { +public: + enum GeoIPQueryAttribute { + ASn, + City, + Continent, + Country, + Country2, + Name, + Region, + Location + }; + + virtual bool queryCountry(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryCountryV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryCountry2(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryCountry2V6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryContinent(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryContinentV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryName(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryNameV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryASnum(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryASnumV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryRegion(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryRegionV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryCity(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryCityV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; + virtual bool queryLocation(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) = 0; + virtual bool queryLocationV6(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) = 0; + + virtual ~GeoIPInterface() { } + + static unique_ptr makeInterface(const string& dbStr); +private: + static unique_ptr makeMMDBInterface(const string &fname, const map& opts); + static unique_ptr makeDATInterface(const string& fname, const map& opts); +}; + +#endif diff --git a/modules/gmysqlbackend/3.4.0_to_4.1.0_schema.mysql.sql b/modules/gmysqlbackend/3.4.0_to_4.1.0_schema.mysql.sql new file mode 100644 index 0000000..108b36c --- /dev/null +++ b/modules/gmysqlbackend/3.4.0_to_4.1.0_schema.mysql.sql @@ -0,0 +1,21 @@ +ALTER TABLE domains MODIFY account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL; +ALTER TABLE domains CHARACTER SET 'latin1'; + +ALTER TABLE records MODIFY id BIGINT AUTO_INCREMENT; +ALTER TABLE records CHARACTER SET 'latin1'; +CREATE INDEX ordername ON records (ordername); +DROP INDEX recordorder ON records; + +ALTER TABLE supermasters MODIFY account VARCHAR(40) CHARACTER SET 'utf8' NOT NULL; +ALTER TABLE supermasters CHARACTER SET 'latin1'; + +ALTER TABLE comments MODIFY account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL; +ALTER TABLE comments MODIFY comment TEXT CHARACTER SET 'utf8' NOT NULL; +ALTER TABLE comments CHARACTER SET 'latin1'; +DROP INDEX comments_domain_id_idx ON comments; + +ALTER TABLE domainmetadata CHARACTER SET 'latin1'; + +ALTER TABLE cryptokeys CHARACTER SET 'latin1'; + +ALTER TABLE tsigkeys CHARACTER SET 'latin1'; diff --git a/modules/gmysqlbackend/4.1.0_to_4.2.0_schema.mysql.sql b/modules/gmysqlbackend/4.1.0_to_4.2.0_schema.mysql.sql new file mode 100644 index 0000000..01efae9 --- /dev/null +++ b/modules/gmysqlbackend/4.1.0_to_4.2.0_schema.mysql.sql @@ -0,0 +1,3 @@ +ALTER TABLE domains MODIFY notified_serial INT UNSIGNED DEFAULT NULL; + +ALTER TABLE records DROP COLUMN change_date; diff --git a/modules/gmysqlbackend/Makefile.am b/modules/gmysqlbackend/Makefile.am new file mode 100644 index 0000000..de168aa --- /dev/null +++ b/modules/gmysqlbackend/Makefile.am @@ -0,0 +1,24 @@ +AM_CPPFLAGS += $(MYSQL_CFLAGS) + +pkglib_LTLIBRARIES = libgmysqlbackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.mysql.sql \ + nodnssec-3.x_to_3.4.0_schema.mysql.sql \ + schema.mysql.sql + +dist_doc_DATA = \ + dnssec-3.x_to_3.4.0_schema.mysql.sql \ + nodnssec-3.x_to_3.4.0_schema.mysql.sql \ + 3.4.0_to_4.1.0_schema.mysql.sql \ + 4.1.0_to_4.2.0_schema.mysql.sql \ + schema.mysql.sql + +libgmysqlbackend_la_SOURCES = \ + gmysqlbackend.cc gmysqlbackend.hh \ + smysql.cc smysql.hh + +libgmysqlbackend_la_LDFLAGS = -module -avoid-version +libgmysqlbackend_la_LIBADD = $(MYSQL_LIBS) diff --git a/modules/gmysqlbackend/Makefile.in b/modules/gmysqlbackend/Makefile.in new file mode 100644 index 0000000..7c10383 --- /dev/null +++ b/modules/gmysqlbackend/Makefile.in @@ -0,0 +1,868 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/gmysqlbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgmysqlbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libgmysqlbackend_la_OBJECTS = gmysqlbackend.lo smysql.lo +libgmysqlbackend_la_OBJECTS = $(am_libgmysqlbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgmysqlbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgmysqlbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgmysqlbackend_la_SOURCES) +DIST_SOURCES = $(libgmysqlbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(MYSQL_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libgmysqlbackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.mysql.sql \ + nodnssec-3.x_to_3.4.0_schema.mysql.sql \ + schema.mysql.sql + +dist_doc_DATA = \ + dnssec-3.x_to_3.4.0_schema.mysql.sql \ + nodnssec-3.x_to_3.4.0_schema.mysql.sql \ + 3.4.0_to_4.1.0_schema.mysql.sql \ + 4.1.0_to_4.2.0_schema.mysql.sql \ + schema.mysql.sql + +libgmysqlbackend_la_SOURCES = \ + gmysqlbackend.cc gmysqlbackend.hh \ + smysql.cc smysql.hh + +libgmysqlbackend_la_LDFLAGS = -module -avoid-version +libgmysqlbackend_la_LIBADD = $(MYSQL_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/gmysqlbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/gmysqlbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgmysqlbackend.la: $(libgmysqlbackend_la_OBJECTS) $(libgmysqlbackend_la_DEPENDENCIES) $(EXTRA_libgmysqlbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgmysqlbackend_la_LINK) -rpath $(pkglibdir) $(libgmysqlbackend_la_OBJECTS) $(libgmysqlbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmysqlbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smysql.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/gmysqlbackend/OBJECTFILES b/modules/gmysqlbackend/OBJECTFILES new file mode 100644 index 0000000..98bf556 --- /dev/null +++ b/modules/gmysqlbackend/OBJECTFILES @@ -0,0 +1 @@ +gmysqlbackend.lo smysql.lo diff --git a/modules/gmysqlbackend/OBJECTLIBS b/modules/gmysqlbackend/OBJECTLIBS new file mode 100644 index 0000000..11d4311 --- /dev/null +++ b/modules/gmysqlbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(MYSQL_LIBS) diff --git a/modules/gmysqlbackend/dnssec-3.x_to_3.4.0_schema.mysql.sql b/modules/gmysqlbackend/dnssec-3.x_to_3.4.0_schema.mysql.sql new file mode 100644 index 0000000..c65c865 --- /dev/null +++ b/modules/gmysqlbackend/dnssec-3.x_to_3.4.0_schema.mysql.sql @@ -0,0 +1,36 @@ +/* Uncomment next 3 lines for versions <= 3.1 */ +/* DROP INDEX rec_name_index ON records; */ +/* DROP INDEX orderindex ON records; */ +/* CREATE INDEX recordorder ON records (domain_id, ordername); */ + +ALTER TABLE records ADD disabled TINYINT(1) DEFAULT 0 AFTER change_date; +ALTER TABLE records MODIFY content VARCHAR(64000) DEFAULT NULL; +ALTER TABLE records MODIFY ordername VARCHAR(255) BINARY DEFAULT NULL; +ALTER TABLE records MODIFY auth TINYINT(1) DEFAULT 1; +ALTER TABLE records MODIFY type VARCHAR(10); +ALTER TABLE supermasters MODIFY ip VARCHAR(64) NOT NULL; +ALTER TABLE supermasters ADD PRIMARY KEY(ip, nameserver); +ALTER TABLE supermasters MODIFY account VARCHAR(40) NOT NULL; +ALTER TABLE domainmetadata MODIFY kind VARCHAR(32); +ALTER TABLE tsigkeys MODIFY algorithm VARCHAR(50); +ALTER TABLE domainmetadata ENGINE=InnoDB; +ALTER TABLE cryptokeys ENGINE=InnoDB; +ALTER TABLE tsigkeys ENGINE=InnoDB; + +DROP INDEX domainmetaidindex ON domainmetadata; +CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); + +CREATE TABLE comments ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) NOT NULL, + comment VARCHAR(64000) NOT NULL, + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); diff --git a/modules/gmysqlbackend/gmysqlbackend.cc b/modules/gmysqlbackend/gmysqlbackend.cc new file mode 100644 index 0000000..22bfeae --- /dev/null +++ b/modules/gmysqlbackend/gmysqlbackend.cc @@ -0,0 +1,184 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "gmysqlbackend.hh" +#include "smysql.hh" +#include + +gMySQLBackend::gMySQLBackend(const string &mode, const string &suffix) : GSQLBackend(mode,suffix) +{ + try { + reconnect(); + } + + catch(SSqlException &e) { + g_log< ? and domain_id=? and disabled=0 and ordername is not null order by 1 asc limit 1"); + declare(suffix, "get-order-last-query", "DNSSEC Ordering Query, last", "select ordername, name from records where ordername != '' and domain_id=? and disabled=0 and ordername is not null order by 1 desc limit 1"); + + declare(suffix, "update-ordername-and-auth-query", "DNSSEC update ordername and auth for a qname query", "update records set ordername=?,auth=? where domain_id=? and name=? and disabled=0"); + declare(suffix, "update-ordername-and-auth-type-query", "DNSSEC update ordername and auth for a rrset query", "update records set ordername=?,auth=? where domain_id=? and name=? and type=? and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and type=? and disabled=0"); + + declare(suffix,"update-master-query","", "update domains set master=? where name=?"); + declare(suffix,"update-kind-query","", "update domains set type=? where name=?"); + declare(suffix,"update-account-query","", "update domains set account=? where name=?"); + declare(suffix,"update-serial-query","", "update domains set notified_serial=? where id=?"); + declare(suffix,"update-lastcheck-query","", "update domains set last_check=? where id=?"); + declare(suffix,"info-all-master-query","", "select d.id, d.name, d.notified_serial, r.content from records r join domains d on r.name=d.name where r.type='SOA' and r.disabled=0 and d.type='MASTER'"); + declare(suffix,"delete-domain-query","", "delete from domains where name=?"); + declare(suffix,"delete-zone-query","", "delete from records where domain_id=?"); + declare(suffix,"delete-rrset-query","","delete from records where domain_id=? and name=? and type=?"); + declare(suffix,"delete-names-query","","delete from records where domain_id=? and name=?"); + + declare(suffix,"add-domain-key-query","", "insert into cryptokeys (domain_id, flags, active, content) select id, ?, ?, ? from domains where name=?"); + declare(suffix,"get-last-inserted-key-id-query", "", "select LAST_INSERT_ID()"); + declare(suffix,"list-domain-keys-query","", "select cryptokeys.id, flags, active, content from domains, cryptokeys where cryptokeys.domain_id=domains.id and name=?"); + declare(suffix,"get-all-domain-metadata-query","", "select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=?"); + declare(suffix,"get-domain-metadata-query","", "select content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=? and domainmetadata.kind=?"); + declare(suffix,"clear-domain-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=?) and domainmetadata.kind=?"); + declare(suffix,"clear-domain-all-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=?)"); + declare(suffix,"set-domain-metadata-query","", "insert into domainmetadata (domain_id, kind, content) select id, ?, ? from domains where name=?"); + declare(suffix,"activate-domain-key-query","", "update cryptokeys set active=1 where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"deactivate-domain-key-query","", "update cryptokeys set active=0 where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"remove-domain-key-query","", "delete from cryptokeys where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"clear-domain-all-keys-query","", "delete from cryptokeys where domain_id=(select id from domains where name=?)"); + declare(suffix,"get-tsig-key-query","", "select algorithm, secret from tsigkeys where name=?"); + declare(suffix,"set-tsig-key-query","", "replace into tsigkeys (name,algorithm,secret) values(?,?,?)"); + declare(suffix,"delete-tsig-key-query","", "delete from tsigkeys where name=?"); + declare(suffix,"get-tsig-keys-query","", "select name,algorithm, secret from tsigkeys"); + + declare(suffix, "get-all-domains-query", "Retrieve all domains", "select domains.id, domains.name, records.content, domains.type, domains.master, domains.notified_serial, domains.last_check, domains.account from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name WHERE records.disabled=0 OR ?"); + + declare(suffix, "list-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE domain_id=?"); + declare(suffix, "insert-comment-query", "", "INSERT INTO comments (domain_id, name, type, modified_at, account, comment) VALUES (?, ?, ?, ?, ?, ?)"); + declare(suffix, "delete-comment-rrset-query", "", "DELETE FROM comments WHERE domain_id=? AND name=? AND type=?"); + declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=?"); + declare(suffix, "search-records-query", "", record_query+" name LIKE ? OR content LIKE ? LIMIT ?"); + declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE ? OR comment LIKE ? LIMIT ?"); + } + + DNSBackend *make(const string &suffix="") + { + return new gMySQLBackend(d_mode,suffix); + } +private: + const string d_mode; +}; + + +//! Magic class that is activated when the dynamic library is loaded +class gMySQLLoader +{ +public: + //! This reports us to the main UeberBackend class + gMySQLLoader() + { + BackendMakers().report(new gMySQLFactory("gmysql")); + g_log << Logger::Info << "[gmysqlbackend] This is the gmysql backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; +static gMySQLLoader gmysqlloader; diff --git a/modules/gmysqlbackend/gmysqlbackend.hh b/modules/gmysqlbackend/gmysqlbackend.hh new file mode 100644 index 0000000..67f6928 --- /dev/null +++ b/modules/gmysqlbackend/gmysqlbackend.hh @@ -0,0 +1,41 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_GMYSQLBACKEND_HH +#define PDNS_GMYSQLBACKEND_HH + +#include +#include +#include "pdns/backends/gsql/gsqlbackend.hh" + +#include "pdns/namespaces.hh" + +/** The gMySQLBackend is a DNSBackend that can answer DNS related questions. It looks up data + in MySQL */ +class gMySQLBackend : public GSQLBackend +{ +public: + gMySQLBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails. +protected: + void reconnect() override; +}; + +#endif /* PDNS_GMYSQLBACKEND_HH */ diff --git a/modules/gmysqlbackend/nodnssec-3.x_to_3.4.0_schema.mysql.sql b/modules/gmysqlbackend/nodnssec-3.x_to_3.4.0_schema.mysql.sql new file mode 100644 index 0000000..7d25b7c --- /dev/null +++ b/modules/gmysqlbackend/nodnssec-3.x_to_3.4.0_schema.mysql.sql @@ -0,0 +1,63 @@ +/* Uncomment next line for versions <= 3.1 */ +/* DROP INDEX rec_name_index ON records; */ + +ALTER TABLE records ADD disabled TINYINT(1) DEFAULT 0; +ALTER TABLE records MODIFY content VARCHAR(64000) DEFAULT NULL; +ALTER TABLE records ADD ordername VARCHAR(255) BINARY DEFAULT NULL; +ALTER TABLE records ADD auth TINYINT(1) DEFAULT 1; +ALTER TABLE records MODIFY type VARCHAR(10); +ALTER TABLE supermasters MODIFY ip VARCHAR(64) NOT NULL; +ALTER TABLE supermasters MODIFY account VARCHAR(40) NOT NULL; +ALTER TABLE supermasters ADD PRIMARY KEY(ip, nameserver); + +CREATE INDEX recordorder ON records (domain_id, ordername); + + +CREATE TABLE domainmetadata ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + kind VARCHAR(32), + content TEXT, + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); + + +CREATE TABLE cryptokeys ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + flags INT NOT NULL, + active TINYINT(1), + content TEXT, + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INT AUTO_INCREMENT, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); + + +CREATE TABLE comments ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) NOT NULL, + comment VARCHAR(64000) NOT NULL, + PRIMARY KEY(id) +) Engine=InnoDB; + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); diff --git a/modules/gmysqlbackend/schema.mysql.sql b/modules/gmysqlbackend/schema.mysql.sql new file mode 100644 index 0000000..2dea1c2 --- /dev/null +++ b/modules/gmysqlbackend/schema.mysql.sql @@ -0,0 +1,88 @@ +CREATE TABLE domains ( + id INT AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial INT UNSIGNED DEFAULT NULL, + account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL, + PRIMARY KEY (id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE UNIQUE INDEX name_index ON domains(name); + + +CREATE TABLE records ( + id BIGINT AUTO_INCREMENT, + domain_id INT DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(64000) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + disabled TINYINT(1) DEFAULT 0, + ordername VARCHAR(255) BINARY DEFAULT NULL, + auth TINYINT(1) DEFAULT 1, + PRIMARY KEY (id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX ordername ON records (ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) CHARACTER SET 'utf8' NOT NULL, + PRIMARY KEY (ip, nameserver) +) Engine=InnoDB CHARACTER SET 'latin1'; + + +CREATE TABLE comments ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL, + comment TEXT CHARACTER SET 'utf8' NOT NULL, + PRIMARY KEY (id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + kind VARCHAR(32), + content TEXT, + PRIMARY KEY (id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); + + +CREATE TABLE cryptokeys ( + id INT AUTO_INCREMENT, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT, + PRIMARY KEY(id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INT AUTO_INCREMENT, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + PRIMARY KEY (id) +) Engine=InnoDB CHARACTER SET 'latin1'; + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); diff --git a/modules/gmysqlbackend/smysql.cc b/modules/gmysqlbackend/smysql.cc new file mode 100644 index 0000000..aac3183 --- /dev/null +++ b/modules/gmysqlbackend/smysql.cc @@ -0,0 +1,569 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "smysql.hh" +#include +#include +#include "pdns/misc.hh" +#include "pdns/logger.hh" +#include "pdns/dns.hh" +#include "pdns/namespaces.hh" +#include "pdns/lock.hh" + +#if MYSQL_VERSION_ID >= 80000 && !defined(MARIADB_BASE_VERSION) +// Need to keep this for compatibility with MySQL < 8.0.0, which used typedef char my_bool; +// MariaDB up to 10.4 also always define it. +typedef bool my_bool; +#endif + +/* + * Older versions of the MySQL and MariaDB client leak memory + * because they expect the application to call mysql_thread_end() + * when a thread ends. This thread_local static object provides + * that closure, but only when the user has asked for it + * by setting gmysql-thread-cleanup. + * For more discussion, see https://github.com/PowerDNS/pdns/issues/6231 + */ +class MySQLThreadCloser +{ +public: + ~MySQLThreadCloser() { + if(d_enabled) { + mysql_thread_end(); + } + } + void enable() { + d_enabled = true; + } + +private: + bool d_enabled = false; +}; + +static thread_local MySQLThreadCloser threadcloser; + +bool SMySQL::s_dolog; +pthread_mutex_t SMySQL::s_myinitlock = PTHREAD_MUTEX_INITIALIZER; + +class SMySQLStatement: public SSqlStatement +{ +public: + SMySQLStatement(const string& query, bool dolog, int nparams, MYSQL* db) : d_prepared(false) + { + d_db = db; + d_dolog = dolog; + d_query = query; + d_paridx = d_fnum = d_resnum = d_residx = 0; + d_parnum = nparams; + d_req_bind = d_res_bind = NULL; + d_stmt = NULL; + + if (query.empty()) { + return; + } + } + + SSqlStatement* bind(const string& name, bool value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_TINY; + d_req_bind[d_paridx].buffer = new char[1]; + *((char*)d_req_bind[d_paridx].buffer) = (value?1:0); + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, int value) { + return bind(name, (long)value); + } + SSqlStatement* bind(const string& name, uint32_t value) { + return bind(name, (unsigned long)value); + } + SSqlStatement* bind(const string& name, long value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; + d_req_bind[d_paridx].buffer = new long[1]; + *((long*)d_req_bind[d_paridx].buffer) = value; + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, unsigned long value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; + d_req_bind[d_paridx].buffer = new unsigned long[1]; + d_req_bind[d_paridx].is_unsigned = 1; + *((unsigned long*)d_req_bind[d_paridx].buffer) = value; + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, long long value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; + d_req_bind[d_paridx].buffer = new long long[1]; + *((long long*)d_req_bind[d_paridx].buffer) = value; + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, unsigned long long value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; + d_req_bind[d_paridx].buffer = new unsigned long long[1]; + d_req_bind[d_paridx].is_unsigned = 1; + *((unsigned long long*)d_req_bind[d_paridx].buffer) = value; + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, const std::string& value) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_STRING; + d_req_bind[d_paridx].buffer = new char[value.size()+1]; + d_req_bind[d_paridx].length = new unsigned long[1]; + *d_req_bind[d_paridx].length = value.size(); + d_req_bind[d_paridx].buffer_length = *d_req_bind[d_paridx].length+1; + memset(d_req_bind[d_paridx].buffer, 0, value.size()+1); + value.copy((char*)d_req_bind[d_paridx].buffer, value.size()); + d_paridx++; + return this; + } + SSqlStatement* bindNull(const string& name) { + prepareStatement(); + if (d_paridx >= d_parnum) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_NULL; + d_paridx++; + return this; + } + + SSqlStatement* execute() { + int err; + + prepareStatement(); + + if (!d_stmt) return this; + + if (d_dolog) { + g_log<(mysql_stmt_field_count(d_stmt)))>0) { + // prepare for result + d_resnum = mysql_stmt_num_rows(d_stmt); + + if (d_resnum > 0 && d_res_bind == nullptr) { + MYSQL_RES* meta = mysql_stmt_result_metadata(d_stmt); + d_fnum = static_cast(mysql_num_fields(meta)); // ensure correct number of fields + d_res_bind = new MYSQL_BIND[d_fnum]; + memset(d_res_bind, 0, sizeof(MYSQL_BIND)*d_fnum); + MYSQL_FIELD* fields = mysql_fetch_fields(meta); + + for(int i = 0; i < d_fnum; i++) { + unsigned long len = std::max(fields[i].max_length, fields[i].length)+1; + if (len > 128 * 1024) len = 128 * 1024; // LONGTEXT may tell us it needs 4GB! + d_res_bind[i].is_null = new my_bool[1]; + d_res_bind[i].error = new my_bool[1]; + d_res_bind[i].length = new unsigned long[1]; + d_res_bind[i].buffer = new char[len]; + d_res_bind[i].buffer_length = len; + d_res_bind[i].buffer_type = MYSQL_TYPE_STRING; + } + + mysql_free_result(meta); + } + + /* we need to bind the results array again because a call to mysql_stmt_next_result() followed + by a call to mysql_stmt_store_result() might have invalidated it (the first one sets + stmt->bind_result_done to false, causing the second to reset the existing binding), + and we can't bind it right after the call to mysql_stmt_store_result() if it returned + no rows, because then the statement 'contains no metadata' */ + if (d_res_bind != nullptr && (err = mysql_stmt_bind_result(d_stmt, d_res_bind))) { + string error(mysql_stmt_error(d_stmt)); + releaseStatement(); + throw SSqlException("Could not bind parameters to mysql statement: " + d_query + string(": ") + error); + } + } + + if(d_dolog) + g_log<= 50500 + if (d_residx >= d_resnum) { + mysql_stmt_free_result(d_stmt); + while(!mysql_stmt_next_result(d_stmt)) { + if ((err = mysql_stmt_store_result(d_stmt))) { + string error(mysql_stmt_error(d_stmt)); + releaseStatement(); + throw SSqlException("Could not store mysql statement while processing additional sets: " + d_query + string(": ") + error); + } + d_resnum = mysql_stmt_num_rows(d_stmt); + // XXX: For some reason mysql_stmt_result_metadata returns NULL here, so we cannot + // ensure row field count matches first result set. + if (d_resnum > 0) { // ignore empty result set + if (d_res_bind != nullptr && (err = mysql_stmt_bind_result(d_stmt, d_res_bind))) { + string error(mysql_stmt_error(d_stmt)); + releaseStatement(); + throw SSqlException("Could not bind parameters to mysql statement: " + d_query + string(": ") + error); + } + d_residx = 0; + break; + } + mysql_stmt_free_result(d_stmt); + } + } +#endif + return this; + } + + SSqlStatement* getResult(result_t& result) { + result.clear(); + result.reserve(d_resnum); + row_t row; + + while(hasNextRow()) { + nextRow(row); + result.push_back(row); + } + + return this; + } + + SSqlStatement* reset() { + if (!d_stmt) return this; + int err=0; + mysql_stmt_free_result(d_stmt); +#if MYSQL_VERSION_ID >= 50500 + while((err = mysql_stmt_next_result(d_stmt)) == 0) { + mysql_stmt_free_result(d_stmt); + } +#endif + if (err>0) { + string error(mysql_stmt_error(d_stmt)); + releaseStatement(); + throw SSqlException("Could not get next result from mysql statement: " + d_query + string(": ") + error); + } + mysql_stmt_reset(d_stmt); + if (d_req_bind) { + for(int i=0;i(mysql_stmt_param_count(d_stmt)) != d_parnum) { + releaseStatement(); + throw SSqlException("Provided parameter count does not match statement: " + d_query); + } + + if (d_parnum>0) { + d_req_bind = new MYSQL_BIND[d_parnum]; + memset(d_req_bind, 0, sizeof(MYSQL_BIND)*d_parnum); + } + + d_prepared = true; + } + + void releaseStatement() { + d_prepared = false; + if (d_stmt) + mysql_stmt_close(d_stmt); + d_stmt = NULL; + if (d_req_bind) { + for(int i=0;i= 50013 + my_bool reconnect = 0; + mysql_options(&d_db, MYSQL_OPT_RECONNECT, &reconnect); +#endif + +#if MYSQL_VERSION_ID >= 50100 + if(d_timeout) { + mysql_options(&d_db, MYSQL_OPT_READ_TIMEOUT, &d_timeout); + mysql_options(&d_db, MYSQL_OPT_WRITE_TIMEOUT, &d_timeout); + } +#endif + +#if MYSQL_VERSION_ID >= 50500 + mysql_options(&d_db, MYSQL_SET_CHARSET_NAME, MYSQL_AUTODETECT_CHARSET_NAME); +#endif + + if (d_setIsolation && (retry == 1)) + mysql_options(&d_db, MYSQL_INIT_COMMAND,"SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"); + + mysql_options(&d_db, MYSQL_READ_DEFAULT_GROUP, d_group.c_str()); + + if (!mysql_real_connect(&d_db, d_host.empty() ? NULL : d_host.c_str(), + d_user.empty() ? NULL : d_user.c_str(), + d_password.empty() ? NULL : d_password.c_str(), + d_database.empty() ? NULL : d_database.c_str(), + d_port, + d_msocket.empty() ? NULL : d_msocket.c_str(), + (d_clientSSL ? CLIENT_SSL : 0) | CLIENT_MULTI_RESULTS)) { + + if (retry == 0) + throw sPerrorException("Unable to connect to database"); + --retry; + } else { + if (retry == 0) { + mysql_close(&d_db); + throw sPerrorException("Please add '(gmysql-)innodb-read-committed=no' to your PowerDNS configuration, and reconsider your storage engine if it does not support transactions."); + } + retry=-1; + } + } while (retry >= 0); +} + +SMySQL::SMySQL(const string &database, const string &host, uint16_t port, const string &msocket, const string &user, + const string &password, const string &group, bool setIsolation, unsigned int timeout, bool threadCleanup, bool clientSSL): + d_database(database), d_host(host), d_msocket(msocket), d_user(user), d_password(password), d_group(group), d_timeout(timeout), d_port(port), d_setIsolation(setIsolation), d_threadCleanup(threadCleanup), d_clientSSL(clientSSL) +{ + connect(); +} + +void SMySQL::setLog(bool state) +{ + s_dolog=state; +} + +SMySQL::~SMySQL() +{ + mysql_close(&d_db); +} + +SSqlException SMySQL::sPerrorException(const string &reason) +{ + return SSqlException(reason+string(": ")+mysql_error(&d_db)); +} + +std::unique_ptr SMySQL::prepare(const string& query, int nparams) +{ + return std::unique_ptr(new SMySQLStatement(query, s_dolog, nparams, &d_db)); +} + +void SMySQL::execute(const string& query) +{ + if(s_dolog) + g_log< +#include "pdns/backends/gsql/ssql.hh" +#include "pdns/utility.hh" + +class SMySQL : public SSql +{ +public: + SMySQL(const string &database, const string &host="", uint16_t port=0, + const string &msocket="",const string &user="", + const string &password="", const string &group="", + bool setIsolation=false, unsigned int timeout=10, + bool threadCleanup=false, bool clientSSL=false); + + ~SMySQL(); + + SSqlException sPerrorException(const string &reason) override; + void setLog(bool state) override; + std::unique_ptr prepare(const string& query, int nparams) override; + void execute(const string& query) override; + + void startTransaction() override; + void commit() override; + void rollback() override; + bool isConnectionUsable() override; +private: + void connect(); + + static bool s_dolog; + static pthread_mutex_t s_myinitlock; + + MYSQL d_db; + std::string d_database; + std::string d_host; + std::string d_msocket; + std::string d_user; + std::string d_password; + std::string d_group; + unsigned int d_timeout; + uint16_t d_port; + bool d_setIsolation; + bool d_threadCleanup; + bool d_clientSSL; +}; + +#endif /* SSMYSQL_HH */ diff --git a/modules/godbcbackend/4.0.0_to_4.2.0_schema.mssql.sql b/modules/godbcbackend/4.0.0_to_4.2.0_schema.mssql.sql new file mode 100644 index 0000000..f910462 --- /dev/null +++ b/modules/godbcbackend/4.0.0_to_4.2.0_schema.mssql.sql @@ -0,0 +1 @@ +ALTER TABLE records DROP COLUMN change_date; diff --git a/modules/godbcbackend/Makefile.am b/modules/godbcbackend/Makefile.am new file mode 100644 index 0000000..539daf1 --- /dev/null +++ b/modules/godbcbackend/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS += $(UNIXODBC_CFLAGS) +pkglib_LTLIBRARIES = libgodbcbackend.la + +EXTRA_DIST=OBJECTFILES OBJECTLIBS + +dist_doc_DATA=schema.mssql.sql \ + 4.0.0_to_4.2.0_schema.mssql.sql + +libgodbcbackend_la_SOURCES=godbcbackend.cc godbcbackend.hh \ + sodbc.hh sodbc.cc + +libgodbcbackend_la_LDFLAGS=-module -avoid-version +libgodbcbackend_la_LIBADD=$(UNIXODBC_LIBS) diff --git a/modules/godbcbackend/Makefile.in b/modules/godbcbackend/Makefile.in new file mode 100644 index 0000000..370606c --- /dev/null +++ b/modules/godbcbackend/Makefile.in @@ -0,0 +1,857 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/godbcbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgodbcbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libgodbcbackend_la_OBJECTS = godbcbackend.lo sodbc.lo +libgodbcbackend_la_OBJECTS = $(am_libgodbcbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgodbcbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgodbcbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgodbcbackend_la_SOURCES) +DIST_SOURCES = $(libgodbcbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(UNIXODBC_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libgodbcbackend.la +EXTRA_DIST = OBJECTFILES OBJECTLIBS +dist_doc_DATA = schema.mssql.sql \ + 4.0.0_to_4.2.0_schema.mssql.sql + +libgodbcbackend_la_SOURCES = godbcbackend.cc godbcbackend.hh \ + sodbc.hh sodbc.cc + +libgodbcbackend_la_LDFLAGS = -module -avoid-version +libgodbcbackend_la_LIBADD = $(UNIXODBC_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/godbcbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/godbcbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgodbcbackend.la: $(libgodbcbackend_la_OBJECTS) $(libgodbcbackend_la_DEPENDENCIES) $(EXTRA_libgodbcbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgodbcbackend_la_LINK) -rpath $(pkglibdir) $(libgodbcbackend_la_OBJECTS) $(libgodbcbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/godbcbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodbc.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/godbcbackend/OBJECTFILES b/modules/godbcbackend/OBJECTFILES new file mode 100644 index 0000000..0f6af2a --- /dev/null +++ b/modules/godbcbackend/OBJECTFILES @@ -0,0 +1 @@ +godbcbackend.lo sodbc.lo \ No newline at end of file diff --git a/modules/godbcbackend/OBJECTLIBS b/modules/godbcbackend/OBJECTLIBS new file mode 100644 index 0000000..3660bcf --- /dev/null +++ b/modules/godbcbackend/OBJECTLIBS @@ -0,0 +1 @@ +-lodbc \ No newline at end of file diff --git a/modules/godbcbackend/godbcbackend.cc b/modules/godbcbackend/godbcbackend.cc new file mode 100644 index 0000000..533f50f --- /dev/null +++ b/modules/godbcbackend/godbcbackend.cc @@ -0,0 +1,170 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "pdns/utility.hh" +#include +#include +#include + +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "sodbc.hh" +#include "godbcbackend.hh" + + +// Connects to the database. +gODBCBackend::gODBCBackend (const std::string & mode, const std::string & suffix) : GSQLBackend( mode, suffix ) +{ + try + { + setDB( new SODBC( getArg( "datasource" ), getArg( "username" ), getArg( "password" ))); + } + catch( SSqlException & e ) + { + g_log< convert(varbinary(255),?) and domain_id=? and disabled=0 and ordername is not null"); + declare(suffix, "get-order-last-query", "DNSSEC Ordering Query, last", "select top 1 convert(varchar(255), ordername), name from records where ordername != convert(varbinary(255),'') and domain_id=? and disabled=0 and ordername is not null order by 1 desc"); + + declare(suffix, "update-ordername-and-auth-query", "DNSSEC update ordername and auth for a qname query", "update records set ordername=convert(varbinary(255),?),auth=? where domain_id=? and name=? and disabled=0"); + declare(suffix, "update-ordername-and-auth-type-query", "DNSSEC update ordername and auth for a rrset query", "update records set ordername=convert(varbinary(255),?),auth=? where domain_id=? and name=? and type=? and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and type=? and disabled=0"); + + declare(suffix,"update-master-query","", "update domains set master=? where name=?"); + declare(suffix,"update-kind-query","", "update domains set type=? where name=?"); + declare(suffix,"update-account-query","", "update domains set account=? where name=?"); + declare(suffix,"update-serial-query","", "update domains set notified_serial=? where id=?"); + declare(suffix,"update-lastcheck-query","", "update domains set last_check=? where id=?"); + declare(suffix,"info-all-master-query","", "select domains.id, domains.name, domains.notified_serial, records.content from records join domains on records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type='MASTER'"); + declare(suffix,"delete-domain-query","", "delete from domains where name=?"); + declare(suffix,"delete-zone-query","", "delete from records where domain_id=?"); + declare(suffix,"delete-rrset-query","","delete from records where domain_id=? and name=? and type=?"); + declare(suffix,"delete-names-query","","delete from records where domain_id=? and name=?"); + + declare(suffix,"add-domain-key-query","", "insert into cryptokeys (domain_id, flags, active, content) select id, ?, ?, ? from domains where name=?"); + declare(suffix,"get-last-inserted-key-id-query", "", "select ident_current('cryptokeys')"); + declare(suffix,"list-domain-keys-query","", "select cryptokeys.id, flags, active, content from domains, cryptokeys where cryptokeys.domain_id=domains.id and name=?"); + declare(suffix,"get-all-domain-metadata-query","", "select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=?"); + declare(suffix,"get-domain-metadata-query","", "select content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=? and domainmetadata.kind=?"); + declare(suffix,"clear-domain-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=?) and domainmetadata.kind=?"); + declare(suffix,"clear-domain-all-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=?)"); + declare(suffix,"set-domain-metadata-query","", "insert into domainmetadata (domain_id, kind, content) select id, ?, ? from domains where name=?"); + declare(suffix,"activate-domain-key-query","", "update cryptokeys set active=1 where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"deactivate-domain-key-query","", "update cryptokeys set active=0 where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"remove-domain-key-query","", "delete from cryptokeys where domain_id=(select id from domains where name=?) and cryptokeys.id=?"); + declare(suffix,"clear-domain-all-keys-query","", "delete from cryptokeys where domain_id=(select id from domains where name=?)"); + declare(suffix,"get-tsig-key-query","", "select algorithm, secret from tsigkeys where name=?"); + /* FIXME: set-tsig-key-query only works on an empty database right now. For MySQL we use the "update into" statement.. + According to the internet, we need to construct a pretty hefty "merge" query: https://msdn.microsoft.com/en-us/library/bb510625.aspx + */ + declare(suffix,"set-tsig-key-query","", "insert into tsigkeys (name,algorithm,secret) values(?,?,?)"); + declare(suffix,"delete-tsig-key-query","", "delete from tsigkeys where name=?"); + declare(suffix,"get-tsig-keys-query","", "select name,algorithm, secret from tsigkeys"); + + declare(suffix, "get-all-domains-query", "Retrieve all domains", "select domains.id, domains.name, records.content, domains.type, domains.master, domains.notified_serial, domains.last_check, domains.account from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name WHERE records.disabled=0 OR records.disabled=?"); + + declare(suffix, "list-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE domain_id=?"); + declare(suffix, "insert-comment-query", "", "INSERT INTO comments (domain_id, name, type, modified_at, account, comment) VALUES (?, ?, ?, ?, ?, ?)"); + declare(suffix, "delete-comment-rrset-query", "", "DELETE FROM comments WHERE domain_id=? AND name=? AND type=?"); + declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=?"); + declare(suffix, "search-records-query", "", record_query+" name LIKE ? OR content LIKE ? LIMIT ?"); + declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE ? OR comment LIKE ? LIMIT ?"); + } + + //! Constructs a new gODBCBackend object. + DNSBackend *make(const string & suffix = "" ) + { + return new gODBCBackend( d_mode, suffix ); + } + +private: + const string d_mode; +}; + + +//! Magic class that is activated when the dynamic library is loaded +class gODBCLoader +{ +public: + //! This reports us to the main UeberBackend class + gODBCLoader() + { + BackendMakers().report( new gODBCFactory("godbc")); + g_log< +#include "pdns/backends/gsql/gsqlbackend.hh" + +class gODBCBackend : public GSQLBackend +{ +public: + //! Constructor that connects to the database, throws an exception if something went wrong. + gODBCBackend( const std::string & mode, const std::string & suffix ); + +}; + diff --git a/modules/godbcbackend/schema.mssql.sql b/modules/godbcbackend/schema.mssql.sql new file mode 100644 index 0000000..0bd56a0 --- /dev/null +++ b/modules/godbcbackend/schema.mssql.sql @@ -0,0 +1,87 @@ +CREATE TABLE domains ( + id INT IDENTITY, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial INT DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL, + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX name_index ON domains(name); + +CREATE TABLE records ( + id INT IDENTITY, + domain_id INT DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(MAX) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + disabled BIT DEFAULT 0, + ordername VARBINARY(255) DEFAULT NULL, + auth BIT DEFAULT 1, + PRIMARY KEY (id) +); + +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) NOT NULL, + PRIMARY KEY (ip, nameserver) +); + + +CREATE TABLE comments ( + id INT IDENTITY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) NOT NULL, + comment VARCHAR(MAX) NOT NULL, + PRIMARY KEY (id) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INT IDENTITY, + domain_id INT NOT NULL, + kind VARCHAR(32), + content VARCHAR(MAX), + PRIMARY KEY (id) +); + +CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); + +CREATE TABLE cryptokeys ( + id INT IDENTITY, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BIT, + content VARCHAR(MAX), + PRIMARY KEY(id) +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INT IDENTITY, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); diff --git a/modules/godbcbackend/sodbc.cc b/modules/godbcbackend/sodbc.cc new file mode 100644 index 0000000..5b8e458 --- /dev/null +++ b/modules/godbcbackend/sodbc.cc @@ -0,0 +1,487 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "pdns/logger.hh" +#include "pdns/utility.hh" +#include +#include "sodbc.hh" +#include + +static bool realTestResult( SQLRETURN result, SQLSMALLINT type, SQLHANDLE handle, const std::string & message, std::string & errorMessage) +{ + // cerr<<"result = "< d_req_bind; + + SSqlStatement* bind(const string& name, ODBCParam& p) { + prepareStatement(); + d_req_bind.push_back(p); + SQLRETURN result = SQLBindParameter( + d_statement, // StatementHandle, + d_paridx+1, // ParameterNumber, + SQL_PARAM_INPUT, // InputOutputType, + p.ValueType, // ValueType, + p.ParameterType, // ParameterType, + 0, // ColumnSize, + 0, // DecimalDigits, + p.ParameterValuePtr, // ParameterValuePtr, + 0, // BufferLength, + p.LenPtr // StrLen_or_IndPtr + ); + testResult( result, SQL_HANDLE_STMT, d_statement, "Could not bind parameter."); + d_paridx++; + + return this; + } + + SSqlStatement* bind(const string& name, bool value) { prepareStatement(); return bind(name, (uint32_t)value); } + + SSqlStatement* bind(const string& name, long value) { prepareStatement(); return bind(name, (unsigned long)value); } + + SSqlStatement* bind(const string& name, int value) { prepareStatement(); return bind(name, (uint32_t)value); } + + SSqlStatement* bind(const string& name, long long value) { prepareStatement(); return bind(name, (unsigned long long)value); } + + SSqlStatement* bind(const string& name, uint32_t value) { + prepareStatement(); + ODBCParam p; + p.ParameterValuePtr = new UDWORD {value}; + p.LenPtr = new SQLLEN {sizeof(UDWORD)}; + p.ParameterType = SQL_INTEGER; + p.ValueType = SQL_INTEGER; + return bind(name, p); + } + + SSqlStatement* bind(const string& name, unsigned long value) { + prepareStatement(); + ODBCParam p; + p.ParameterValuePtr = new ULONG {value}; + p.LenPtr = new SQLLEN {sizeof(ULONG)}; + p.ParameterType = SQL_INTEGER; + p.ValueType = SQL_INTEGER; + return bind(name, p); + } + + SSqlStatement* bind(const string& name, unsigned long long value) { + prepareStatement(); + ODBCParam p; + p.ParameterValuePtr = new unsigned long long {value}; + p.LenPtr = new SQLLEN {sizeof(unsigned long long)}; + p.ParameterType = SQL_BIGINT; + p.ValueType = SQL_C_UBIGINT; + return bind(name, p); + } + + SSqlStatement* bind(const string& name, const std::string& value) { + + // cerr<<"asked to bind string "< (d_parnum+1)) throw SSqlException("Trying to bind too many parameters."); + prepareStatement(); + ODBCParam p; + + p.ParameterValuePtr = (char*) new char[value.size()+1]; + value.copy((char*)p.ParameterValuePtr, value.size()); + ((char*)p.ParameterValuePtr)[value.size()]=0; + p.LenPtr=new SQLLEN; + *(p.LenPtr)=value.size(); + p.ParameterType = SQL_VARCHAR; + p.ValueType = SQL_C_CHAR; + + return bind(name, p); + } + + SSqlStatement* bindNull(const string& name) { + if(d_req_bind.size() > (d_parnum+1)) throw SSqlException("Trying to bind too many parameters."); + + prepareStatement(); + ODBCParam p; + + p.ParameterValuePtr = NULL; + p.LenPtr=new SQLLEN; + *(p.LenPtr)=SQL_NULL_DATA; + p.ParameterType = SQL_VARCHAR; + p.ValueType = SQL_C_CHAR; + + return bind(name, p); + } + + SSqlStatement* execute() + { + prepareStatement(); + SQLRETURN result; + // cerr<<"execute("<(d_parnum)) { + releaseStatement(); + throw SSqlException("Provided parameter count does not match statement: " + d_query); + } + + // cerr<<"prepared ("< SQL_NULL_DATA) + strres = std::string(reinterpret_cast(coldata), std::min(sizeof(coldata)-1,len)); // do not use nil byte + row.push_back(strres); + } + + // Done! + d_residx++; + // cerr<<"SQLFetch"<( SQL_OV_ODBC3 ), 0 ); + testResult( result, SQL_HANDLE_ENV, m_environment, "Could not set the ODBC version." ); + + // Allocate connection handle. + result = SQLAllocHandle( SQL_HANDLE_DBC, m_environment, &m_connection ); + testResult( result, SQL_HANDLE_ENV, m_environment, "Could not allocate a connection handle." ); + + // Connect to the database. + char *l_dsn = strdup( dsn.c_str()); + char *l_username = strdup( username.c_str()); + char *l_password = strdup( password.c_str()); + + result = SQLConnect( m_connection, + reinterpret_cast< SQLTCHAR * >( l_dsn ), dsn.length(), + reinterpret_cast< SQLTCHAR * >( l_username ), username.length(), + reinterpret_cast< SQLTCHAR * >( l_password ), password.length()); + + free( l_dsn ); + free( l_username ); + free( l_password ); + + testResult( result, SQL_HANDLE_DBC, m_connection, "Could not connect to ODBC datasource." ); + + + m_busy = false; + m_log = false; +} + + +// Destructor. +SODBC::~SODBC( void ) +{ + // Disconnect from database and free all used resources. + // SQLFreeHandle( SQL_HANDLE_STMT, m_statement ); + + SQLDisconnect( m_connection ); + + SQLFreeHandle( SQL_HANDLE_DBC, m_connection ); + SQLFreeHandle( SQL_HANDLE_ENV, m_environment ); + + // Free all allocated column memory. + // for ( int i = 0; i < m_columnInfo.size(); i++ ) + // { + // if ( m_columnInfo[ i ].m_pData ) + // delete m_columnInfo[ i ].m_pData; + // } +} + +// Executes a command. +void SODBC::execute( const std::string & command ) +{ + SODBCStatement stmt(command, m_log, 0, m_connection); + + stmt.execute()->reset(); +} + +// Sets the log state. +void SODBC::setLog( bool state ) +{ + m_log = state; +} + +// Returns an exception. +SSqlException SODBC::sPerrorException( const std::string & reason ) +{ + return SSqlException( reason ); +} + +std::unique_ptr SODBC::prepare(const string& query, int nparams) +{ + return std::unique_ptr(new SODBCStatement(query, m_log, nparams, m_connection)); +} + + +void SODBC::startTransaction() { + // cerr<<"starting transaction"< +#include + +#include +#include + +#include "pdns/backends/gsql/ssql.hh" + +//! ODBC SSql implementation for use with the Generic ODBC Backend. +class SODBC : public SSql +{ +private: + + + bool m_log; //!< Should we log? + bool m_busy; //!< Are we busy executing a query? + + SQLHDBC m_connection; //!< Database connection handle. + SQLHENV m_environment; //!< Database environment handle + + void testResult(SQLRETURN result, SQLSMALLINT type, SQLHANDLE handle, const std::string & message); + +public: + //! Default constructor. + /*! + This constructor connects to an ODBC datasource and makes sure it's ready to use. + + \param dsn The ODBC DSN to use. + \param username Username to use. + \param password Password to use. + */ + SODBC( + const std::string & dsn, + const std::string & username, + const std::string & password + ); + + //! Destructor. + virtual ~SODBC( void ); + + //! Sets the logging state. + void setLog( bool state ) override; + + std::unique_ptr prepare(const string& query, int nparams) override; + void execute(const string& query) override; + void startTransaction() override; + void rollback() override; + void commit() override; + + //! Returns an exception. + SSqlException sPerrorException( const std::string & reason ) override; + +}; + + +#endif // SODBC_HH diff --git a/modules/goraclebackend/Makefile.am b/modules/goraclebackend/Makefile.am new file mode 100644 index 0000000..f4fdf92 --- /dev/null +++ b/modules/goraclebackend/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS += $(ORACLE_CFLAGS) + +pkglib_LTLIBRARIES = libgoraclebackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + drop-schema.goracle.sql \ + schema.goracle.sql + +dist_doc_DATA = \ + drop-schema.goracle.sql \ + schema.goracle.sql + +libgoraclebackend_la_SOURCES = \ + goraclebackend.cc goraclebackend.hh \ + soracle.cc soracle.hh + +libgoraclebackend_la_LDFLAGS = -module -avoid-version +libgoraclebackend_la_LIBADD = $(ORACLE_LIBS) diff --git a/modules/goraclebackend/Makefile.in b/modules/goraclebackend/Makefile.in new file mode 100644 index 0000000..5bcab3d --- /dev/null +++ b/modules/goraclebackend/Makefile.in @@ -0,0 +1,864 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/goraclebackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgoraclebackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libgoraclebackend_la_OBJECTS = goraclebackend.lo soracle.lo +libgoraclebackend_la_OBJECTS = $(am_libgoraclebackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgoraclebackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgoraclebackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgoraclebackend_la_SOURCES) +DIST_SOURCES = $(libgoraclebackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(ORACLE_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libgoraclebackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + drop-schema.goracle.sql \ + schema.goracle.sql + +dist_doc_DATA = \ + drop-schema.goracle.sql \ + schema.goracle.sql + +libgoraclebackend_la_SOURCES = \ + goraclebackend.cc goraclebackend.hh \ + soracle.cc soracle.hh + +libgoraclebackend_la_LDFLAGS = -module -avoid-version +libgoraclebackend_la_LIBADD = $(ORACLE_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/goraclebackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/goraclebackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgoraclebackend.la: $(libgoraclebackend_la_OBJECTS) $(libgoraclebackend_la_DEPENDENCIES) $(EXTRA_libgoraclebackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgoraclebackend_la_LINK) -rpath $(pkglibdir) $(libgoraclebackend_la_OBJECTS) $(libgoraclebackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/goraclebackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/soracle.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/goraclebackend/OBJECTFILES b/modules/goraclebackend/OBJECTFILES new file mode 100644 index 0000000..4ea82a0 --- /dev/null +++ b/modules/goraclebackend/OBJECTFILES @@ -0,0 +1 @@ +goraclebackend.lo soracle.lo diff --git a/modules/goraclebackend/OBJECTLIBS b/modules/goraclebackend/OBJECTLIBS new file mode 100644 index 0000000..e69de29 diff --git a/modules/goraclebackend/drop-schema.goracle.sql b/modules/goraclebackend/drop-schema.goracle.sql new file mode 100644 index 0000000..2edd308 --- /dev/null +++ b/modules/goraclebackend/drop-schema.goracle.sql @@ -0,0 +1,19 @@ +DROP TABLE records; +DROP SEQUENCE records_id_sequence; + +DROP TABLE supermasters; + +DROP TABLE comments; +DROP SEQUENCE comments_id_sequence; + +DROP TABLE domainmetadata; +DROP SEQUENCE domainmetadata_id_sequence; + +DROP TABLE cryptokeys; +DROP SEQUENCE cryptokeys_id_sequence; + +DROP TABLE tsigkeys; +DROP SEQUENCE tsigkeys_id_sequence; + +DROP TABLE domains; +DROP SEQUENCE domains_id_sequence; diff --git a/modules/goraclebackend/goraclebackend.cc b/modules/goraclebackend/goraclebackend.cc new file mode 100644 index 0000000..f18c476 --- /dev/null +++ b/modules/goraclebackend/goraclebackend.cc @@ -0,0 +1,186 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/lock.hh" +#include "goraclebackend.hh" +#include "soracle.hh" +#include + +static OCIEnv* d_environmentHandle = 0; +static pthread_mutex_t s_goracle_lock=PTHREAD_MUTEX_INITIALIZER; + +gOracleBackend::gOracleBackend(const string &mode, const string &suffix) : GSQLBackend(mode, suffix) +{ + Lock gl(&s_goracle_lock); + if (d_environmentHandle == 0) { + setenv("ORACLE_HOME", getArg("home").c_str(), 1); + setenv("ORACLE_SID", getArg("sid").c_str(), 1); + setenv("NLS_LANG", getArg("nls-lang").c_str(), 1); + + int err = OCIEnvCreate(&d_environmentHandle, OCI_THREADED, NULL, NULL, NULL, NULL, 0, NULL); + + if (err) { + throw PDNSException("OCIEnvCreate failed"); + } + } + + try { + // set Oracle environment variables + setDB(new SOracle(getArg("tnsname"), + getArg("user"), + getArg("password"), + mustDo("release-statements"), + d_environmentHandle)); + } + + catch (SSqlException &e) { + g_log< :ordername || ' ' and domain_id=:domain_id and ordername is not null"); + declare(suffix, "get-order-last-query", "DNSSEC Ordering Query, last", "select * from (select trim(ordername), name from records where disabled=0 and ordername != ' ' and domain_id=:domain_id and ordername is not null order by ordername desc) where rownum=1"); + + declare(suffix, "update-ordername-and-auth-query", "DNSSEC update ordername and auth for a qname query", "update records set ordername=:ordername || ' ',auth=:auth where domain_id=:domain_id and name=:qname and disabled=0"); + declare(suffix, "update-ordername-and-auth-type-query", "DNSSEC update ordername and auth for a rrset query", "update records set ordername=:ordername || ' ',auth=:auth where domain_id=:domain_id and name=:qname and type=:qtype and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and type=:qtype and disabled=0"); + + declare(suffix, "update-master-query", "", "update domains set master=:master where name=:domain"); + declare(suffix, "update-kind-query", "", "update domains set type=:kind where name=:domain"); + declare(suffix, "update-account-query", "", "update domains set account=:account where name=:domain"); + declare(suffix, "update-serial-query", "", "update domains set notified_serial=:serial where id=:domain_id"); + declare(suffix, "update-lastcheck-query", "", "update domains set last_check=:last_check where id=:domain_id"); + declare(suffix, "info-all-master-query", "", "select id,name,master,last_check,notified_serial,type from domains where type='MASTER'"); + declare(suffix, "delete-domain-query","", "delete from domains where name=:domain"); + declare(suffix, "delete-zone-query", "", "delete from records where domain_id=:domain_id"); + declare(suffix, "delete-rrset-query", "", "delete from records where domain_id=:domain_id and name=:qname and type=:qtype"); + declare(suffix, "delete-names-query", "", "delete from records where domain_id=:domain_id and name=:qname"); + + declare(suffix, "add-domain-key-query","", "insert into cryptokeys (id, domain_id, flags, active, content) select cryptokeys_id_sequence.nextval, id, :flags,:active, :content from domains where name=:domain"); + declare(suffix, "get-last-inserted-key-id-query", "", "select cryptokeys_id_sequence.currval from DUAL"); + declare(suffix, "list-domain-keys-query","", "select cryptokeys.id, flags, active, content from domains, cryptokeys where cryptokeys.domain_id=domains.id and name=:domain"); + declare(suffix, "get-all-domain-metadata-query","", "select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=:domain"); + declare(suffix, "get-domain-metadata-query","", "select content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=:domain and domainmetadata.kind=:kind"); + declare(suffix, "clear-domain-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=:domain) and domainmetadata.kind=:kind"); + declare(suffix, "clear-domain-all-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=:domain)"); + declare(suffix, "set-domain-metadata-query","", "insert into domainmetadata (id, domain_id, kind, content) select domainmetadata_id_sequence.nextval, id, :kind, :content from domains where name=:domain"); + declare(suffix, "activate-domain-key-query","", "update cryptokeys set active=1 where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "deactivate-domain-key-query","", "update cryptokeys set active=0 where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "remove-domain-key-query","", "delete from cryptokeys where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "clear-domain-all-keys-query","", "delete from cryptokeys where domain_id=(select id from domains where name=:domain)"); + declare(suffix, "get-tsig-key-query","", "select algorithm, secret from tsigkeys where name=:key_name"); + declare(suffix, "set-tsig-key-query","", "merge into tsigkeys tk using dual on (name = :key_name and algorithm = :algorithm) when not matched then insert (id, name, algorithm, secret) values(tsigkeys_id_sequence.nextval, :key_name, :algorithm, :content) when matched then update set secret = :content"); + declare(suffix, "delete-tsig-key-query","", "delete from tsigkeys where name=:key_name"); + declare(suffix, "get-tsig-keys-query","", "select name,algorithm, secret from tsigkeys"); + + declare(suffix, "get-all-domains-query", "Retrieve all domains", "select domains.id, domains.name, records.content, domains.type, domains.master, domains.notified_serial, domains.last_check, domain.account from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name WHERE records.disabled=0 OR records.disabled=:include_disabled"); + + declare(suffix, "list-comments-query", "", "SELECT domain_id,name,type,modified_at,account,\"comment\" FROM comments WHERE domain_id=:domain_id"); + declare(suffix, "insert-comment-query", "", "INSERT INTO comments (id, domain_id, name, type, modified_at, account, \"comment\") VALUES (comments_id_sequence.nextval, :domain_id, :qname, :qtype, :modified_at, :account, :content)"); + declare(suffix, "delete-comment-rrset-query", "", "DELETE FROM comments WHERE domain_id=:domain_id AND name=:qname AND type=:qtype"); + declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=:domain_id"); + declare(suffix, "search-records-query", "", record_query+" name LIKE :value OR content LIKE :value2 LIMIT :limit"); + declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE :value OR comment LIKE :value2 LIMIT :limit"); + + } + + DNSBackend* make(const string &suffix="") { + return new gOracleBackend(d_mode,suffix); + } + +private: + const string d_mode; +}; + + +//! Magic class that is activated when the dynamic library is loaded +class gOracleLoader +{ +public: + //! This reports us to the main UeberBackend class + gOracleLoader() { + BackendMakers().report(new gOracleFactory("goracle")); + g_log << Logger::Info << "[goraclebackend] This is the goracle backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + +//! Reports the backendloader to the UeberBackend. +static gOracleLoader goracleloader; diff --git a/modules/goraclebackend/goraclebackend.hh b/modules/goraclebackend/goraclebackend.hh new file mode 100644 index 0000000..c41de32 --- /dev/null +++ b/modules/goraclebackend/goraclebackend.hh @@ -0,0 +1,39 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_GORACLEBACKEND_HH +#define PDNS_GORACLEBACKEND_HH + +#include +#include +#include "pdns/backends/gsql/gsqlbackend.hh" + +#include "pdns/namespaces.hh" + +/** The gOracleBackend is a DNSBackend that can answer DNS related questions. It looks up data + in PostgreSQL */ +class gOracleBackend : public GSQLBackend +{ +public: + gOracleBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails. +}; + +#endif /* PDNS_GORACLEBACKEND_HH */ diff --git a/modules/goraclebackend/schema.goracle.sql b/modules/goraclebackend/schema.goracle.sql new file mode 100644 index 0000000..c2f9016 --- /dev/null +++ b/modules/goraclebackend/schema.goracle.sql @@ -0,0 +1,93 @@ +CREATE TABLE domains ( + id INTEGER NOT NULL, + name VARCHAR2(255) NOT NULL, + master VARCHAR2(128) DEFAULT NULL, + last_check INTEGER DEFAULT NULL, + type VARCHAR2(6) NOT NULL, + notified_serial NUMBER(10,0) DEFAULT NULL, + account VARCHAR2(40) DEFAULT NULL, + PRIMARY KEY (id) +); + +CREATE SEQUENCE domains_id_sequence; +CREATE INDEX domains$name ON domains (name); + + +CREATE TABLE records ( + id INTEGER NOT NULL, + domain_id INTEGER DEFAULT NULL REFERENCES domains (id) ON DELETE CASCADE, + name VARCHAR2(255) DEFAULT NULL, + type VARCHAR2(10) DEFAULT NULL, + content VARCHAR2(4000) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + disabled NUMBER(1,0) DEFAULT 0 NOT NULL, + ordername VARCHAR2(255) DEFAULT NULL, + auth NUMBER(1,0) DEFAULT 1 NOT NULL, + PRIMARY KEY (id) +) pctfree 40; + +CREATE SEQUENCE records_id_sequence; +CREATE INDEX records$nametype ON records (name, type); +CREATE INDEX records$domain_id ON records (domain_id); +CREATE INDEX records$recordorder ON records (domain_id, ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR2(64) NOT NULL, + nameserver VARCHAR2(255) NOT NULL, + account VARCHAR2(40) NOT NULL, + PRIMARY KEY (ip, nameserver) +); + + +CREATE TABLE comments ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL REFERENCES domains (id) ON DELETE CASCADE, + name VARCHAR2(255) NOT NULL, + type VARCHAR2(10) NOT NULL, + modified_at INTEGER NOT NULL, + account VARCHAR2(40) NOT NULL, + "comment" VARCHAR2(4000) NOT NULL +); +CREATE SEQUENCE comments_id_sequence; +CREATE INDEX comments$nametype ON comments (name, type); +CREATE INDEX comments$domain_id ON comments (domain_id); +CREATE INDEX comments$order ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL, + kind VARCHAR2(32), + content VARCHAR2(4000), + PRIMARY KEY (id) +); + +CREATE SEQUENCE domainmetadata_id_sequence; +CREATE INDEX domainmetadata$domain_id ON domainmetadata (domain_id); + + +CREATE TABLE cryptokeys ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL, + flags INTEGER NOT NULL, + active INTEGER NOT NULL, + content VARCHAR2(4000), + PRIMARY KEY (id) +); + +CREATE SEQUENCE cryptokeys_id_sequence; +CREATE INDEX cryptokeys$domain_id ON cryptokeys (domain_id); + + +CREATE TABLE tsigkeys ( + id INTEGER NOT NULL, + name VARCHAR2(255), + algorithm VARCHAR2(50), + secret VARCHAR2(255), + PRIMARY KEY (id) +); + +CREATE SEQUENCE tsigkeys_id_sequence; +CREATE UNIQUE INDEX tsigkeys$namealgo ON tsigkeys (name, algorithm); diff --git a/modules/goraclebackend/soracle.cc b/modules/goraclebackend/soracle.cc new file mode 100644 index 0000000..5442b17 --- /dev/null +++ b/modules/goraclebackend/soracle.cc @@ -0,0 +1,554 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "soracle.hh" +#include +#include +#include "pdns/misc.hh" +#include "pdns/logger.hh" +#include "pdns/dns.hh" +#include "pdns/namespaces.hh" +#include "pdns/digests.hh" + +static AtomicCounter s_txid; + +bool SOracle::s_dolog; + +class SOracleStatement: public SSqlStatement { +public: + SOracleStatement(const string& query, bool dolog, int nparams, OCIEnv *ctx, OCISvcCtx *svc_ctx, bool release_stmt) { + d_query = query; + d_ctx = ctx; + d_svcctx = svc_ctx; + d_dolog = dolog; + d_res = NULL; + d_bind = NULL; + d_stmt = NULL; + d_err = NULL; + d_queryResult = OCI_NO_DATA; + d_paridx = d_parnum = d_resnum = d_residx = 0; + d_release_stmt = release_stmt; + d_non_null_ind = 0; + d_null_ind = -1; + d_init = false; + d_prepared = false; + d_parnum = nparams; + // create a key + string key = pdns_md5sum(d_query); + d_stmt_keysize = std::min(key.size()*2, sizeof(d_stmt_key)); + for(string::size_type i = 0; i < key.size() && i*2 < d_stmt_keysize; i++) + snprintf((char*)&(d_stmt_key[i*2]), 3, "%02x", (unsigned char)key[i]); + d_stmt_key[d_stmt_keysize] = 0; + } + + SSqlStatement* bind(const string& name, bool value) + { + return bind(name, (int)value); + } + SSqlStatement* bind(const string& name, int value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val4 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), &(d_bind[d_paridx].val4), sizeof(sb4), SQLT_INT, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, uint32_t value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val4 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (ub4*)&(d_bind[d_paridx].val4), sizeof(ub4), SQLT_UIN, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, long value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val4 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (ub4*)&(d_bind[d_paridx].val4), sizeof(sb4), SQLT_INT, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, unsigned long value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val4 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (ub4*)&(d_bind[d_paridx].val4), sizeof(ub4), SQLT_UIN, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, long long value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val8 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (orasb8*)&(d_bind[d_paridx].val8), sizeof(orasb8), SQLT_INT, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, unsigned long long value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].val8 = value; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (oraub8*)&(d_bind[d_paridx].val8), sizeof(oraub8), SQLT_UIN, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bind(const string& name, const std::string& value) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + d_bind[d_paridx].vals = new text[value.size()+1]; + memset(d_bind[d_paridx].vals, 0, value.size()+1); + value.copy((char*)d_bind[d_paridx].vals, value.size()); + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), (text*)d_bind[d_paridx].vals, value.size()+1, SQLT_STR, &d_non_null_ind,0,0,0,0,OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_paridx++; + return this; + } + SSqlStatement* bindNull(const string& name) + { + if (d_paridx >= d_parnum) + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + prepareStatement(); + string zName = string(":") + name; + if (OCIBindByName(d_stmt, &(d_bind[d_paridx].handle), d_err, (text*)zName.c_str(), zName.size(), NULL, 0, SQLT_STR, &d_null_ind, 0, 0, 0, 0, OCI_DEFAULT) != OCI_SUCCESS) { + throw SSqlException(string("Cannot bind parameter ") + name + string(": ") + OCIErrStr()); + } + d_bind[d_paridx].release = true; // remember to free this + d_paridx++; + return this; + } + SSqlStatement* execute() + { + if (d_query.size() == 0) return this; // do not execute empty queries + prepareStatement(); + + if (d_dolog) + g_log< 0) { + ub2 o_attrtype; + OCIParam *parms = NULL; + d_res = new struct oresult[d_fnum]; + memset(d_res, 0, sizeof(struct oresult)*d_fnum); + + for(int i=0; i < d_fnum; i++) { + if (OCIParamGet(d_stmt, OCI_HTYPE_STMT, d_err, (dvoid**)&parms, (ub4)i+1) != OCI_SUCCESS) { + throw SSqlException("Cannot get statement result column information: " + d_query + string(": ") + OCIErrStr()); + } + + if (OCIAttrGet(parms, OCI_DTYPE_PARAM, (dvoid*)&(d_res[i].colsize), 0, OCI_ATTR_DATA_SIZE, d_err) != OCI_SUCCESS) { + throw SSqlException("Cannot get statement result column information: " + d_query + string(": ") + OCIErrStr()); + } + + if (d_res[i].colsize == 0) { + if (OCIAttrGet(parms, OCI_DTYPE_PARAM, (dvoid*)&o_attrtype, 0, OCI_ATTR_DATA_TYPE, d_err) != OCI_SUCCESS) { + throw SSqlException("Cannot get statement result column information: " + d_query + string(": ") + OCIErrStr()); + } + + // oracle 11g returns 0 for integer fields - we know oracle should return 22. + if (o_attrtype == OCI_TYPECODE_INTEGER || + o_attrtype == OCI_TYPECODE_SMALLINT || + o_attrtype == OCI_TYPECODE_REAL || + o_attrtype == OCI_TYPECODE_DOUBLE || + o_attrtype == OCI_TYPECODE_FLOAT || + o_attrtype == OCI_TYPECODE_NUMBER || + o_attrtype == OCI_TYPECODE_DECIMAL) d_res[i].colsize = 22; + } + d_res[i].content = new char[d_res[i].colsize+1]; + } + } + + if (d_fnum > 0) { + for(int i=0;i=0) { + row.push_back(d_res[i].content); + } else { + row.push_back(""); + } + } + + d_queryResult = OCIStmtFetch2(d_stmt, d_err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + d_residx++; + return this; + } + + SSqlStatement* getResult(result_t& result) { + row_t row; + + result.reserve(d_resnum); + while(hasNextRow()) { + nextRow(row); + result.push_back(row); + } + + return this; + } + + SSqlStatement* reset() { + d_paridx = 0; + d_residx = d_resnum = 0; + + if (d_bind) { + for(int i=0;i SOracle::prepare(const string& query, int nparams) { + return std::unique_ptr(new SOracleStatement(query, s_dolog, nparams, d_environmentHandle, d_serviceContextHandle, d_release_stmt)); +} + +void SOracle::execute(const string& query) { + SOracleStatement(query, s_dolog, 0, d_environmentHandle, d_serviceContextHandle, true).execute(); +} + +string SOracle::getOracleError() +{ + string mReason = "ORA-UNKNOWN"; + if (d_errorHandle != NULL) { + text msg[512]; + sb4 errcode = 0; + memset(msg, 0, 512); + OCIErrorGet((dvoid*) d_errorHandle,1, NULL, &errcode, msg, sizeof(msg), OCI_HTYPE_ERROR); + if (errcode) { + char* p = (char*) msg; + while (*p++ != 0x00) { + if (*p == '\n' || *p == '\r') { + *p = ';'; + } + } + mReason = (char*) msg; + } + } + return mReason; +} diff --git a/modules/goraclebackend/soracle.hh b/modules/goraclebackend/soracle.hh new file mode 100644 index 0000000..2abae2b --- /dev/null +++ b/modules/goraclebackend/soracle.hh @@ -0,0 +1,64 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef SORACLE_HH +#define SORACLE_HH + +#include "pdns/backends/gsql/ssql.hh" +#include "pdns/utility.hh" +#include +#include +#include "pdns/misc.hh" + +#ifndef dsword +typedef sb4 dsword; +#endif + +class SOracle : public SSql +{ +public: + SOracle(const string &database, + const string &user="", + const string &password="", + bool releaseStatements=false, + OCIEnv* oraenv=NULL); + + ~SOracle(); + + SSqlException sPerrorException(const string &reason); + void setLog(bool state); + std::unique_ptr prepare(const string& query, int nparams); + void execute(const string& query); + + void startTransaction(); + void commit(); + void rollback(); +private: + OCIEnv* d_environmentHandle; + OCIError* d_errorHandle; + OCISvcCtx* d_serviceContextHandle; + + string getOracleError(); + static bool s_dolog; + bool d_release_stmt; +}; + +#endif /* SSORACLE_HH */ diff --git a/modules/gpgsqlbackend/3.4.0_to_4.1.0_schema.pgsql.sql b/modules/gpgsqlbackend/3.4.0_to_4.1.0_schema.pgsql.sql new file mode 100644 index 0000000..6c4f660 --- /dev/null +++ b/modules/gpgsqlbackend/3.4.0_to_4.1.0_schema.pgsql.sql @@ -0,0 +1 @@ +ALTER TABLE records ALTER id TYPE BIGINT; diff --git a/modules/gpgsqlbackend/4.1.0_to_4.2.0_schema.pgsql.sql b/modules/gpgsqlbackend/4.1.0_to_4.2.0_schema.pgsql.sql new file mode 100644 index 0000000..2333cf4 --- /dev/null +++ b/modules/gpgsqlbackend/4.1.0_to_4.2.0_schema.pgsql.sql @@ -0,0 +1,2 @@ +ALTER TABLE records DROP COLUMN change_date; +ALTER TABLE domains ALTER notified_serial TYPE bigint USING CASE WHEN notified_serial >= 0 THEN notified_serial::bigint END; diff --git a/modules/gpgsqlbackend/Makefile.am b/modules/gpgsqlbackend/Makefile.am new file mode 100644 index 0000000..f193cd4 --- /dev/null +++ b/modules/gpgsqlbackend/Makefile.am @@ -0,0 +1,23 @@ +AM_CPPFLAGS += $(PGSQL_CFLAGS) +pkglib_LTLIBRARIES = libgpgsqlbackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.pgsql.sql \ + nodnssec-3.x_to_3.4.0_schema.pgsql.sql \ + schema.pgsql.sql + +dist_doc_DATA = \ + schema.pgsql.sql \ + nodnssec-3.x_to_3.4.0_schema.pgsql.sql \ + dnssec-3.x_to_3.4.0_schema.pgsql.sql \ + 3.4.0_to_4.1.0_schema.pgsql.sql \ + 4.1.0_to_4.2.0_schema.pgsql.sql + +libgpgsqlbackend_la_SOURCES = \ + gpgsqlbackend.cc gpgsqlbackend.hh \ + spgsql.cc spgsql.hh + +libgpgsqlbackend_la_LDFLAGS = -module -avoid-version +libgpgsqlbackend_la_LIBADD = $(PGSQL_LIBS) diff --git a/modules/gpgsqlbackend/Makefile.in b/modules/gpgsqlbackend/Makefile.in new file mode 100644 index 0000000..9501728 --- /dev/null +++ b/modules/gpgsqlbackend/Makefile.in @@ -0,0 +1,868 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/gpgsqlbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libgpgsqlbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libgpgsqlbackend_la_OBJECTS = gpgsqlbackend.lo spgsql.lo +libgpgsqlbackend_la_OBJECTS = $(am_libgpgsqlbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgpgsqlbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgpgsqlbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgpgsqlbackend_la_SOURCES) +DIST_SOURCES = $(libgpgsqlbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(PGSQL_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libgpgsqlbackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.pgsql.sql \ + nodnssec-3.x_to_3.4.0_schema.pgsql.sql \ + schema.pgsql.sql + +dist_doc_DATA = \ + schema.pgsql.sql \ + nodnssec-3.x_to_3.4.0_schema.pgsql.sql \ + dnssec-3.x_to_3.4.0_schema.pgsql.sql \ + 3.4.0_to_4.1.0_schema.pgsql.sql \ + 4.1.0_to_4.2.0_schema.pgsql.sql + +libgpgsqlbackend_la_SOURCES = \ + gpgsqlbackend.cc gpgsqlbackend.hh \ + spgsql.cc spgsql.hh + +libgpgsqlbackend_la_LDFLAGS = -module -avoid-version +libgpgsqlbackend_la_LIBADD = $(PGSQL_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/gpgsqlbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/gpgsqlbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgpgsqlbackend.la: $(libgpgsqlbackend_la_OBJECTS) $(libgpgsqlbackend_la_DEPENDENCIES) $(EXTRA_libgpgsqlbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgpgsqlbackend_la_LINK) -rpath $(pkglibdir) $(libgpgsqlbackend_la_OBJECTS) $(libgpgsqlbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsqlbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spgsql.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/gpgsqlbackend/OBJECTFILES b/modules/gpgsqlbackend/OBJECTFILES new file mode 100644 index 0000000..288a969 --- /dev/null +++ b/modules/gpgsqlbackend/OBJECTFILES @@ -0,0 +1 @@ +gpgsqlbackend.lo spgsql.lo diff --git a/modules/gpgsqlbackend/OBJECTLIBS b/modules/gpgsqlbackend/OBJECTLIBS new file mode 100644 index 0000000..30be9e6 --- /dev/null +++ b/modules/gpgsqlbackend/OBJECTLIBS @@ -0,0 +1 @@ +-lssl -lcrypto $(PGSQL_LIBS) diff --git a/modules/gpgsqlbackend/dnssec-3.x_to_3.4.0_schema.pgsql.sql b/modules/gpgsqlbackend/dnssec-3.x_to_3.4.0_schema.pgsql.sql new file mode 100644 index 0000000..a70cc35 --- /dev/null +++ b/modules/gpgsqlbackend/dnssec-3.x_to_3.4.0_schema.pgsql.sql @@ -0,0 +1,35 @@ +/* Uncomment next 2 lines for versions <= 3.3 */ +/* ALTER TABLE domains ADD CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))); */ +/* ALTER TABLE tsigkeys ADD CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))); */ + +ALTER TABLE records ADD disabled BOOL DEFAULT 'f'; +ALTER TABLE records ALTER COLUMN content TYPE VARCHAR(65535); +ALTER TABLE records ALTER COLUMN auth SET DEFAULT 't'; +ALTER TABLE records ALTER COLUMN type TYPE VARCHAR(10); +ALTER TABLE supermasters ALTER COLUMN ip TYPE INET USING ip::INET; +ALTER TABLE supermasters ALTER COLUMN account SET DEFAULT NOT NULL; +ALTER TABLE supermasters ADD CONSTRAINT supermasters_pkey PRIMARY KEY (ip, nameserver); +ALTER TABLE domainmetadata ALTER COLUMN kind TYPE VARCHAR(32); +ALTER TABLE tsigkeys ALTER COLUMN algorithm TYPE VARCHAR(50); + +CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops); +DROP INDEX IF EXISTS orderindex; + + +CREATE TABLE comments ( + id SERIAL PRIMARY KEY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); diff --git a/modules/gpgsqlbackend/gpgsqlbackend.cc b/modules/gpgsqlbackend/gpgsqlbackend.cc new file mode 100644 index 0000000..cc1c601 --- /dev/null +++ b/modules/gpgsqlbackend/gpgsqlbackend.cc @@ -0,0 +1,190 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "gpgsqlbackend.hh" +#include "spgsql.hh" +#include +#include + +gPgSQLBackend::gPgSQLBackend(const string &mode, const string &suffix) : GSQLBackend(mode,suffix) +{ + try { + setDB(new SPgSQL(getArg("dbname"), + getArg("host"), + getArg("port"), + getArg("user"), + getArg("password"), + getArg("extra-connection-parameters"))); + } + + catch(SSqlException &e) { + g_log<reconnect(); + + allocateStatements(); + } +} + +bool gPgSQLBackend::inTransaction() +{ + const auto* db = dynamic_cast(d_db); + if (db) { + return db->in_trx(); + } + return false; +} + +class gPgSQLFactory : public BackendFactory +{ +public: + gPgSQLFactory(const string &mode) : BackendFactory(mode),d_mode(mode) {} + + void declareArguments(const string &suffix="") + { + declare(suffix,"dbname","Backend database name to connect to",""); + declare(suffix,"user","Database backend user to connect as",""); + declare(suffix,"host","Database backend host to connect to",""); + declare(suffix,"port","Database backend port to connect to",""); + declare(suffix,"password","Database backend password to connect with",""); + declare(suffix,"extra-connection-parameters", "Extra parameters to add to connection string",""); + + declare(suffix,"dnssec","Enable DNSSEC processing","no"); + + string record_query = "SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE"; + + declare(suffix, "basic-query", "Basic query", record_query+" disabled=false and type=$1 and name=$2"); + declare(suffix, "id-query", "Basic with ID query", record_query+" disabled=false and type=$1 and name=$2 and domain_id=$3"); + declare(suffix, "any-query", "Any query", record_query+" disabled=false and name=$1"); + declare(suffix, "any-id-query", "Any with ID query", record_query+" disabled=false and name=$1 and domain_id=$2"); + + declare(suffix, "list-query", "AXFR query", record_query+" (disabled=false OR $1) and domain_id=$2 order by name, type"); + declare(suffix, "list-subzone-query", "Subzone listing", record_query+" disabled=false and (name=$1 OR name like $2) and domain_id=$3"); + + declare(suffix,"remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id=$1 and type is null"); + declare(suffix,"delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id=$1 and name=$2 and type is null"); + + declare(suffix,"info-zone-query","","select id,name,master,last_check,notified_serial,type,account from domains where name=$1"); + + declare(suffix,"info-all-slaves-query","","select id,name,master,last_check from domains where type='SLAVE'"); + declare(suffix,"supermaster-query","", "select account from supermasters where ip=$1 and nameserver=$2"); + declare(suffix,"supermaster-name-to-ips", "", "select ip,account from supermasters where nameserver=$1 and account=$2"); + + declare(suffix,"insert-zone-query","", "insert into domains (type,name,master,account,last_check, notified_serial) values($1,$2,$3,$4,null,null)"); + + declare(suffix, "insert-record-query", "", "insert into records (content,ttl,prio,type,domain_id,disabled,name,ordername,auth) values ($1,$2,$3,$4,$5,$6,$7,$8,$9)"); + declare(suffix, "insert-empty-non-terminal-order-query", "insert empty non-terminal in zone", "insert into records (type,domain_id,disabled,name,ordername,auth,ttl,prio,content) values (null,$1,false,$2,$3,$4,null,null,null)"); + + declare(suffix, "get-order-first-query", "DNSSEC Ordering Query, last", "select ordername from records where disabled=false and domain_id=$1 and ordername is not null order by 1 using ~<~ limit 1"); + declare(suffix, "get-order-before-query", "DNSSEC Ordering Query, before", "select ordername, name from records where disabled=false and ordername ~<=~ $1 and domain_id=$2 and ordername is not null order by 1 using ~>~ limit 1"); + declare(suffix, "get-order-after-query", "DNSSEC Ordering Query, after", "select ordername from records where disabled=false and ordername ~>~ $1 and domain_id=$2 and ordername is not null order by 1 using ~<~ limit 1"); + declare(suffix, "get-order-last-query", "DNSSEC Ordering Query, last", "select ordername, name from records where disabled=false and ordername != '' and domain_id=$1 and ordername is not null order by 1 using ~>~ limit 1"); + + declare(suffix, "update-ordername-and-auth-query", "DNSSEC update ordername and auth for a qname query", "update records set ordername=$1,auth=$2 where domain_id=$3 and name=$4 and disabled=false"); + declare(suffix, "update-ordername-and-auth-type-query", "DNSSEC update ordername and auth for a rrset query", "update records set ordername=$1,auth=$2 where domain_id=$3 and name=$4 and type=$5 and disabled=false"); + declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=$1 where domain_id=$2 and name=$3 and disabled=false"); + declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=$1 where domain_id=$2 and name=$3 and type=$4 and disabled=false"); + + declare(suffix,"update-master-query","", "update domains set master=$1 where name=$2"); + declare(suffix,"update-kind-query","", "update domains set type=$1 where name=$2"); + declare(suffix,"update-account-query","", "update domains set account=$1 where name=$2"); + declare(suffix,"update-serial-query","", "update domains set notified_serial=$1 where id=$2"); + declare(suffix,"update-lastcheck-query","", "update domains set last_check=$1 where id=$2"); + declare(suffix,"info-all-master-query","", "select domains.id, domains.name, domains.notified_serial, records.content from records join domains on records.name=domains.name where records.type='SOA' and records.disabled=false and domains.type='MASTER'"); + declare(suffix,"delete-domain-query","", "delete from domains where name=$1"); + declare(suffix,"delete-zone-query","", "delete from records where domain_id=$1"); + declare(suffix,"delete-rrset-query","","delete from records where domain_id=$1 and name=$2 and type=$3"); + declare(suffix,"delete-names-query","","delete from records where domain_id=$1 and name=$2"); + + declare(suffix,"add-domain-key-query","", "insert into cryptokeys (domain_id, flags, active, content) select id, $1, $2, $3 from domains where name=$4"); + declare(suffix,"get-last-inserted-key-id-query","", "select lastval()"); + declare(suffix,"list-domain-keys-query","", "select cryptokeys.id, flags, case when active then 1 else 0 end as active, content from domains, cryptokeys where cryptokeys.domain_id=domains.id and name=$1"); + declare(suffix,"get-all-domain-metadata-query","", "select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=$1"); + declare(suffix,"get-domain-metadata-query","", "select content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=$1 and domainmetadata.kind=$2"); + declare(suffix,"clear-domain-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=$1) and domainmetadata.kind=$2"); + declare(suffix,"clear-domain-all-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=$1)"); + declare(suffix,"set-domain-metadata-query","", "insert into domainmetadata (domain_id, kind, content) select id, $1, $2 from domains where name=$3"); + declare(suffix,"activate-domain-key-query","", "update cryptokeys set active=true where domain_id=(select id from domains where name=$1) and cryptokeys.id=$2"); + declare(suffix,"deactivate-domain-key-query","", "update cryptokeys set active=false where domain_id=(select id from domains where name=$1) and cryptokeys.id=$2"); + declare(suffix,"remove-domain-key-query","", "delete from cryptokeys where domain_id=(select id from domains where name=$1) and cryptokeys.id=$2"); + declare(suffix,"clear-domain-all-keys-query","", "delete from cryptokeys where domain_id=(select id from domains where name=$1)"); + declare(suffix,"get-tsig-key-query","", "select algorithm, secret from tsigkeys where name=$1"); + declare(suffix,"set-tsig-key-query","", "insert into tsigkeys (name,algorithm,secret) values($1,$2,$3)"); + declare(suffix,"delete-tsig-key-query","", "delete from tsigkeys where name=$1"); + declare(suffix,"get-tsig-keys-query","", "select name,algorithm, secret from tsigkeys"); + + declare(suffix, "get-all-domains-query", "Retrieve all domains", "select domains.id, domains.name, records.content, domains.type, domains.master, domains.notified_serial, domains.last_check, domains.account from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name WHERE records.disabled=false OR $1"); + + declare(suffix, "list-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE domain_id=$1"); + declare(suffix, "insert-comment-query", "", "INSERT INTO comments (domain_id, name, type, modified_at, account, comment) VALUES ($1, $2, $3, $4, $5, $6)"); + declare(suffix, "delete-comment-rrset-query", "", "DELETE FROM comments WHERE domain_id=$1 AND name=$2 AND type=$3"); + declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=$1"); + declare(suffix, "search-records-query", "", record_query+" name LIKE $1 OR content LIKE $2 LIMIT $3"); + declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE $1 OR comment LIKE $2 LIMIT $3"); + + } + + DNSBackend *make(const string &suffix="") + { + return new gPgSQLBackend(d_mode,suffix); + } +private: + const string d_mode; +}; + + +//! Magic class that is activated when the dynamic library is loaded +class gPgSQLLoader +{ +public: + //! This reports us to the main UeberBackend class + gPgSQLLoader() + { + BackendMakers().report(new gPgSQLFactory("gpgsql")); + g_log << Logger::Info << "[gpgsqlbackend] This is the gpgsql backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; +static gPgSQLLoader gpgsqlloader; diff --git a/modules/gpgsqlbackend/gpgsqlbackend.hh b/modules/gpgsqlbackend/gpgsqlbackend.hh new file mode 100644 index 0000000..b1bef1d --- /dev/null +++ b/modules/gpgsqlbackend/gpgsqlbackend.hh @@ -0,0 +1,42 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_GPGSQLBACKEND_HH +#define PDNS_GPGSQLBACKEND_HH + +#include +#include +#include "pdns/backends/gsql/gsqlbackend.hh" + +#include "pdns/namespaces.hh" + +/** The gPgSQLBackend is a DNSBackend that can answer DNS related questions. It looks up data + in PostgreSQL */ +class gPgSQLBackend : public GSQLBackend +{ +public: + gPgSQLBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails. +protected: + void reconnect() override; + bool inTransaction() override; +}; + +#endif /* PDNS_GPGSQLBACKEND_HH */ diff --git a/modules/gpgsqlbackend/nodnssec-3.x_to_3.4.0_schema.pgsql.sql b/modules/gpgsqlbackend/nodnssec-3.x_to_3.4.0_schema.pgsql.sql new file mode 100644 index 0000000..b21458e --- /dev/null +++ b/modules/gpgsqlbackend/nodnssec-3.x_to_3.4.0_schema.pgsql.sql @@ -0,0 +1,64 @@ +/* Uncomment next line for versions <= 3.3 */ +/* ALTER TABLE domains ADD CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))); */ + +ALTER TABLE records ADD disabled BOOL DEFAULT 'f'; +ALTER TABLE records ALTER COLUMN content TYPE VARCHAR(65535); +ALTER TABLE records ADD ordername VARCHAR(255); +ALTER TABLE records ADD auth BOOL DEFAULT 't'; +ALTER TABLE records ALTER COLUMN type TYPE VARCHAR(10); +ALTER TABLE supermasters ALTER COLUMN ip TYPE INET USING ip::INET; +ALTER TABLE supermasters ALTER COLUMN account SET DEFAULT NOT NULL; +ALTER TABLE supermasters ADD CONSTRAINT supermasters_pkey PRIMARY KEY (ip, nameserver); + +CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops); + + +CREATE TABLE domainmetadata ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + kind VARCHAR(32), + content TEXT +); + +CREATE INDEX domainidmetaindex ON domainmetadata(domain_id); + + +CREATE TABLE cryptokeys ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + constraint c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); + + +CREATE TABLE comments ( + id SERIAL PRIMARY KEY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); diff --git a/modules/gpgsqlbackend/schema.pgsql.sql b/modules/gpgsqlbackend/schema.pgsql.sql new file mode 100644 index 0000000..911dd37 --- /dev/null +++ b/modules/gpgsqlbackend/schema.pgsql.sql @@ -0,0 +1,94 @@ +CREATE TABLE domains ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial BIGINT DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX name_index ON domains(name); + + +CREATE TABLE records ( + id BIGSERIAL PRIMARY KEY, + domain_id INT DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + disabled BOOL DEFAULT 'f', + ordername VARCHAR(255), + auth BOOL DEFAULT 't', + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX rec_name_index ON records(name); +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops); + + +CREATE TABLE supermasters ( + ip INET NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) NOT NULL, + PRIMARY KEY(ip, nameserver) +); + + +CREATE TABLE comments ( + id SERIAL PRIMARY KEY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +CREATE INDEX comments_name_type_idx ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + kind VARCHAR(32), + content TEXT +); + +CREATE INDEX domainidmetaindex ON domainmetadata(domain_id); + + +CREATE TABLE cryptokeys ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); diff --git a/modules/gpgsqlbackend/spgsql.cc b/modules/gpgsqlbackend/spgsql.cc new file mode 100644 index 0000000..e2052d8 --- /dev/null +++ b/modules/gpgsqlbackend/spgsql.cc @@ -0,0 +1,390 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "spgsql.hh" +#include +#include +#include "pdns/logger.hh" +#include "pdns/dns.hh" +#include "pdns/namespaces.hh" +#include + +class SPgSQLStatement: public SSqlStatement +{ +public: + SPgSQLStatement(const string& query, bool dolog, int nparams, SPgSQL* db, unsigned int nstatement) { + d_query = query; + d_dolog = dolog; + d_parent = db; + d_prepared = false; + d_nparams = nparams; + d_res = NULL; + d_res_set = NULL; + paramValues = NULL; + paramLengths = NULL; + d_nstatement = nstatement; + d_paridx = 0; + d_residx = 0; + d_resnum = 0; + d_fnum = 0; + d_cur_set = 0; + } + + SSqlStatement* bind(const string& name, bool value) { return bind(name, string(value ? "t" : "f")); } + SSqlStatement* bind(const string& name, int value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, uint32_t value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, long value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, unsigned long value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, long long value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, unsigned long long value) { return bind(name, std::to_string(value)); } + SSqlStatement* bind(const string& name, const std::string& value) { + prepareStatement(); + allocate(); + if (d_paridx>=d_nparams) { + releaseStatement(); + throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } + paramValues[d_paridx] = new char[value.size()+1]; + memset(paramValues[d_paridx], 0, sizeof(char)*(value.size()+1)); + value.copy(paramValues[d_paridx], value.size()); + paramLengths[d_paridx] = value.size(); + d_paridx++; + return this; + } + SSqlStatement* bindNull(const string& name) { prepareStatement(); d_paridx++; return this; } // these are set null in allocate() + SSqlStatement* execute() { + prepareStatement(); + if (d_dolog) { + g_log<= PQntuples(d_res_set)) { + PQclear(d_res_set); + d_res_set = NULL; + return; + } + // this code handles refcursors if they are returned + // by stored procedures. you can return more than one + // if you return SETOF refcursor. + if (PQftype(d_res_set, 0) == 1790) { // REFCURSOR +#if PG_VERSION_NUM > 90000 + // PQescapeIdentifier was added to libpq in postgresql 9.0 + char *val = PQgetvalue(d_res_set, d_cur_set++, 0); + char *portal = PQescapeIdentifier(d_db(), val, strlen(val)); + string cmd = string("FETCH ALL FROM \"") + string(portal) + string("\""); + PQfreemem(portal); +#else + string portal = string(PQgetvalue(d_res_set, d_cur_set++, 0)); + string cmd = string("FETCH ALL FROM \"") + portal + string("\""); +#endif + // execute FETCH + if (d_dolog) + g_log<=d_resnum || !d_res) return this; + row.reserve(PQnfields(d_res)); + for(i=0;i= d_resnum) { + PQclear(d_res); + d_res = NULL; + nextResult(); + } + return this; + } + + SSqlStatement* getResult(result_t& result) { + result.clear(); + if (d_res == NULL) return this; + result.reserve(d_resnum); + row_t row; + while(hasNextRow()) { nextRow(row); result.push_back(row); } + return this; + } + + SSqlStatement* reset() { + int i; + if (d_res) + PQclear(d_res); + if (d_res_set) + PQclear(d_res_set); + d_res_set = NULL; + d_res = NULL; + d_paridx = d_residx = d_resnum = 0; + if (paramValues) + for(i=0;idb(); + } + + void releaseStatement() { + d_prepared = false; + reset(); + if (!d_stmt.empty()) { + string cmd = string("DEALLOCATE " + d_stmt); + PGresult *res = PQexec(d_db(), cmd.c_str()); + PQclear(res); + d_stmt.clear(); + } + } + + void prepareStatement() { + if (d_prepared) return; + // prepare a statement; name must be unique per session (using d_nstatement to ensure this). + this->d_stmt = string("stmt") + std::to_string(d_nstatement); + PGresult* res = PQprepare(d_db(), d_stmt.c_str(), d_query.c_str(), d_nparams, NULL); + ExecStatusType status = PQresultStatus(res); + string errmsg(PQresultErrorMessage(res)); + PQclear(res); + if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_NONFATAL_ERROR) { + releaseStatement(); + throw SSqlException("Fatal error during prepare: " + d_query + string(": ") + errmsg); + } + paramValues=NULL; + d_cur_set=d_paridx=d_residx=d_resnum=d_fnum=0; + paramLengths=NULL; + d_res=NULL; + d_res_set=NULL; + d_prepared = true; + } + + void allocate() { + if (paramValues != NULL) return; + paramValues = new char*[d_nparams]; + paramLengths = new int[d_nparams]; + memset(paramValues, 0, sizeof(char*)*d_nparams); + memset(paramLengths, 0, sizeof(int)*d_nparams); + } + + string d_query; + string d_stmt; + SPgSQL *d_parent; + PGresult *d_res_set; + PGresult *d_res; + bool d_dolog; + DTime d_dtime; // only used if d_dolog is set + bool d_prepared; + int d_nparams; + int d_paridx; + char **paramValues; + int *paramLengths; + int d_residx; + int d_resnum; + int d_fnum; + int d_cur_set; + unsigned int d_nstatement; +}; + +bool SPgSQL::s_dolog; + +SPgSQL::SPgSQL(const string &database, const string &host, const string& port, const string &user, + const string &password, const string &extra_connection_parameters) +{ + d_db=0; + d_in_trx = false; + d_connectstr=""; + d_nstatement = 0; + + if (!database.empty()) + d_connectstr+="dbname="+database; + + if (!user.empty()) + d_connectstr+=" user="+user; + + if(!host.empty()) + d_connectstr+=" host="+host; + + if(!port.empty()) + d_connectstr+=" port="+port; + + if(!extra_connection_parameters.empty()) + d_connectstr+=" " + extra_connection_parameters; + + d_connectlogstr=d_connectstr; + + if(!password.empty()) { + d_connectlogstr+=" password="; + d_connectstr+=" password="+password; + } + + d_db=PQconnectdb(d_connectstr.c_str()); + + if (!d_db || PQstatus(d_db)==CONNECTION_BAD) { + try { + throw sPerrorException("Unable to connect to database, connect string: "+d_connectlogstr); + } + catch(...) { + if(d_db) + PQfinish(d_db); + d_db = 0; + throw; + } + } +} + +void SPgSQL::setLog(bool state) +{ + s_dolog=state; +} + +SPgSQL::~SPgSQL() +{ + PQfinish(d_db); +} + +SSqlException SPgSQL::sPerrorException(const string &reason) +{ + return SSqlException(reason+string(": ")+(d_db ? PQerrorMessage(d_db) : "no connection")); +} + +void SPgSQL::execute(const string& query) +{ + PGresult* res = PQexec(d_db, query.c_str()); + ExecStatusType status = PQresultStatus(res); + string errmsg(PQresultErrorMessage(res)); + PQclear(res); + if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_NONFATAL_ERROR) { + throw sPerrorException("Fatal error during query: " + errmsg); + } +} + +std::unique_ptr SPgSQL::prepare(const string& query, int nparams) +{ + d_nstatement++; + return std::unique_ptr(new SPgSQLStatement(query, s_dolog, nparams, this, d_nstatement)); +} + +void SPgSQL::startTransaction() { + execute("begin"); + d_in_trx = true; +} + +void SPgSQL::commit() { + execute("commit"); + d_in_trx = false; +} + +void SPgSQL::rollback() { + execute("rollback"); + d_in_trx = false; +} + +bool SPgSQL::isConnectionUsable() +{ + if (PQstatus(d_db) != CONNECTION_OK) { + return false; + } + + bool usable = false; + int sd = PQsocket(d_db); + bool wasNonBlocking = isNonBlocking(sd); + + if (!wasNonBlocking) { + if (!setNonBlocking(sd)) { + return usable; + } + } + + usable = isTCPSocketUsable(sd); + + if (!wasNonBlocking) { + if (!setBlocking(sd)) { + usable = false; + } + } + + return usable; +} + +void SPgSQL::reconnect() +{ + PQreset(d_db); +} diff --git a/modules/gpgsqlbackend/spgsql.hh b/modules/gpgsqlbackend/spgsql.hh new file mode 100644 index 0000000..35631e4 --- /dev/null +++ b/modules/gpgsqlbackend/spgsql.hh @@ -0,0 +1,61 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef SPGSQL_HH +#define SPGSQL_HH +#include "pdns/namespaces.hh" +#include "pdns/backends/gsql/ssql.hh" + +#include +class SPgSQL : public SSql +{ +public: + SPgSQL(const string &database, const string &host="", const string& port="", + const string &user="", const string &password="", + const string &extra_connection_parameters=""); + + ~SPgSQL(); + + SSqlException sPerrorException(const string &reason) override; + void setLog(bool state) override; + unique_ptr prepare(const string& query, int nparams) override; + void execute(const string& query) override; + + void startTransaction() override; + void rollback() override; + void commit() override; + + bool isConnectionUsable() override; + void reconnect() override; + + PGconn* db() { return d_db; } + bool in_trx() const { return d_in_trx; } + +private: + PGconn* d_db; + string d_connectstr; + string d_connectlogstr; + static bool s_dolog; + bool d_in_trx; + unsigned int d_nstatement; +}; + +#endif /* SPGSQL_HH */ diff --git a/modules/gsqlite3backend/3.4.0_to_4.0.0_schema.sqlite3.sql b/modules/gsqlite3backend/3.4.0_to_4.0.0_schema.sqlite3.sql new file mode 100644 index 0000000..2543c55 --- /dev/null +++ b/modules/gsqlite3backend/3.4.0_to_4.0.0_schema.sqlite3.sql @@ -0,0 +1,139 @@ +-- Disable foreign keys, if any +PRAGMA foreign_keys = 0; + +-- Replace records-table +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE records_backup ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + change_date INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1 + ); + + INSERT INTO records_backup SELECT id,domain_id,name,type,content,ttl,prio,change_date,disabled,ordername,auth FROM records; + DROP TABLE records; + + CREATE TABLE records ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + change_date INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE + ); + + CREATE INDEX rec_name_index ON records(name); + CREATE INDEX nametype_index ON records(name,type); + CREATE INDEX domain_id ON records(domain_id); + CREATE INDEX orderindex ON records(ordername); + + INSERT INTO records SELECT id,domain_id,name,type,content,ttl,prio,change_date,disabled,ordername,auth FROM records_backup; + DROP TABLE records_backup; +COMMIT; + +-- Replace comments-table +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE comments_backup ( + id INTEGER PRIMARY KEY, + domain_id INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL + ); + + INSERT INTO comments_backup SELECT id,domain_id,name,type,modified_at,account,comment FROM comments; + DROP TABLE comments; + + CREATE TABLE comments ( + id INTEGER PRIMARY KEY, + domain_id INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE + ); + + CREATE INDEX comments_domain_id_index ON comments (domain_id); + CREATE INDEX comments_nametype_index ON comments (name, type); + CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + INSERT INTO comments SELECT id,domain_id,name,type,modified_at,account,comment FROM comments_backup; + DROP TABLE comments_backup; +COMMIT; + +-- Replace domainmetadata-table +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE domainmetadata_backup ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT + ); + + INSERT INTO domainmetadata_backup SELECT id,domain_id,kind,content FROM domainmetadata; + DROP TABLE domainmetadata; + + CREATE TABLE domainmetadata ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE + ); + + CREATE INDEX domainmetaidindex ON domainmetadata(domain_id); + + INSERT INTO domainmetadata SELECT id,domain_id,kind,content FROM domainmetadata_backup; + DROP TABLE domainmetadata_backup; +COMMIT; + +-- Replace cryptokeys-table +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE cryptokeys_backup ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT + ); + + INSERT INTO cryptokeys_backup SELECT id,domain_id,flags,active,content FROM cryptokeys; + DROP TABLE cryptokeys; + + CREATE TABLE cryptokeys ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE + ); + + CREATE INDEX domainidindex ON cryptokeys(domain_id); + INSERT INTO cryptokeys SELECT id,domain_id,flags,active,content FROM cryptokeys_backup; + DROP TABLE cryptokeys_backup; +COMMIT; + +-- Check the current database for FOREIGN_KEYS after enabling it again +PRAGMA foreign_keys = 1; + +-- This command checks the status of the constraints. Output is in the form of: +-- [table]|[id]|[referred table]|[id])(which is probably 0, since the constraint fails)] +PRAGMA foreign_key_check; diff --git a/modules/gsqlite3backend/4.0.0_to_4.2.0_schema.sqlite3.sql b/modules/gsqlite3backend/4.0.0_to_4.2.0_schema.sqlite3.sql new file mode 100644 index 0000000..47c39ad --- /dev/null +++ b/modules/gsqlite3backend/4.0.0_to_4.2.0_schema.sqlite3.sql @@ -0,0 +1,39 @@ +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE records_backup ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1 + ); + + INSERT INTO records_backup SELECT id,domain_id,name,type,content,ttl,prio,disabled,ordername,auth FROM records; + DROP TABLE records; + + CREATE TABLE records ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE + ); + + CREATE INDEX rec_name_index ON records(name); + CREATE INDEX nametype_index ON records(name,type); + CREATE INDEX domain_id ON records(domain_id); + CREATE INDEX orderindex ON records(ordername); + + INSERT INTO records SELECT id,domain_id,name,type,content,ttl,prio,disabled,ordername,auth FROM records_backup; + DROP TABLE records_backup; +COMMIT; diff --git a/modules/gsqlite3backend/Makefile.am b/modules/gsqlite3backend/Makefile.am new file mode 100644 index 0000000..af15a03 --- /dev/null +++ b/modules/gsqlite3backend/Makefile.am @@ -0,0 +1,19 @@ +pkglib_LTLIBRARIES = libgsqlite3backend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + nodnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + schema.sqlite3.sql + +dist_doc_DATA = \ + dnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + nodnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + 3.4.0_to_4.0.0_schema.sqlite3.sql \ + 4.0.0_to_4.2.0_schema.sqlite3.sql \ + schema.sqlite3.sql + +libgsqlite3backend_la_SOURCES = gsqlite3backend.cc gsqlite3backend.hh + +libgsqlite3backend_la_LDFLAGS = -module -avoid-version diff --git a/modules/gsqlite3backend/Makefile.in b/modules/gsqlite3backend/Makefile.in new file mode 100644 index 0000000..865bd24 --- /dev/null +++ b/modules/gsqlite3backend/Makefile.in @@ -0,0 +1,862 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/gsqlite3backend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +libgsqlite3backend_la_LIBADD = +am_libgsqlite3backend_la_OBJECTS = gsqlite3backend.lo +libgsqlite3backend_la_OBJECTS = $(am_libgsqlite3backend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgsqlite3backend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgsqlite3backend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgsqlite3backend_la_SOURCES) +DIST_SOURCES = $(libgsqlite3backend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libgsqlite3backend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + nodnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + schema.sqlite3.sql + +dist_doc_DATA = \ + dnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + nodnssec-3.x_to_3.4.0_schema.sqlite3.sql \ + 3.4.0_to_4.0.0_schema.sqlite3.sql \ + 4.0.0_to_4.2.0_schema.sqlite3.sql \ + schema.sqlite3.sql + +libgsqlite3backend_la_SOURCES = gsqlite3backend.cc gsqlite3backend.hh +libgsqlite3backend_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/gsqlite3backend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/gsqlite3backend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgsqlite3backend.la: $(libgsqlite3backend_la_OBJECTS) $(libgsqlite3backend_la_DEPENDENCIES) $(EXTRA_libgsqlite3backend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgsqlite3backend_la_LINK) -rpath $(pkglibdir) $(libgsqlite3backend_la_OBJECTS) $(libgsqlite3backend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsqlite3backend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/gsqlite3backend/OBJECTFILES b/modules/gsqlite3backend/OBJECTFILES new file mode 100644 index 0000000..fe8c0e4 --- /dev/null +++ b/modules/gsqlite3backend/OBJECTFILES @@ -0,0 +1 @@ +gsqlite3backend.lo diff --git a/modules/gsqlite3backend/OBJECTLIBS b/modules/gsqlite3backend/OBJECTLIBS new file mode 100644 index 0000000..c18055a --- /dev/null +++ b/modules/gsqlite3backend/OBJECTLIBS @@ -0,0 +1 @@ +$(SQLITE3_LIBS) diff --git a/modules/gsqlite3backend/dnssec-3.x_to_3.4.0_schema.sqlite3.sql b/modules/gsqlite3backend/dnssec-3.x_to_3.4.0_schema.sqlite3.sql new file mode 100644 index 0000000..dc2f6c4 --- /dev/null +++ b/modules/gsqlite3backend/dnssec-3.x_to_3.4.0_schema.sqlite3.sql @@ -0,0 +1,101 @@ +CREATE TABLE comments ( + id INTEGER PRIMARY KEY, + domain_id INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL +); + +CREATE INDEX comments_domain_id_index ON comments (domain_id); +CREATE INDEX comments_nametype_index ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE records_backup( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + change_date INTEGER DEFAULT NULL, + ordername VARCHAR(255), + auth BOOL DEFAULT 1 + ); + + INSERT INTO records_backup SELECT id,domain_id,name,type,content,ttl,prio,change_date,ordername,auth FROM records; + DROP TABLE records; + + CREATE TABLE records ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + change_date INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1 + ); + + CREATE INDEX rec_name_index ON records(name); + CREATE INDEX nametype_index ON records(name,type); + CREATE INDEX domain_id ON records(domain_id); + CREATE INDEX orderindex ON records(ordername); + + INSERT INTO records SELECT id,domain_id,name,type,content,ttl,prio,change_date,0,ordername,auth FROM records_backup; + DROP TABLE records_backup; +COMMIT; + + +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE supermasters_backup ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, + account VARCHAR(40) DEFAULT NULL + ); + + INSERT INTO supermasters_backup SELECT ip,nameserver,account FROM supermasters; + UPDATE supermasters_backup SET account='' WHERE account IS NULL; + DROP TABLE supermasters; + + CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, + account VARCHAR(40) NOT NULL + ); + CREATE UNIQUE INDEX ip_nameserver_pk ON supermasters(ip, nameserver); + + INSERT INTO supermasters SELECT ip,nameserver,account FROM supermasters_backup; + DROP TABLE supermasters_backup; +COMMIT; + + +BEGIN TRANSACTION; + CREATE TABLE domainmetadata_backup ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT + ); + + INSERT INTO domainmetadata_backup SELECT id,domain_id,kind,content FROM domainmetadata; + DROP TABLE domainmetadata; + + CREATE TABLE domainmetadata ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT + ); + CREATE INDEX domainmetaidindex ON domainmetadata(domain_id); + + INSERT INTO domainmetadata SELECT id,domain_id,kind,content FROM domainmetadata_backup; + DROP TABLE domainmetadata_backup; +COMMIT; diff --git a/modules/gsqlite3backend/gsqlite3backend.cc b/modules/gsqlite3backend/gsqlite3backend.cc new file mode 100644 index 0000000..a188fc6 --- /dev/null +++ b/modules/gsqlite3backend/gsqlite3backend.cc @@ -0,0 +1,185 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/utility.hh" +#include +#include +#include +#include + +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/ssqlite3.hh" +#include "gsqlite3backend.hh" +#include + +// Connects to the database. +gSQLite3Backend::gSQLite3Backend( const std::string & mode, const std::string & suffix ) : GSQLBackend( mode, suffix ) +{ + try + { + SSQLite3 *ptr = new SSQLite3( getArg( "database" ), getArg( "pragma-journal-mode") ); + setDB(ptr); + if(!getArg("pragma-synchronous").empty()) { + ptr->execute("PRAGMA synchronous="+getArg("pragma-synchronous")); + } + if (mustDo("pragma-foreign-keys")) { + ptr->execute("PRAGMA foreign_keys = 1"); + } + } + catch( SSqlException & e ) + { + g_log << Logger::Error << mode << ": connection failed: " << e.txtReason() << std::endl; + throw PDNSException( "Unable to launch " + mode + " connection: " + e.txtReason()); + } + + g_log << Logger::Info << mode << ": connection to '"< :ordername and domain_id=:domain_id and ordername is not null"); + declare(suffix, "get-order-last-query", "DNSSEC Ordering Query, last", "select ordername, name from records where disabled=0 and ordername != '' and domain_id=:domain_id and ordername is not null order by 1 desc limit 1"); + + declare(suffix, "update-ordername-and-auth-query", "DNSSEC update ordername and auth for a qname query", "update records set ordername=:ordername,auth=:auth where domain_id=:domain_id and name=:qname and disabled=0"); + declare(suffix, "update-ordername-and-auth-type-query", "DNSSEC update ordername and auth for a rrset query", "update records set ordername=:ordername,auth=:auth where domain_id=:domain_id and name=:qname and type=:qtype and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and disabled=0"); + declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and type=:qtype and disabled=0"); + + declare(suffix, "update-master-query", "", "update domains set master=:master where name=:domain"); + declare(suffix, "update-kind-query", "", "update domains set type=:kind where name=:domain"); + declare(suffix, "update-account-query","", "update domains set account=:account where name=:domain"); + declare(suffix, "update-serial-query", "", "update domains set notified_serial=:serial where id=:domain_id"); + declare(suffix, "update-lastcheck-query", "", "update domains set last_check=:last_check where id=:domain_id"); + declare(suffix, "info-all-master-query", "", "select domains.id, domains.name, domains.notified_serial, records.content from records join domains on records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type='MASTER'"); + declare(suffix, "delete-domain-query","", "delete from domains where name=:domain"); + declare(suffix, "delete-zone-query", "", "delete from records where domain_id=:domain_id"); + declare(suffix, "delete-rrset-query", "", "delete from records where domain_id=:domain_id and name=:qname and type=:qtype"); + declare(suffix, "delete-names-query", "", "delete from records where domain_id=:domain_id and name=:qname"); + + declare(suffix, "add-domain-key-query","", "insert into cryptokeys (domain_id, flags, active, content) select id, :flags,:active, :content from domains where name=:domain"); + declare(suffix, "get-last-inserted-key-id-query", "", "select last_insert_rowid()"); + declare(suffix, "list-domain-keys-query","", "select cryptokeys.id, flags, active, content from domains, cryptokeys where cryptokeys.domain_id=domains.id and name=:domain"); + declare(suffix, "get-all-domain-metadata-query","", "select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=:domain"); + declare(suffix, "get-domain-metadata-query","", "select content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=:domain and domainmetadata.kind=:kind"); + declare(suffix, "clear-domain-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=:domain) and domainmetadata.kind=:kind"); + declare(suffix, "clear-domain-all-metadata-query","", "delete from domainmetadata where domain_id=(select id from domains where name=:domain)"); + declare(suffix, "set-domain-metadata-query","", "insert into domainmetadata (domain_id, kind, content) select id, :kind, :content from domains where name=:domain"); + declare(suffix, "activate-domain-key-query","", "update cryptokeys set active=1 where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "deactivate-domain-key-query","", "update cryptokeys set active=0 where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "remove-domain-key-query","", "delete from cryptokeys where domain_id=(select id from domains where name=:domain) and cryptokeys.id=:key_id"); + declare(suffix, "clear-domain-all-keys-query","", "delete from cryptokeys where domain_id=(select id from domains where name=:domain)"); + declare(suffix, "get-tsig-key-query","", "select algorithm, secret from tsigkeys where name=:key_name"); + declare(suffix, "set-tsig-key-query","", "replace into tsigkeys (name,algorithm,secret) values(:key_name,:algorithm,:content)"); + declare(suffix, "delete-tsig-key-query","", "delete from tsigkeys where name=:key_name"); + declare(suffix, "get-tsig-keys-query","", "select name,algorithm, secret from tsigkeys"); + + declare(suffix, "get-all-domains-query", "Retrieve all domains", "select domains.id, domains.name, records.content, domains.type, domains.master, domains.notified_serial, domains.last_check, domains.account from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name WHERE records.disabled=0 OR :include_disabled"); + + declare(suffix, "list-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE domain_id=:domain_id"); + declare(suffix, "insert-comment-query", "", "INSERT INTO comments (domain_id, name, type, modified_at, account, comment) VALUES (:domain_id, :qname, :qtype, :modified_at, :account, :content)"); + declare(suffix, "delete-comment-rrset-query", "", "DELETE FROM comments WHERE domain_id=:domain_id AND name=:qname AND type=:qtype"); + declare(suffix, "delete-comments-query", "", "DELETE FROM comments WHERE domain_id=:domain_id"); + declare(suffix, "search-records-query", "", record_query+" name LIKE :value OR content LIKE :value2 LIMIT :limit"); + declare(suffix, "search-comments-query", "", "SELECT domain_id,name,type,modified_at,account,comment FROM comments WHERE name LIKE :value OR comment LIKE :value2 LIMIT :limit"); + } + + //! Constructs a new gSQLite3Backend object. + DNSBackend *make( const string & suffix = "" ) + { + return new gSQLite3Backend( d_mode, suffix ); + } + +private: + const string d_mode; +}; + + +//! Magic class that is activated when the dynamic library is loaded +class gSQLite3Loader +{ +public: + //! This reports us to the main UeberBackend class + gSQLite3Loader() + { + BackendMakers().report( new gSQLite3Factory( "gsqlite3" )); + g_log << Logger::Info << "[gsqlite3] This is the gsqlite3 backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + +//! Reports the backendloader to the UeberBackend. +static gSQLite3Loader gsqlite3loader; + diff --git a/modules/gsqlite3backend/gsqlite3backend.hh b/modules/gsqlite3backend/gsqlite3backend.hh new file mode 100644 index 0000000..623d482 --- /dev/null +++ b/modules/gsqlite3backend/gsqlite3backend.hh @@ -0,0 +1,36 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef GSQLITEBACKEND_HH +#define GSQLITEBACKEND_HH + +#include +#include "pdns/backends/gsql/gsqlbackend.hh" + +//! The gSQLiteBackend retrieves it's data from a SQLite database (http://www.sqlite.org/) +class gSQLite3Backend : public GSQLBackend +{ +public: + //! Constructs the backend, throws an exception if it failed.. + gSQLite3Backend( const std::string & mode, const std::string & suffix ); +}; + +#endif // GSQLITEBACKEND_HH diff --git a/modules/gsqlite3backend/nodnssec-3.x_to_3.4.0_schema.sqlite3.sql b/modules/gsqlite3backend/nodnssec-3.x_to_3.4.0_schema.sqlite3.sql new file mode 100644 index 0000000..0385384 --- /dev/null +++ b/modules/gsqlite3backend/nodnssec-3.x_to_3.4.0_schema.sqlite3.sql @@ -0,0 +1,74 @@ +ALTER TABLE records ADD disabled BOOL DEFAULT 0; +ALTER TABLE records ADD ordername VARCHAR(255); +ALTER TABLE records ADD auth BOOL DEFAULT 1; + +CREATE INDEX orderindex ON records(ordername); + + +CREATE TABLE domainmetadata ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT +); + +CREATE INDEX domainmetaidindex on domainmetadata(domain_id); + + +CREATE TABLE cryptokeys ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INTEGER PRIMARY KEY, + name VARCHAR(255) COLLATE NOCASE, + algorithm VARCHAR(50) COLLATE NOCASE, + secret VARCHAR(255) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); + + +CREATE TABLE comments ( + id INTEGER PRIMARY KEY, + domain_id INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL +); + +CREATE INDEX comments_domain_id_index ON comments (domain_id); +CREATE INDEX comments_nametype_index ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +BEGIN TRANSACTION; + CREATE TEMPORARY TABLE supermasters_backup ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, + account VARCHAR(40) DEFAULT NULL + ); + + INSERT INTO supermasters_backup SELECT ip, nameserver, account FROM supermasters; + UPDATE supermasters_backup SET account='' WHERE account IS NULL; + DROP TABLE supermasters; + + CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, + account VARCHAR(40) NOT NULL + ); + CREATE UNIQUE INDEX ip_nameserver_pk ON supermasters(ip, nameserver); + + INSERT INTO supermasters SELECT ip, nameserver, account FROM supermasters_backup; + DROP TABLE supermasters_backup; +COMMIT; diff --git a/modules/gsqlite3backend/schema.sqlite3.sql b/modules/gsqlite3backend/schema.sqlite3.sql new file mode 100644 index 0000000..ed3a23d --- /dev/null +++ b/modules/gsqlite3backend/schema.sqlite3.sql @@ -0,0 +1,91 @@ +PRAGMA foreign_keys = 1; + +CREATE TABLE domains ( + id INTEGER PRIMARY KEY, + name VARCHAR(255) NOT NULL COLLATE NOCASE, + master VARCHAR(128) DEFAULT NULL, + last_check INTEGER DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial INTEGER DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL +); + +CREATE UNIQUE INDEX name_index ON domains(name); + + +CREATE TABLE records ( + id INTEGER PRIMARY KEY, + domain_id INTEGER DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + disabled BOOLEAN DEFAULT 0, + ordername VARCHAR(255), + auth BOOL DEFAULT 1, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE INDEX rec_name_index ON records(name); +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX orderindex ON records(ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, + account VARCHAR(40) NOT NULL +); + +CREATE UNIQUE INDEX ip_nameserver_pk ON supermasters(ip, nameserver); + + +CREATE TABLE comments ( + id INTEGER PRIMARY KEY, + domain_id INTEGER NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE INDEX comments_domain_id_index ON comments (domain_id); +CREATE INDEX comments_nametype_index ON comments (name, type); +CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE INDEX domainmetaidindex ON domainmetadata(domain_id); + + +CREATE TABLE cryptokeys ( + id INTEGER PRIMARY KEY, + domain_id INT NOT NULL, + flags INT NOT NULL, + active BOOL, + content TEXT, + FOREIGN KEY(domain_id) REFERENCES domains(id) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id INTEGER PRIMARY KEY, + name VARCHAR(255) COLLATE NOCASE, + algorithm VARCHAR(50) COLLATE NOCASE, + secret VARCHAR(255) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); diff --git a/modules/ldapbackend/Makefile.am b/modules/ldapbackend/Makefile.am new file mode 100644 index 0000000..53020a6 --- /dev/null +++ b/modules/ldapbackend/Makefile.am @@ -0,0 +1,22 @@ +pkglib_LTLIBRARIES = libldapbackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnsdomain2.schema \ + pdns-domaininfo.schema + +dist_doc_DATA = \ + dnsdomain2.schema \ + pdns-domaininfo.schema + +libldapbackend_la_SOURCES = \ + ldapbackend.cc ldapbackend.hh \ + master.cc native.cc \ + powerldap.cc powerldap.hh \ + utils.hh exceptions.hh \ + ldaputils.hh ldaputils.cc \ + ldapauthenticator.hh ldapauthenticator_p.hh ldapauthenticator.cc + +libldapbackend_la_LDFLAGS = -module -avoid-version +libldapbackend_la_LIBADD = $(LDAP_LIBS) $(KRB5_LIBS) diff --git a/modules/ldapbackend/Makefile.in b/modules/ldapbackend/Makefile.in new file mode 100644 index 0000000..6d14c92 --- /dev/null +++ b/modules/ldapbackend/Makefile.in @@ -0,0 +1,874 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/ldapbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libldapbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_libldapbackend_la_OBJECTS = ldapbackend.lo master.lo native.lo \ + powerldap.lo ldaputils.lo ldapauthenticator.lo +libldapbackend_la_OBJECTS = $(am_libldapbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libldapbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libldapbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libldapbackend_la_SOURCES) +DIST_SOURCES = $(libldapbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libldapbackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + dnsdomain2.schema \ + pdns-domaininfo.schema + +dist_doc_DATA = \ + dnsdomain2.schema \ + pdns-domaininfo.schema + +libldapbackend_la_SOURCES = \ + ldapbackend.cc ldapbackend.hh \ + master.cc native.cc \ + powerldap.cc powerldap.hh \ + utils.hh exceptions.hh \ + ldaputils.hh ldaputils.cc \ + ldapauthenticator.hh ldapauthenticator_p.hh ldapauthenticator.cc + +libldapbackend_la_LDFLAGS = -module -avoid-version +libldapbackend_la_LIBADD = $(LDAP_LIBS) $(KRB5_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/ldapbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/ldapbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libldapbackend.la: $(libldapbackend_la_OBJECTS) $(libldapbackend_la_DEPENDENCIES) $(EXTRA_libldapbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libldapbackend_la_LINK) -rpath $(pkglibdir) $(libldapbackend_la_OBJECTS) $(libldapbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldapauthenticator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldapbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldaputils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/native.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/powerldap.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/ldapbackend/OBJECTFILES b/modules/ldapbackend/OBJECTFILES new file mode 100644 index 0000000..d986486 --- /dev/null +++ b/modules/ldapbackend/OBJECTFILES @@ -0,0 +1 @@ +ldapbackend.lo master.lo native.lo powerldap.lo ldaputils.lo ldapauthenticator.lo diff --git a/modules/ldapbackend/OBJECTLIBS b/modules/ldapbackend/OBJECTLIBS new file mode 100644 index 0000000..f296c5a --- /dev/null +++ b/modules/ldapbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(LDAP_LIBS) $(KRB5_LIBS) diff --git a/modules/ldapbackend/dnsdomain2.schema b/modules/ldapbackend/dnsdomain2.schema new file mode 100644 index 0000000..2c88c34 --- /dev/null +++ b/modules/ldapbackend/dnsdomain2.schema @@ -0,0 +1,283 @@ +# A schema for storing DNS zones in LDAP +# +# ORDERING is not necessary, and some servers don't support +# integerOrderingMatch. Omit or change if you like + +attributetype ( 1.3.6.1.4.1.2428.20.0.0 NAME 'dNSTTL' + DESC 'An integer denoting time to live' + EQUALITY integerMatch + ORDERING integerOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) + +attributetype ( 1.3.6.1.4.1.2428.20.0.1 NAME 'dNSClass' + DESC 'The class of a resource record' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.11 NAME 'wKSRecord' + DESC 'a well known service description, RFC 1035' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.12 NAME 'pTRRecord' + DESC 'domain name pointer, RFC 1035' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.13 NAME 'hInfoRecord' + DESC 'host information, RFC 1035' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.14 NAME 'mInfoRecord' + DESC 'mailbox or mail list information, RFC 1035' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.16 NAME 'tXTRecord' + DESC 'text string, RFC 1035' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.17 NAME 'rPRecord' + DESC 'for Responsible Person, RFC 1183' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.18 NAME 'aFSDBRecord' + DESC 'for AFS Data Base location, RFC 1183' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.24 NAME 'SigRecord' + DESC 'Signature, RFC 2535' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.25 NAME 'KeyRecord' + DESC 'Key, RFC 2535' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.27 NAME 'gPosRecord' + DESC 'Geographical Position, RFC 1712' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.28 NAME 'aAAARecord' + DESC 'IPv6 address, RFC 1886' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.29 NAME 'LocRecord' + DESC 'Location, RFC 1876' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.30 NAME 'nXTRecord' + DESC 'non-existant, RFC 2535' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.33 NAME 'sRVRecord' + DESC 'service location, RFC 2782' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.35 NAME 'nAPTRRecord' + DESC 'Naming Authority Pointer, RFC 2915' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.36 NAME 'kXRecord' + DESC 'Key Exchange Delegation, RFC 2230' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.37 NAME 'certRecord' + DESC 'certificate, RFC 2538' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.38 NAME 'a6Record' + DESC 'A6 Record Type, RFC 2874' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.39 NAME 'dNameRecord' + DESC 'Non-Terminal DNS Name Redirection, RFC 2672' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.42 NAME 'aPLRecord' + DESC 'Lists of Address Prefixes, RFC 3123' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.43 NAME 'dSRecord' + DESC 'Delegation Signer, RFC 3658' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.44 NAME 'sSHFPRecord' + DESC 'SSH Key Fingerprint, RFC 4255' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.45 NAME 'iPSecKeyRecord' + DESC 'SSH Key Fingerprint, RFC 4025' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.46 NAME 'rRSIGRecord' + DESC 'RRSIG, RFC 3755' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.47 NAME 'nSECRecord' + DESC 'NSEC, RFC 3755' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.48 NAME 'dNSKeyRecord' + DESC 'DNSKEY, RFC 3755' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.49 NAME 'dHCIDRecord' + DESC 'DHCID, RFC 4701' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.50 NAME 'nSEC3Record' + DESC 'NSEC record version 3, RFC 5155' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.51 NAME 'nSEC3PARAMRecord' + DESC 'NSEC3 parameters, RFC 5155' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.52 NAME 'tLSARecord' + DESC 'TLSA certificate association, RFC 6698' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.59 NAME 'cDSRecord' + DESC 'Child DS, RFC7344' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.60 NAME 'cDNSKeyRecord' + DESC 'DNSKEY(s) the Child wants reflected in DS, RFC7344' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.61 NAME 'openPGPKeyRecord' + DESC 'OpenPGP Key, RFC7929' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.99 NAME 'sPFRecord' + DESC 'Sender Policy Framework, RFC 4408' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.108 NAME 'EUI48Record' + DESC 'EUI-48 address, RFC7043' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.109 NAME 'EUI64Record' + DESC 'EUI-64 address, RFC7043' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.249 NAME 'tKeyRecord' + DESC 'Transaction Key, RFC2930' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.256 NAME 'uRIRecord' + DESC 'URI, RFC7553' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.257 NAME 'cAARecord' + DESC 'Certification Authority Restriction, RFC6844' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.32769 NAME 'dLVRecord' + DESC 'DNSSEC Lookaside Validation, RFC4431' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.65226 NAME 'TYPE65226Record' + DESC '' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.2428.20.1.65534 NAME 'TYPE65534Record' + DESC '' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +objectclass ( 1.3.6.1.4.1.2428.20.2 NAME 'dNSDomain2' + SUP 'dNSDomain' STRUCTURAL + MAY ( DNSTTL $ DNSClass $ WKSRecord $ PTRRecord $ + HINFORecord $ MINFORecord $ TXTRecord $ RPRecord $ + AFSDBRecord $ SIGRecord $ KEYRecord $ GPOSRecord $ + AAAARecord $ LOCRecord $ NXTRecord $ SRVRecord $ + NAPTRRecord $ KXRecord $ CERTRecord $ A6Record $ + DNAMERecord $ APLRecord $ DSRecord $ SSHFPRecord $ + IPSECKEYRecord $ RRSIGRecord $ NSECRecord $ + DNSKEYRecord $ DHCIDRecord $ NSEC3Record $ NSEC3PARAMRecord $ + TLSARecord $ CDSRecord $ CDNSKEYRecord $ OPENPGPKEYRecord $ + SPFRecord $ EUI48Record $ EUI64Record $ TKEYRecord $ + URIRecord $ CAARecord $ DLVRecord $ TYPE65226Record $ + TYPE65534Record + ) ) diff --git a/modules/ldapbackend/exceptions.hh b/modules/ldapbackend/exceptions.hh new file mode 100644 index 0000000..3436e38 --- /dev/null +++ b/modules/ldapbackend/exceptions.hh @@ -0,0 +1,51 @@ +/* + * PowerDNS LDAP Connector + * By PowerDNS.COM BV + * By Norbert Sendetzky (2003-2007) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#ifndef LDAPEXCEPTIONS_HH +#define LDAPEXCEPTIONS_HH + +class LDAPException : public std::runtime_error +{ + public: + explicit LDAPException( const std::string &str ) : std::runtime_error( str ) {} +}; + +class LDAPTimeout : public LDAPException +{ + public: + explicit LDAPTimeout() : LDAPException( "Timeout" ) {} +}; + +class LDAPNoConnection : public LDAPException +{ + public: + explicit LDAPNoConnection() : LDAPException( "No connection to LDAP server" ) {} +}; + +class LDAPNoSuchObject : public LDAPException +{ + public: + explicit LDAPNoSuchObject() : LDAPException( "No such object" ) {} +}; + +#endif // LDAPEXCEPTIONS_HH diff --git a/modules/ldapbackend/ldapauthenticator.cc b/modules/ldapbackend/ldapauthenticator.cc new file mode 100644 index 0000000..e28f3e6 --- /dev/null +++ b/modules/ldapbackend/ldapauthenticator.cc @@ -0,0 +1,299 @@ +/* + * PowerDNS LDAP Backend + * Copyright (C) 2011 Grégory Oestreicher + * Copyright (C) 2003-2007 Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "ldapauthenticator_p.hh" +#include "ldaputils.hh" + +/***************************** + * + * LdapSimpleAuthenticator + * + ****************************/ + +LdapSimpleAuthenticator::LdapSimpleAuthenticator( const std::string& dn, const std::string& pw, int tmout ) + : d_binddn( dn ), d_bindpw( pw ), d_timeout( tmout ) +{ +} + +bool LdapSimpleAuthenticator::authenticate( LDAP *conn ) +{ + int msgid; + +#ifdef HAVE_LDAP_SASL_BIND + int rc; + struct berval passwd; + + passwd.bv_val = (char *)d_bindpw.c_str(); + passwd.bv_len = strlen( passwd.bv_val ); + + if( ( rc = ldap_sasl_bind( conn, d_binddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS ) + { + fillLastError( conn, rc ); + return false; + } +#else + if( ( msgid = ldap_bind( conn, d_binddn.c_str(), d_bindpw.c_str(), LDAP_AUTH_SIMPLE ) ) == -1 ) + { + fillLastError( conn, msgid ); + return false; + } +#endif + + ldapWaitResult( conn, msgid, d_timeout, NULL ); + return true; +} + +std::string LdapSimpleAuthenticator::getError() const +{ + return d_lastError; +} + +void LdapSimpleAuthenticator::fillLastError( LDAP* conn, int code ) +{ + d_lastError = ldapGetError( conn, code ); +} + +/***************************** + * + * LdapGssapiAuthenticator + * + ****************************/ + +static int ldapGssapiAuthenticatorSaslInteractCallback( LDAP *conn, unsigned flags, void *defaults, void *in ) +{ + return LDAP_SUCCESS; +} + +LdapGssapiAuthenticator::LdapGssapiAuthenticator( const std::string& kt, const std::string &ccache, int tmout ) + : d_logPrefix( "[LDAP GSSAPI] " ), d_keytabFile( kt ), d_cCacheFile( ccache ), d_timeout( tmout ) +{ + krb5_error_code code; + + if ( ( code = krb5_init_context( &d_context ) ) != 0 ) + throw PDNSException( d_logPrefix + std::string( "Failed to initialize krb5 context" ) ); + + // Locate the credentials cache file + if ( !d_cCacheFile.empty() ) { + std::string cCacheStr( "FILE:" + d_cCacheFile ); + code = krb5_cc_resolve( d_context, cCacheStr.c_str(), &d_ccache ); + } + else { + code = krb5_cc_default( d_context, &d_ccache ); + } + + if ( code != 0 ) + throw PDNSException( d_logPrefix + + std::string( "krb5 error when locating the credentials cache file: " ) + + std::string( krb5_get_error_message( d_context, code ) ) ); +} + +LdapGssapiAuthenticator::~LdapGssapiAuthenticator() +{ + krb5_cc_close( d_context, d_ccache ); + krb5_free_context( d_context ); +} + +bool LdapGssapiAuthenticator::authenticate( LDAP *conn ) +{ + int code = attemptAuth( conn ); + + if ( code == -1 ) { + return false; + } + else if ( code == -2 ) { + // Here it may be possible to retry after obtainting a fresh ticket + g_log< + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef LDAPAUTHENTICATOR_HH +#define LDAPAUTHENTICATOR_HH + +class LdapAuthenticator +{ + public: + virtual ~LdapAuthenticator() {} + virtual bool authenticate( LDAP *connection ) = 0; + virtual std::string getError() const = 0; +}; + +#endif // LDAPAUTHENTICATOR_HH diff --git a/modules/ldapbackend/ldapauthenticator_p.hh b/modules/ldapbackend/ldapauthenticator_p.hh new file mode 100644 index 0000000..cd5d083 --- /dev/null +++ b/modules/ldapbackend/ldapauthenticator_p.hh @@ -0,0 +1,72 @@ +/* + * PowerDNS LDAP Backend + * Copyright (C) 2011 Grégory Oestreicher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "ldapauthenticator.hh" + +#ifndef LDAPAUTHENTICATOR_P_HH +#define LDAPAUTHENTICATOR_P_HH + +#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS +#define krb5_get_init_creds_opt_set_default_flags( a, b, c, d ) /* This does not exist with MIT Kerberos */ +#endif + +class LdapSimpleAuthenticator : public LdapAuthenticator +{ + std::string d_binddn; + std::string d_bindpw; + int d_timeout; + std::string d_lastError; + + void fillLastError( LDAP *conn, int code ); + + public: + LdapSimpleAuthenticator( const std::string &dn, const std::string &pw, int timeout ); + virtual bool authenticate( LDAP *conn ); + virtual std::string getError() const; +}; + +class LdapGssapiAuthenticator : public LdapAuthenticator +{ + std::string d_logPrefix; + std::string d_keytabFile; + std::string d_cCacheFile; + int d_timeout; + std::string d_lastError; + + krb5_context d_context; + krb5_ccache d_ccache; + + struct SaslDefaults { + std::string mech; + std::string realm; + std::string authcid; + std::string authzid; + }; + + int attemptAuth( LDAP *conn ); + int updateTgt(); + + public: + LdapGssapiAuthenticator( const std::string &keytab, const std::string &credsCache, int timeout ); + ~LdapGssapiAuthenticator(); + virtual bool authenticate( LDAP *conn ); + virtual std::string getError() const; +}; + +#endif // LDAPAUTHENTICATOR_P_HH diff --git a/modules/ldapbackend/ldapbackend.cc b/modules/ldapbackend/ldapbackend.cc new file mode 100644 index 0000000..1a4374f --- /dev/null +++ b/modules/ldapbackend/ldapbackend.cc @@ -0,0 +1,328 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "exceptions.hh" +#include "ldapauthenticator_p.hh" +#include "ldapbackend.hh" +#include + +unsigned int ldap_host_index = 0; + +LdapBackend::LdapBackend( const string &suffix ) +{ + string hoststr; + unsigned int i, idx; + vector hosts; + + + try + { + d_qname.clear(); + d_pldap = NULL; + d_authenticator = NULL; + d_qlog = arg().mustDo( "query-logging" ); + d_default_ttl = arg().asNum( "default-ttl" ); + d_myname = "[LdapBackend]"; + d_in_list = false; + + setArgPrefix( "ldap" + suffix ); + + d_getdn = false; + d_reconnect_attempts = getArgAsNum( "reconnect-attempts" ); + d_list_fcnt = &LdapBackend::list_simple; + d_lookup_fcnt = &LdapBackend::lookup_simple; + + if( getArg( "method" ) == "tree" ) + { + d_lookup_fcnt = &LdapBackend::lookup_tree; + } + + if( getArg( "method" ) == "strict" || mustDo( "disable-ptrrecord" ) ) + { + d_list_fcnt = &LdapBackend::list_strict; + d_lookup_fcnt = &LdapBackend::lookup_strict; + } + + stringtok( hosts, getArg( "host" ), ", " ); + idx = ldap_host_index++ % hosts.size(); + hoststr = hosts[idx]; + + for( i = 1; i < hosts.size(); i++ ) + { + hoststr += " " + hosts[ ( idx + i ) % hosts.size() ]; + } + + g_log << Logger::Info << d_myname << " LDAP servers = " << hoststr << endl; + + d_pldap = new PowerLDAP( hoststr.c_str(), LDAP_PORT, mustDo( "starttls" ), getArgAsNum( "timeout" ) ); + d_pldap->setOption( LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + + string bindmethod = getArg( "bindmethod" ); + if ( bindmethod == "gssapi" ) { + setenv( "KRB5CCNAME", getArg( "krb5-ccache" ).c_str(), 1 ); + d_authenticator = new LdapGssapiAuthenticator( getArg( "krb5-keytab" ), getArg( "krb5-ccache" ), getArgAsNum( "timeout" ) ); + } + else { + d_authenticator = new LdapSimpleAuthenticator( getArg( "binddn" ), getArg( "secret" ), getArgAsNum( "timeout" ) ); + } + d_pldap->bind( d_authenticator ); + + g_log << Logger::Notice << d_myname << " Ldap connection succeeded" << endl; + return; + } + catch( LDAPTimeout < ) + { + g_log << Logger::Error << d_myname << " Ldap connection to server failed because of timeout" << endl; + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Ldap connection to server failed: " << le.what() << endl; + } + catch( std::exception &e ) + { + g_log << Logger::Error << d_myname << " Caught STL exception: " << e.what() << endl; + } + + if( d_pldap != NULL ) { delete( d_pldap ); } + throw PDNSException( "Unable to connect to ldap server" ); +} + + + +LdapBackend::~LdapBackend() +{ + d_search.reset(); // This is necessary otherwise d_pldap will get deleted first and + // we may hang in SearchResult::~SearchResult() waiting for the + // current operation to be abandoned + delete( d_pldap ); + delete( d_authenticator ); + g_log << Logger::Notice << d_myname << " Ldap connection closed" << endl; +} + + + +bool LdapBackend::reconnect() +{ + int attempts = d_reconnect_attempts; + bool connected = false; + while ( !connected && attempts > 0 ) { + g_log << Logger::Debug << d_myname << " Reconnection attempts left: " << attempts << endl; + connected = d_pldap->connect(); + if ( !connected ) + Utility::usleep( 250 ); + --attempts; + } + + if ( connected ) + d_pldap->bind( d_authenticator ); + + return connected; +} + + +void LdapBackend::extract_common_attributes( DNSResult &result ) { + if ( d_result.count( "dNSTTL" ) && !d_result["dNSTTL"].empty() ) { + char *endptr; + uint32_t ttl = (uint32_t) strtol( d_result["dNSTTL"][0].c_str(), &endptr, 10 ); + + if ( *endptr != '\0' ) { + // NOTE: this will not give the entry for which the TTL was off. + // TODO: improve this. + // - Check how d_getdn is used, because if it's never false then we + // might as well use it. + g_log << Logger::Warning << d_myname << " Invalid time to live for " << d_qname << ": " << d_result["dNSTTL"][0] << endl; + } + else { + result.ttl = ttl; + } + + // We have to erase the attribute, otherwise this will mess up the records retrieval later. + d_result.erase( "dNSTTL" ); + } + + if ( d_result.count( "modifyTimestamp" ) && !d_result["modifyTimestamp"].empty() ) { + time_t tstamp = 0; + if ( ( tstamp = str2tstamp( d_result["modifyTimestamp"][0] ) ) == 0 ) { + // Same note as above, we don't know which entry failed here + g_log << Logger::Warning << d_myname << " Invalid modifyTimestamp for " << d_qname << ": " << d_result["modifyTimestamp"][0] << endl; + } + else { + result.lastmod = tstamp; + } + + // Here too we have to erase this attribute. + d_result.erase( "modifyTimestamp" ); + } +} + + +void LdapBackend::extract_entry_results( const DNSName& domain, const DNSResult& result_template, QType qtype ) { + std:: string attrname, qstr; + QType qt; + bool has_records = false; + + for ( const auto& attribute : d_result ) { + // Find if we're dealing with a record attribute + if ( attribute.first.length() > 6 && attribute.first.compare( attribute.first.length() - 6, 6, "Record" ) == 0 ) { + has_records = true; + attrname = attribute.first; + // extract qtype string from ldap attribute name by removing the 'Record' suffix. + qstr = attrname.substr( 0, attrname.length() - 6 ); + qt = toUpper( qstr ); + + for ( const auto& value : attribute.second ) { + if(qtype != qt && qtype != QType::ANY) { + continue; + } + + DNSResult local_result = result_template; + local_result.qtype = qt; + local_result.qname = domain; + local_result.value = value; + local_result.auth = true; + + // Now let's see if we have some PDNS record data + + // TTL + if ( d_result.count( "PdnsRecordTTL" ) && !d_result["PdnsRecordTTL"].empty() ) { + for ( const auto& rdata : d_result["PdnsRecordTTL"] ) { + std::string qtype; + std::size_t pos = rdata.find_first_of( '|', 0 ); + if ( pos == std::string::npos ) + continue; + + qtype = rdata.substr( 0, pos ); + if ( qtype != QType( local_result.qtype ).getName() ) + continue; + + local_result.ttl = pdns_stou( rdata.substr( pos + 1 ) ); + } + } + + // Not authoritative + if ( d_result.count( "PdnsRecordNoAuth" ) && !d_result["PdnsRecordNoAuth"].empty() ) { + for ( const auto& rdata : d_result["PdnsRecordNoAuth"] ) { + if ( rdata == QType( local_result.qtype ).getName() ) + local_result.auth = false; + } + } + + // Ordername + if ( d_result.count( "PdnsRecordOrdername" ) && !d_result["PdnsRecordOrdername"].empty() ) { + std::string defaultOrdername; + + for ( const auto& rdata : d_result["PdnsRecordOrdername"] ) { + std::string qtype; + std::size_t pos = rdata.find_first_of( '|', 0 ); + if ( pos == std::string::npos ) { + // This is the default ordername for all records in this entry + defaultOrdername = rdata; + continue; + } + + qtype = rdata.substr( 0, pos ); + if ( qtype != QType( local_result.qtype ).getName() ) + continue; + + local_result.ordername = rdata.substr( pos + 1 ); + } + + if ( local_result.ordername.empty() && !defaultOrdername.empty() ) + local_result.ordername = defaultOrdername; + } + + d_results_cache.push_back( local_result ); + } + } + } + + if ( !has_records ) { + // This is an ENT + DNSResult local_result = result_template; + local_result.qname = domain; + if ( !d_result.count( "PdnsRecordOrdername" ) || d_result["PdnsRecordOrdername"].empty() ) { + // An ENT with an order name is authoritative + local_result.auth = false; + } + d_results_cache.push_back( local_result ); + } +} + + +class LdapFactory : public BackendFactory +{ + public: + + LdapFactory() : BackendFactory( "ldap" ) {} + + void declareArguments( const string &suffix="" ) + { + declare( suffix, "host", "One or more LDAP server with ports or LDAP URIs (separated by spaces)","ldap://127.0.0.1:389/" ); + declare( suffix, "starttls", "Use TLS to encrypt connection (unused for LDAP URIs)", "no" ); + declare( suffix, "basedn", "Search root in ldap tree (must be set)","" ); + declare( suffix, "basedn-axfr-override", "Override base dn for AXFR subtree search", "no" ); + declare( suffix, "bindmethod", "Bind method to use (simple or gssapi)", "simple" ); + declare( suffix, "binddn", "User dn for non anonymous binds","" ); + declare( suffix, "secret", "User password for non anonymous binds", "" ); + declare( suffix, "krb5-keytab", "The keytab to use for GSSAPI authentication", "" ); + declare( suffix, "krb5-ccache", "The credentials cache used for GSSAPI authentication", "" ); + declare( suffix, "timeout", "Seconds before connecting to server fails", "5" ); + declare( suffix, "method", "How to search entries (simple, strict or tree)", "simple" ); + declare( suffix, "filter-axfr", "LDAP filter for limiting AXFR results", "(:target:)" ); + declare( suffix, "filter-lookup", "LDAP filter for limiting IP or name lookups", "(:target:)" ); + declare( suffix, "disable-ptrrecord", "Deprecated, use ldap-method=strict instead", "no" ); + declare( suffix, "reconnect-attempts", "Number of attempts to re-establish a lost LDAP connection", "5" ); + } + + + DNSBackend* make( const string &suffix="" ) + { + return new LdapBackend( suffix ); + } +}; + + + + + +class LdapLoader +{ + LdapFactory factory; + + public: + + LdapLoader() + { + BackendMakers().report( &factory ); + g_log << Logger::Info << "[ldapbackend] This is the ldap backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + + +static LdapLoader ldaploader; diff --git a/modules/ldapbackend/ldapbackend.hh b/modules/ldapbackend/ldapbackend.hh new file mode 100644 index 0000000..7fe7df8 --- /dev/null +++ b/modules/ldapbackend/ldapbackend.hh @@ -0,0 +1,187 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pdns/dns.hh" +#include "pdns/utility.hh" +#include "pdns/dnspacket.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/arguments.hh" +#include "pdns/logger.hh" +#include "powerldap.hh" +#include "utils.hh" + + + +#ifndef LDAPBACKEND_HH +#define LDAPBACKEND_HH + +using std::string; +using std::vector; + +class LdapAuthenticator; + +/* + * Known DNS RR types + * Types which aren't active are currently not supported by PDNS + */ + +__attribute__ ((unused)) static const char* ldap_attrany[] = { + "associatedDomain", + "dNSTTL", + "ALIASRecord", + "aRecord", + "nSRecord", + "cNAMERecord", + "sOARecord", + "pTRRecord", + "hInfoRecord", + "mXRecord", + "tXTRecord", + "rPRecord", + "aFSDBRecord", +// "SigRecord", + "KeyRecord", +// "gPosRecord", + "aAAARecord", + "lOCRecord", + "sRVRecord", + "nAPTRRecord", + "kXRecord", + "certRecord", +// "a6Record", + "dNameRecord", +// "aPLRecord", + "dSRecord", + "sSHFPRecord", + "iPSecKeyRecord", + "rRSIGRecord", + "nSECRecord", + "dNSKeyRecord", + "dHCIDRecord", + "nSEC3Record", + "nSEC3PARAMRecord", + "tLSARecord", + "cDSRecord", + "cDNSKeyRecord", + "openPGPKeyRecord", + "sPFRecord", + "EUI48Record", + "EUI64Record", + "tKeyRecord", + "uRIRecord", + "cAARecord", + "TYPE65226Record", + "TYPE65534Record", + "modifyTimestamp", + "PdnsRecordTTL", + "PdnsRecordAuth", + "PdnsRecordOrdername", + NULL +}; + + + +class LdapBackend : public DNSBackend +{ + string d_myname; + + bool d_qlog; + uint32_t d_default_ttl; + int d_reconnect_attempts; + + bool d_getdn; + PowerLDAP::SearchResult::Ptr d_search; + PowerLDAP::sentry_t d_result; + bool d_in_list; + + struct DNSResult { + QType qtype; + DNSName qname; + uint32_t ttl; + time_t lastmod; + std::string value; + bool auth; + std::string ordername; + + DNSResult() + : ttl( 0 ), lastmod( 0 ), value( "" ), auth( true ), ordername( "" ) + { + } + }; + std::list d_results_cache; + + DNSName d_qname; + QType d_qtype; + + PowerLDAP* d_pldap; + LdapAuthenticator *d_authenticator; + + bool (LdapBackend::*d_list_fcnt)( const DNSName&, int ); + void (LdapBackend::*d_lookup_fcnt)( const QType&, const DNSName&, DNSPacket*, int ); + + bool list_simple( const DNSName& target, int domain_id ); + bool list_strict( const DNSName& target, int domain_id ); + + void lookup_simple( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); + void lookup_strict( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); + void lookup_tree( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); + + bool reconnect(); + + // Extracts common attributes from the current result stored in d_result and sets them in the given DNSResult. + // This will modify d_result by removing attributes that may interfere with the records extraction later. + void extract_common_attributes( DNSResult &result ); + + // Extract LDAP attributes for the current result stored in d_result and create a new DNSResult that will + // be appended in the results cache. The result parameter is used as a template that will be copied for + // each result extracted from the entry. + // The given domain will be added as the qname attribute of the result. + // The qtype parameter is used to filter extracted results. + void extract_entry_results( const DNSName& domain, const DNSResult& result, QType qtype ); + + public: + + LdapBackend( const string &suffix="" ); + ~LdapBackend(); + + // Native backend + bool list( const DNSName& target, int domain_id, bool include_disabled=false ) override; + void lookup( const QType& qtype, const DNSName& qdomain, DNSPacket* p = 0, int zoneid = -1 ) override; + bool get( DNSResourceRecord& rr ) override; + + bool getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial=true ) override; + + // Master backend + void getUpdatedMasters( vector* domains ) override; + void setNotified( uint32_t id, uint32_t serial ) override; +}; + +#endif /* LDAPBACKEND_HH */ diff --git a/modules/ldapbackend/ldaputils.cc b/modules/ldapbackend/ldaputils.cc new file mode 100644 index 0000000..13c929d --- /dev/null +++ b/modules/ldapbackend/ldaputils.cc @@ -0,0 +1,49 @@ +#include "ldaputils.hh" +#include + +void ldapSetOption( LDAP *conn, int option, void *value ) +{ + if( ldap_set_option( conn, option, value ) != LDAP_OPT_SUCCESS ) + { + throw LDAPException( "Unable to set option" ); + } +} + +void ldapGetOption( LDAP *conn, int option, void *value ) +{ + if( ldap_get_option( conn, option, value ) != LDAP_OPT_SUCCESS ) + { + throw LDAPException( "Unable to get option" ); + } +} + +std::string ldapGetError( LDAP *conn, int code ) +{ + if ( code == -1 ) + ldapGetOption( conn, LDAP_OPT_ERROR_NUMBER, &code ); + return std::string( ldap_err2string( code ) ); +} + +int ldapWaitResult( LDAP *conn, int msgid, int timeout, LDAPMessage** result ) +{ + struct timeval tv; + LDAPMessage* res; + + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + int rc = ldap_result( conn, msgid, LDAP_MSG_ONE, &tv, &res ); + + if ( rc == -1 || rc == 0 ) + return rc; + + if( result == NULL ) + { + ldap_msgfree( res ); + return rc; + } + + *result = res; + return rc; +} diff --git a/modules/ldapbackend/ldaputils.hh b/modules/ldapbackend/ldaputils.hh new file mode 100644 index 0000000..83012f2 --- /dev/null +++ b/modules/ldapbackend/ldaputils.hh @@ -0,0 +1,36 @@ +/* + * PowerDNS LDAP Connector + * By PowerDNS.COM BV + * By Norbert Sendetzky (2003-2007) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "exceptions.hh" + +#include +#include + +#ifndef LDAPUTILS_HH +#define LDAPUTILS_HH + +void ldapSetOption( LDAP *conn, int option, void *value ); + +void ldapGetOption( LDAP *conn, int option, void *value ); + +std::string ldapGetError( LDAP *conn, int code ); + +int ldapWaitResult( LDAP *conn, int msgid, int timeout, LDAPMessage** result = NULL ); + +#endif // LDAPUTILS_HH diff --git a/modules/ldapbackend/master.cc b/modules/ldapbackend/master.cc new file mode 100644 index 0000000..c83b573 --- /dev/null +++ b/modules/ldapbackend/master.cc @@ -0,0 +1,160 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "exceptions.hh" +#include "ldapbackend.hh" +#include + + +void LdapBackend::getUpdatedMasters( vector* domains ) +{ + string filter; + PowerLDAP::SearchResult::Ptr search; + PowerLDAP::sentry_t result; + const char* attronly[] = { + "associatedDomain", + NULL + }; + + try + { + // First get all domains on which we are master. + filter = strbind( ":target:", "&(SOARecord=*)(PdnsDomainId=*)", getArg( "filter-axfr" ) ); + search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); + } + catch( LDAPTimeout < ) + { + g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; + throw DBException( "LDAP server timeout" ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->getUpdatedMasters( domains ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + throw DBException( "STL exception" ); + } + + while( search->getNext( result ) ) { + if( !result.count( "associatedDomain" ) || result["associatedDomain"].empty() ) + continue; + + DomainInfo di; + if ( !getDomainInfo( DNSName( result["associatedDomain"][0] ), di ) ) + continue; + + if( di.notified_serial < di.serial ) + domains->push_back( di ); + } +} + + + +void LdapBackend::setNotified( uint32_t id, uint32_t serial ) +{ + string filter; + PowerLDAP::SearchResult::Ptr search; + PowerLDAP::sresult_t results; + PowerLDAP::sentry_t entry; + const char* attronly[] = { "associatedDomain", NULL }; + + try + { + // Try to find the notified domain + filter = strbind( ":target:", "PdnsDomainId=" + std::to_string( id ), getArg( "filter-axfr" ) ); + search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); + search->getAll( results, true ); + } + catch( LDAPTimeout < ) + { + g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; + throw DBException( "LDAP server timeout" ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->setNotified( id, serial ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + throw DBException( "STL exception" ); + } + + if ( results.empty() ) + throw PDNSException( "No results found when trying to update domain notified_serial for ID " + std::to_string( id ) ); + + entry = results.front(); + string dn = entry["dn"][0]; + string serialStr = std::to_string( serial ); + LDAPMod *mods[2]; + LDAPMod mod; + char *vals[2]; + + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = (char*)"PdnsDomainNotifiedSerial"; + vals[0] = const_cast( serialStr.c_str() ); + vals[1] = NULL; + mod.mod_values = vals; + + mods[0] = &mod; + mods[1] = NULL; + + try + { + d_pldap->modify( dn, mods ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->setNotified( id, serial ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + throw DBException( "STL exception" ); + } +} diff --git a/modules/ldapbackend/native.cc b/modules/ldapbackend/native.cc new file mode 100644 index 0000000..c0f913f --- /dev/null +++ b/modules/ldapbackend/native.cc @@ -0,0 +1,448 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "exceptions.hh" +#include "ldapbackend.hh" +#include + + +bool LdapBackend::list( const DNSName& target, int domain_id, bool include_disabled ) +{ + try + { + d_in_list = true; + d_qname = target; + d_qtype = QType::ANY; + d_results_cache.clear(); + + return (this->*d_list_fcnt)( target, domain_id ); + } + catch( LDAPTimeout < ) + { + g_log << Logger::Warning << d_myname << " Unable to get zone " << target << " from LDAP directory: " << lt.what() << endl; + throw DBException( "LDAP server timeout" ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->list( target, domain_id ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to get zone " << target << " from LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + g_log << Logger::Error << d_myname << " Caught STL exception for target " << target << ": " << e.what() << endl; + throw DBException( "STL exception" ); + } + + return false; +} + + + +bool LdapBackend::list_simple( const DNSName& target, int domain_id ) +{ + string dn; + string filter; + string qesc; + + + dn = getArg( "basedn" ); + qesc = toLower( d_pldap->escape( target.toStringRootDot() ) ); + + // search for SOARecord of target + filter = strbind( ":target:", "&(associatedDomain=" + qesc + ")(sOARecord=*)", getArg( "filter-axfr" ) ); + PowerLDAP::SearchResult::Ptr search = d_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany ); + if ( !search->getNext( d_result, true ) ) + return false; + + if( d_result.count( "dn" ) && !d_result["dn"].empty() ) + { + if( !mustDo( "basedn-axfr-override" ) ) + { + dn = d_result["dn"][0]; + } + } + + // If we have any records associated with this entry let's parse them here + DNSResult soa_result; + soa_result.ttl = d_default_ttl; + soa_result.lastmod = 0; + this->extract_common_attributes( soa_result ); + this->extract_entry_results( d_qname, soa_result, QType(uint16_t(QType::ANY)) ); + + filter = strbind( ":target:", "associatedDomain=*." + qesc, getArg( "filter-axfr" ) ); + g_log << Logger::Debug << d_myname << " Search = basedn: " << dn << ", filter: " << filter << endl; + d_search = d_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany ); + + return true; +} + + +bool LdapBackend::list_strict( const DNSName& target, int domain_id ) +{ + if( target.isPartOf(DNSName("in-addr.arpa")) || target.isPartOf(DNSName("ip6.arpa")) ) + { + g_log << Logger::Warning << d_myname << " Request for reverse zone AXFR, but this is not supported in strict mode" << endl; + return false; // AXFR isn't supported in strict mode. Use simple mode and additional PTR records + } + + return list_simple( target, domain_id ); +} + + + +void LdapBackend::lookup( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +{ + try + { + d_in_list = false; + d_qname = qname; + d_qtype = qtype; + d_results_cache.clear(); + + if( d_qlog ) { g_log.log( "Query: '" + qname.toStringRootDot() + "|" + qtype.getName() + "'", Logger::Error ); } + (this->*d_lookup_fcnt)( qtype, qname, dnspkt, zoneid ); + } + catch( LDAPTimeout < ) + { + g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; + throw DBException( "LDAP server timeout" ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->lookup( qtype, qname, dnspkt, zoneid ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + g_log << Logger::Error << d_myname << " Caught STL exception for qname " << qname << ": " << e.what() << endl; + throw DBException( "STL exception" ); + } +} + + + +void LdapBackend::lookup_simple( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +{ + string filter, attr, qesc; + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; + + + qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); + filter = "associatedDomain=" + qesc; + + if( qtype.getCode() != QType::ANY ) + { + attr = qtype.getName() + "Record"; + filter = "&(" + filter + ")(" + attr + "=*)"; + attronly[0] = attr.c_str(); + attributes = attronly; + } + + filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + + g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes ); +} + + + +void LdapBackend::lookup_strict( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +{ + int len; + vector parts; + string filter, attr, qesc; + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; + + + qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); + stringtok( parts, qesc, "." ); + len = qesc.length(); + + if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups + { + filter = "aRecord=" + ptr2ip4( parts ); + attronly[0] = "associatedDomain"; + attributes = attronly; + } + else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups + { + filter = "aAAARecord=" + ptr2ip6( parts ); + attronly[0] = "associatedDomain"; + attributes = attronly; + } + else // IPv4 and IPv6 lookups + { + filter = "associatedDomain=" + qesc; + } + + if( qtype.getCode() != QType::ANY ) + { + attr = qtype.getName() + "Record"; + filter = "&(" + filter + ")(" + attr + "=*)"; + attronly[0] = attr.c_str(); + attributes = attronly; + } + + filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + + g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes ); +} + + + +void LdapBackend::lookup_tree( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +{ + string filter, attr, qesc, dn; + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; + vector parts; + + + qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); + filter = "associatedDomain=" + qesc; + + if( qtype.getCode() != QType::ANY ) + { + attr = qtype.getName() + "Record"; + filter = "&(" + filter + ")(" + attr + "=*)"; + attronly[0] = attr.c_str(); + attributes = attronly; + } + + filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + + stringtok( parts, toLower( qname.toString() ), "." ); + for(auto i = parts.crbegin(); i != parts.crend(); i++ ) + { + dn = "dc=" + *i + "," + dn; + } + + g_log << Logger::Debug << d_myname << " Search = basedn: " << dn + getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search( dn + getArg( "basedn" ), LDAP_SCOPE_BASE, filter, attributes ); +} + + +bool LdapBackend::get( DNSResourceRecord &rr ) +{ + if ( d_results_cache.empty() ) { + while ( d_results_cache.empty() ) { + bool exhausted = false; + bool valid_entry_found = false; + + while ( !valid_entry_found && !exhausted ) { + try { + exhausted = !d_search->getNext( d_result, true ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Failed to get next result: " << le.what() << endl; + throw PDNSException( "Get next result impossible" ); + } + + if ( !exhausted ) { + if ( !d_in_list ) { + // All entries are valid here + valid_entry_found = true; + } + else { + // If we're called after list() then the entry *must* contain + // associatedDomain, otherwise let's just skip it + if ( d_result.count( "associatedDomain" ) ) + valid_entry_found = true; + } + } + } + + if ( exhausted ) { + break; + } + + DNSResult result_template; + result_template.ttl = d_default_ttl; + result_template.lastmod = 0; + this->extract_common_attributes( result_template ); + + std::vector associatedDomains; + + if ( d_result.count( "associatedDomain" ) ) { + if ( d_in_list ) { + // We can have more than one associatedDomain in the entry, so for each of them we have to check + // that they are indeed under the domain we've been asked to list (nothing enforces this, so you + // can have one associatedDomain set to "host.first-domain.com" and another one set to + // "host.second-domain.com"). Better not return the latter I guess :) + // We also have to generate one DNSResult per DNS-relevant attribute. As we've asked only for them + // and the others above we've already cleaned it's just a matter of iterating over them. + + unsigned int axfrqlen = d_qname.toStringRootDot().length(); + for ( auto i = d_result["associatedDomain"].begin(); i != d_result["associatedDomain"].end(); ++i ) { + // Sanity checks: is this associatedDomain attribute under the requested domain? + if ( i->size() >= axfrqlen && i->substr( i->size() - axfrqlen, axfrqlen ) == d_qname.toStringRootDot() ) + associatedDomains.push_back( *i ); + } + } + else { + // This was a lookup in strict mode, so we add the reverse lookup + // information manually. + d_result["pTRRecord"] = d_result["associatedDomain"]; + } + } + + if ( d_in_list ) { + for ( const auto& domain : associatedDomains ) + this->extract_entry_results( DNSName( domain ), result_template, QType(uint16_t(QType::ANY)) ); + } + else { + this->extract_entry_results( d_qname, result_template, QType(uint16_t(QType::ANY)) ); + } + } + + if ( d_results_cache.empty() ) + return false; + } + + DNSResult result = d_results_cache.back(); + d_results_cache.pop_back(); + rr.qtype = result.qtype; + rr.qname = result.qname; + rr.ttl = result.ttl; + rr.last_modified = 0; + rr.content = result.value; + rr.auth = result.auth; + + g_log << Logger::Debug << d_myname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", ttl: " << rr.ttl << ", content: " << rr.content << endl; + return true; +} + + +bool LdapBackend::getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial ) +{ + string filter; + SOAData sd; + PowerLDAP::sentry_t result; + const char* attronly[] = { + "sOARecord", + "PdnsDomainId", + "PdnsDomainNotifiedSerial", + "PdnsDomainLastCheck", + "PdnsDomainMaster", + "PdnsDomainType", + NULL + }; + + try + { + // search for SOARecord of domain + filter = "(&(associatedDomain=" + toLower( d_pldap->escape( domain.toStringRootDot() ) ) + ")(SOARecord=*))"; + d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); + if (!d_search->getNext( result )) { + return false; + } + } + catch( LDAPTimeout < ) + { + g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; + throw DBException( "LDAP server timeout" ); + } + catch( LDAPNoConnection &lnc ) + { + g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; + if ( reconnect() ) + this->getDomainInfo( domain, di ); + else + throw PDNSException( "Failed to reconnect to LDAP server" ); + } + catch( LDAPException &le ) + { + g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; + throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + } + catch( std::exception &e ) + { + throw DBException( "STL exception" ); + } + + if( result.count( "sOARecord" ) && !result["sOARecord"].empty() ) + { + sd.serial = 0; + fillSOAData( result["sOARecord"][0], sd ); + + if ( result.count( "PdnsDomainId" ) && !result["PdnsDomainId"].empty() ) + di.id = std::stoi( result["PdnsDomainId"][0] ); + else + di.id = 0; + + di.serial = sd.serial; + di.zone = DNSName(domain); + + if( result.count( "PdnsDomainLastCheck" ) && !result["PdnsDomainLastCheck"].empty() ) + di.last_check = pdns_stou( result["PdnsDomainLastCheck"][0] ); + else + di.last_check = 0; + + if ( result.count( "PdnsDomainNotifiedSerial" ) && !result["PdnsDomainNotifiedSerial"].empty() ) + di.notified_serial = pdns_stou( result["PdnsDomainNotifiedSerial"][0] ); + else + di.notified_serial = 0; + + if ( result.count( "PdnsDomainMaster" ) && !result["PdnsDomainMaster"].empty() ) { + for(const auto &m : result["PdnsDomainMaster"]) + di.masters.emplace_back(m, 53); + } + + if ( result.count( "PdnsDomainType" ) && !result["PdnsDomainType"].empty() ) { + string kind = result["PdnsDomainType"][0]; + if ( kind == "master" ) + di.kind = DomainInfo::Master; + else if ( kind == "slave" ) + di.kind = DomainInfo::Slave; + else + di.kind = DomainInfo::Native; + } + else { + di.kind = DomainInfo::Native; + } + + di.backend = this; + return true; + } + + return false; +} diff --git a/modules/ldapbackend/pdns-domaininfo.schema b/modules/ldapbackend/pdns-domaininfo.schema new file mode 100644 index 0000000..c4cf100 --- /dev/null +++ b/modules/ldapbackend/pdns-domaininfo.schema @@ -0,0 +1,77 @@ +# LDAP schema for PowerDNS specific information +# +# This schema does not define a way to store DNS +# data but only metadata relevant only to the +# PowerDNS implementation of a LDAP backend. +# See dnsdomain2.schema for a schema that contains +# everything needed to store the zones and RRs. +# +# 1.3.6.1.4.1.27080 +# Sequanux - Gregory Oestreicher +# +# 1.3.6.1.4.1.27080.2 +# PowerDNS LDAP schema +# +# 1.3.6.1.4.1.27080.2.1 +# PowerDNS LDAP schema attributes +# +# 1.3.6.1.4.1.27080.2.2 +# PowerDNS LDAP schema object classes + +attributetype ( 1.3.6.1.4.1.27080.2.1.1 NAME 'PdnsDomainId' + DESC 'Domain identifier in the LDAP backend - mapped to DomainInfo::id' + EQUALITY numericStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27080.2.1.2 NAME 'PdnsDomainNotifiedSerial' + DESC 'Last serial number of this zone that slaves have seen - mapped to DomainInfo::notified_serial' + EQUALITY numericStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27080.2.1.3 NAME 'PdnsDomainLastCheck' + DESC 'Last time this zone was checked over at the master for changes - mapped to DomainInfo::last_check' + EQUALITY numericStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27080.2.1.4 NAME 'PdnsDomainMaster' + DESC 'IP address of the master(s) of this domain, if any - mapped to DomainInfo::masters - Multivalued attribute' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.27080.2.1.5 NAME 'PdnsDomainType' + DESC 'Type of zone, must be one of "master", "slave" or "native" - mapped to DomainInfo::kind' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27080.1.11 NAME 'PdnsRecordTTL' + DESC 'TTL for a RR set. Syntax is RR type, a literal "|", TTL' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype ( 1.3.6.1.4.1.27080.1.12 NAME 'PdnsRecordNoAuth' + DESC 'Whether or not this entry is authoritative for the RR given in this attribute. If this attribute is present then it is *NOT* for the RR in the attribute.' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype ( 1.3.6.1.4.1.27080.1.13 NAME 'PdnsRecordOrdername' + DESC 'The ordername for the RR. Syntax is RR type, a literal "|", the ordername' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + +attributetype ( 1.3.6.1.4.1.27080.1.15 NAME 'ALIASRecord' + DESC 'PowerDNS ALIAS RR type' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +objectclass ( 1.3.6.1.4.1.27080.2.2.1 NAME 'PdnsDomain' + DESC 'PDNS domain metadata information' + SUP top AUXILIARY + MUST ( PdnsDomainId ) + MAY ( PdnsDomainNotifiedSerial $ PdnsDomainLastCheck $ + PdnsDomainMaster $ PdnsDomainType ) ) + +objectclass ( 1.3.6.1.4.1.27080.2.2.4 NAME 'PdnsRecordData' + DESC 'Additional record data for PDNS' + SUP top AUXILIARY + MAY ( PdnsRecordTTL $ PdnsRecordNoAuth $ PdnsRecordOrdername $ ALIASRecord ) ) diff --git a/modules/ldapbackend/powerldap.cc b/modules/ldapbackend/powerldap.cc new file mode 100644 index 0000000..a2c1a53 --- /dev/null +++ b/modules/ldapbackend/powerldap.cc @@ -0,0 +1,468 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "exceptions.hh" +#include "ldapauthenticator.hh" +#include "ldaputils.hh" +#include "powerldap.hh" +#include "pdns/misc.hh" +#include + + +PowerLDAP::SearchResult::SearchResult( int msgid, LDAP* ld ) + : d_ld( ld ), d_msgid( msgid ), d_finished( false ) +{ +} + + +PowerLDAP::SearchResult::~SearchResult() +{ + if ( !d_finished ) + ldap_abandon_ext( d_ld, d_msgid, NULL, NULL ); // We don't really care about the return code as there's + // not much we can do now +} + + +bool PowerLDAP::SearchResult::getNext( PowerLDAP::sentry_t& entry, bool dn, int timeout ) +{ + int i; + char* attr; + BerElement* ber; + struct berval** berval; + vector values; + LDAPMessage* result = NULL; + LDAPMessage* object; + + while ( !d_finished && result == NULL ) { + i = ldapWaitResult( d_ld, d_msgid, 5, &result ); + switch ( i ) { + case -1: + int err_code; + ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code ); + if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR ) + throw LDAPNoConnection(); + else + throw LDAPException( "Error waiting for LDAP result: " + ldapGetError( d_ld, err_code ) ); + break; + case 0: + throw LDAPTimeout(); + break; + case LDAP_NO_SUCH_OBJECT: + return false; + case LDAP_RES_SEARCH_REFERENCE: + ldap_msgfree( result ); + result = NULL; + break; + case LDAP_RES_SEARCH_RESULT: + d_finished = true; + ldap_msgfree( result ); + break; + case LDAP_RES_SEARCH_ENTRY: + // Yay! + break; + } + } + + if ( d_finished ) + return false; + + if( ( object = ldap_first_entry( d_ld, result ) ) == NULL ) + { + ldap_msgfree( result ); + throw LDAPException( "Couldn't get first result entry: " + ldapGetError( d_ld, -1 ) ); + } + + entry.clear(); + + if( dn ) + { + attr = ldap_get_dn( d_ld, object ); + values.push_back( string( attr ) ); + ldap_memfree( attr ); + entry["dn"] = values; + } + + if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL ) + { + do + { + if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL ) + { + values.clear(); + for( i = 0; i < ldap_count_values_len( berval ); i++ ) + { + values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values? + } + + entry[attr] = values; + ldap_value_free_len( berval ); + } + ldap_memfree( attr ); + } + while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL ); + + ber_free( ber, 0 ); + } + + ldap_msgfree( result ); + return true; +} + + +void PowerLDAP::SearchResult::getAll( PowerLDAP::sresult_t& results, bool dn, int timeout ) +{ + PowerLDAP::sentry_t entry; + + while( getNext( entry, dn, timeout ) ) + { + results.push_back( entry ); + } +} + + +PowerLDAP::PowerLDAP( const string& hosts, uint16_t port, bool tls, int timeout ) +{ + d_ld = 0; + d_hosts = hosts; + d_port = port; + d_tls = tls; + d_timeout = timeout; + ensureConnect(); +} + +void PowerLDAP::ensureConnect() +{ + int err; + + if(d_ld) { + ldap_unbind_ext( d_ld, NULL, NULL ); + } + +#ifdef HAVE_LDAP_INITIALIZE + if( ( err = ldap_initialize( &d_ld, d_hosts.c_str() ) ) != LDAP_SUCCESS ) + { + string ldapuris; + vector uris; + stringtok( uris, d_hosts ); + + for( size_t i = 0; i < uris.size(); i++ ) + { + ldapuris += " ldap://" + uris[i]; + } + + if( ( err = ldap_initialize( &d_ld, ldapuris.c_str() ) ) != LDAP_SUCCESS ) + { + throw LDAPException( "Error initializing LDAP connection to '" + ldapuris + ": " + getError( err ) ); + } + } +#else + if( ( d_ld = ldap_init( d_hosts.c_str(), d_port ) ) == NULL ) + { + throw LDAPException( "Error initializing LDAP connection to '" + d_hosts + "': " + string( strerror( errno ) ) ); + } +#endif + + int protocol = LDAP_VERSION3; + if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) + { + protocol = LDAP_VERSION2; + if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) + { + ldap_unbind_ext( d_ld, NULL, NULL ); + throw LDAPException( "Couldn't set protocol version to LDAPv3 or LDAPv2" ); + } + } + + if( d_tls && ( err = ldap_start_tls_s( d_ld, NULL, NULL ) ) != LDAP_SUCCESS ) + { + ldap_unbind_ext( d_ld, NULL, NULL ); + throw LDAPException( "Couldn't perform STARTTLS: " + getError( err ) ); + } +} + + +PowerLDAP::~PowerLDAP() +{ + ldap_unbind_ext( d_ld, NULL, NULL ); +} + + +bool PowerLDAP::connect() +{ + try + { + ensureConnect(); + return true; + } + catch( LDAPException &le ) + { + return false; + } +} + + +void PowerLDAP::setOption( int option, int value ) +{ + ldapSetOption( d_ld, option, (void*) &value ); +} + + +void PowerLDAP::getOption( int option, int *value ) +{ + ldapGetOption( d_ld, option, (void*) value ); +} + + +void PowerLDAP::bind( LdapAuthenticator* authenticator ) +{ + if ( !authenticator->authenticate( d_ld ) ) + throw LDAPException( "Failed to bind to LDAP server: " + authenticator->getError() ); +} + + +void PowerLDAP::bind( const string& ldapbinddn, const string& ldapsecret, int method) +{ + int msgid; + +#ifdef HAVE_LDAP_SASL_BIND + int rc; + struct berval passwd; + + passwd.bv_val = (char *)ldapsecret.c_str(); + passwd.bv_len = strlen( passwd.bv_val ); + + if( ( rc = ldap_sasl_bind( d_ld, ldapbinddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS ) + { + throw LDAPException( "Failed to bind to LDAP server: " + getError( rc ) ); + } +#else + if( ( msgid = ldap_bind( d_ld, ldapbinddn.c_str(), ldapsecret.c_str(), method ) ) == -1 ) + { + throw LDAPException( "Failed to bind to LDAP server: " + getError( msgid ) ); + } +#endif + + ldapWaitResult( d_ld, msgid, d_timeout, NULL ); +} + + +/** + * Deprecated, use PowerLDAP::bind() instead + */ + +void PowerLDAP::simpleBind( const string& ldapbinddn, const string& ldapsecret ) +{ + this->bind( ldapbinddn, ldapsecret, LDAP_AUTH_SIMPLE ); +} + + +void PowerLDAP::add( const string &dn, LDAPMod *mods[] ) +{ + int rc; + + rc = ldap_add_ext_s( d_ld, dn.c_str(), mods, NULL, NULL ); + if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + throw LDAPNoConnection(); + else if ( rc != LDAP_SUCCESS ) + throw LDAPException( "Error adding LDAP entry " + dn + ": " + getError( rc ) ); +} + + +void PowerLDAP::modify( const string &dn, LDAPMod *mods[], LDAPControl **scontrols, LDAPControl **ccontrols ) +{ + int rc; + + rc = ldap_modify_ext_s( d_ld, dn.c_str(), mods, scontrols, ccontrols ); + if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + throw LDAPNoConnection(); + else if ( rc != LDAP_SUCCESS ) + throw LDAPException( "Error modifying LDAP entry " + dn + ": " + getError( rc ) ); +} + + +void PowerLDAP::del( const string& dn ) +{ + int rc; + + rc = ldap_delete_ext_s( d_ld, dn.c_str(), NULL, NULL ); + if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + throw LDAPNoConnection(); + else if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT ) + throw LDAPException( "Error deleting LDAP entry " + dn + ": " + getError( rc ) ); +} + + +PowerLDAP::SearchResult::Ptr PowerLDAP::search( const string& base, int scope, const string& filter, const char** attr ) +{ + int msgid, rc; + + if ( ( rc = ldap_search_ext( d_ld, base.c_str(), scope, filter.c_str(), const_cast (attr), 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ) ) ) { + throw LDAPException( "Starting LDAP search: " + getError( rc ) ); + } + + return SearchResult::Ptr( new SearchResult( msgid, d_ld ) ); +} + + +/** + * Function waits for a result, returns its type and optionally stores the result. + * If the result is returned, the caller is responsible for freeing it with + * ldap_msgfree! + */ + +int PowerLDAP::waitResult( int msgid, LDAPMessage** result ) +{ + return ldapWaitResult( d_ld, msgid, d_timeout, result ); +} + + +bool PowerLDAP::getSearchEntry( int msgid, sentry_t& entry, bool dn ) +{ + int i; + char* attr; + BerElement* ber; + struct berval** berval; + vector values; + LDAPMessage* result; + LDAPMessage* object; + bool hasResult = false; + + while ( !hasResult ) { + i = waitResult( msgid, &result ); + // Here we deliberately ignore LDAP_RES_SEARCH_REFERENCE as we don't follow them. + // Instead we get the next result. + // If the function returned an error (i <= 0) we'll deal with after this loop too. + if ( i == LDAP_RES_SEARCH_ENTRY || i == LDAP_RES_SEARCH_RESULT || i <= 0 ) + hasResult = true; + } + + if ( i == -1 ) { + // Error while retrieving the message + int err_code; + ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code ); + if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR ) + throw LDAPNoConnection(); + else + throw LDAPException( "PowerLDAP::getSearchEntry(): Error when retrieving LDAP result: " + getError( err_code ) ); + } + + if ( i == 0 ) { + // Timeout expired before the message could be retrieved + throw LDAPTimeout(); + } + + if ( i == LDAP_RES_SEARCH_RESULT ) { + // We're done with this request + ldap_msgfree( result ); + return false; + } + + if( ( object = ldap_first_entry( d_ld, result ) ) == NULL ) + { + ldap_msgfree( result ); + throw LDAPException( "Couldn't get first result entry: " + getError() ); + } + + entry.clear(); + + if( dn ) + { + attr = ldap_get_dn( d_ld, object ); + values.push_back( string( attr ) ); + ldap_memfree( attr ); + entry["dn"] = values; + } + + if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL ) + { + do + { + if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL ) + { + values.clear(); + for( i = 0; i < ldap_count_values_len( berval ); i++ ) + { + values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values? + } + + entry[attr] = values; + ldap_value_free_len( berval ); + } + ldap_memfree( attr ); + } + while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL ); + + ber_free( ber, 0 ); + } + + ldap_msgfree( result ); + return true; +} + + +void PowerLDAP::getSearchResults( int msgid, sresult_t& result, bool dn ) +{ + sentry_t entry; + + result.clear(); + while( getSearchEntry( msgid, entry, dn ) ) + { + result.push_back( entry ); + } +} + + +const string PowerLDAP::getError( int rc ) +{ + return ldapGetError( d_ld, rc ); +} + + +const string PowerLDAP::escape( const string& str ) +{ + string a; + string::const_iterator i; + char tmp[4]; + + for( i = str.begin(); i != str.end(); i++ ) + { + // RFC4515 3 + if( (unsigned char)*i == '*' || + (unsigned char)*i == '(' || + (unsigned char)*i == ')' || + (unsigned char)*i == '\\' || + (unsigned char)*i == '\0' || + (unsigned char)*i > 127) + { + snprintf(tmp, sizeof(tmp), "\\%02x", (unsigned char)*i); + + a += tmp; + } + else + a += *i; + } + + return a; +} diff --git a/modules/ldapbackend/powerldap.hh b/modules/ldapbackend/powerldap.hh new file mode 100644 index 0000000..8ff3441 --- /dev/null +++ b/modules/ldapbackend/powerldap.hh @@ -0,0 +1,105 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +#ifndef POWERLDAP_HH +#define POWERLDAP_HH + +using std::list; +using std::map; +using std::string; +using std::vector; + +class LdapAuthenticator; + +class PowerLDAP +{ + LDAP* d_ld; + string d_hosts; + int d_port; + bool d_tls; + int d_timeout; + + const string getError( int rc = -1 ); + int waitResult( int msgid = LDAP_RES_ANY, LDAPMessage** result = NULL ); + void ensureConnect(); + + public: + typedef map > sentry_t; + typedef vector sresult_t; + + class SearchResult { + LDAP* d_ld; + int d_msgid; + bool d_finished; + + SearchResult( const SearchResult& other ); + SearchResult& operator=( const SearchResult& other ); + + public: + typedef std::unique_ptr Ptr; + + SearchResult( int msgid, LDAP* ld ); + ~SearchResult(); + + bool getNext( PowerLDAP::sentry_t& entry, bool dn = false, int timeout = 5 ); + void getAll( PowerLDAP::sresult_t& results, bool dn = false, int timeout = 5 ); + }; + + PowerLDAP( const string& hosts, uint16_t port, bool tls, int timeout ); + ~PowerLDAP(); + + bool connect(); + + void getOption( int option, int* value ); + void setOption( int option, int value ); + + void bind( LdapAuthenticator *authenticator ); + void bind( const string& ldapbinddn = "", const string& ldapsecret = "", int method = LDAP_AUTH_SIMPLE ); + void simpleBind( const string& ldapbinddn = "", const string& ldapsecret = "" ); + SearchResult::Ptr search( const string& base, int scope, const string& filter, const char** attr = 0 ); + void add( const string &dn, LDAPMod *mods[] ); + void modify( const string& dn, LDAPMod *mods[], LDAPControl **scontrols = 0, LDAPControl **ccontrols = 0 ); + void del( const string& dn ); + + bool getSearchEntry( int msgid, sentry_t& entry, bool dn = false ); + void getSearchResults( int msgid, sresult_t& result, bool dn = false ); + + static const string escape( const string& tobe ); +}; + + + +#endif diff --git a/modules/ldapbackend/utils.hh b/modules/ldapbackend/utils.hh new file mode 100644 index 0000000..902c3d5 --- /dev/null +++ b/modules/ldapbackend/utils.hh @@ -0,0 +1,177 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#include +#include +#include +#include "pdns/misc.hh" +#include "pdns/utility.hh" + + +#ifndef LDAPBACKEND_UTILS_HH +#define LDAPBACKEND_UTILS_HH + +using std::string; +using std::vector; + + +inline string ptr2ip4( vector& parts ) +{ + string ip; + parts.pop_back(); + parts.pop_back(); + + + ip = parts.back(); + parts.pop_back(); + + while( !parts.empty() ) + { + ip += "." + parts.back(); + parts.pop_back(); + } + + return ip; +} + + +inline string ptr2ip6( vector& parts ) +{ + int i = 0; + string ip; + + + parts.pop_back(); + parts.pop_back(); + + while( i < 3 && parts.size() > 1 && parts.back() == "0" ) + { + parts.pop_back(); + i++; + } + + while( i++ < 4 && !parts.empty() ) + { + ip += parts.back(); + parts.pop_back(); + } + + while( !parts.empty() ) + { + i = 0; + ip += ":"; + + while( i < 3 && parts.size() > 1 && parts.back() == "0" ) + { + parts.pop_back(); + i++; + } + + while( i++ < 4 && !parts.empty() ) + { + ip += parts.back(); + parts.pop_back(); + } + } + + return ip; +} + + +inline string ip2ptr4( const string& ip ) +{ + string ptr; + vector parts; + + stringtok( parts, ip, "." ); + while( !parts.empty() ) + { + ptr += parts.back() + "."; + parts.pop_back(); + } + + return ptr + "in-addr.arpa"; +} + + +inline string ip2ptr6( const string& ip ) +{ + string ptr, part, defstr; + vector parts; + + stringtok( parts, ip, ":" ); + while( !parts.empty() ) + { + defstr = "0.0.0.0."; + part = parts.back(); + + while( part.length() < 4 ) + { + part = "0" + part; + } + + defstr[0] = part[3]; + defstr[2] = part[2]; + defstr[4] = part[1]; + defstr[6] = part[0]; + ptr += defstr; + parts.pop_back(); + } + + return ptr + "ip6.arpa"; +} + + +inline string strbind( const string& search, const string& replace, string subject ) +{ + size_t pos = 0; + + + while( ( pos = subject.find( search, pos ) ) != string::npos ) + { + subject.replace( pos, search.size(), replace ); + pos += replace.size(); + } + + return subject; +} + +/* + * Convert a LDAP time string to a time_t. Return 0 if unable to convert + */ + +inline time_t str2tstamp( const string& str ) +{ + char* tmp; + struct tm tm; + + tmp = strptime( str.c_str(), "%Y%m%d%H%M%SZ", &tm ); + + if( tmp != NULL && *tmp == 0 ) + { + return Utility::timegm( &tm ); + } + + return 0; +} + +#endif diff --git a/modules/lmdbbackend/Makefile.am b/modules/lmdbbackend/Makefile.am new file mode 100644 index 0000000..6ac36e9 --- /dev/null +++ b/modules/lmdbbackend/Makefile.am @@ -0,0 +1,9 @@ +AM_CPPFLAGS += $(LMDB_CFLAGS) + +pkglib_LTLIBRARIES = liblmdbbackend.la + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +liblmdbbackend_la_SOURCES = lmdbbackend.cc lmdbbackend.hh lmdb-safe.hh lmdb-safe.cc lmdb-typed.hh lmdb-typed.cc +liblmdbbackend_la_LDFLAGS = -module -avoid-version +liblmdbbackend_la_LIBADD = $(LMDB_LIBS) $(BOOST_SERIALIZATION_LIBS) \ No newline at end of file diff --git a/modules/lmdbbackend/Makefile.in b/modules/lmdbbackend/Makefile.in new file mode 100644 index 0000000..92050c8 --- /dev/null +++ b/modules/lmdbbackend/Makefile.in @@ -0,0 +1,830 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/lmdbbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +liblmdbbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_liblmdbbackend_la_OBJECTS = lmdbbackend.lo lmdb-safe.lo \ + lmdb-typed.lo +liblmdbbackend_la_OBJECTS = $(am_liblmdbbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +liblmdbbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(liblmdbbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(liblmdbbackend_la_SOURCES) +DIST_SOURCES = $(liblmdbbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(LMDB_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = liblmdbbackend.la +EXTRA_DIST = OBJECTFILES OBJECTLIBS +liblmdbbackend_la_SOURCES = lmdbbackend.cc lmdbbackend.hh lmdb-safe.hh lmdb-safe.cc lmdb-typed.hh lmdb-typed.cc +liblmdbbackend_la_LDFLAGS = -module -avoid-version +liblmdbbackend_la_LIBADD = $(LMDB_LIBS) $(BOOST_SERIALIZATION_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/lmdbbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/lmdbbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +liblmdbbackend.la: $(liblmdbbackend_la_OBJECTS) $(liblmdbbackend_la_DEPENDENCIES) $(EXTRA_liblmdbbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liblmdbbackend_la_LINK) -rpath $(pkglibdir) $(liblmdbbackend_la_OBJECTS) $(liblmdbbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmdb-safe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmdb-typed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmdbbackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/lmdbbackend/OBJECTFILES b/modules/lmdbbackend/OBJECTFILES new file mode 100644 index 0000000..02c8d57 --- /dev/null +++ b/modules/lmdbbackend/OBJECTFILES @@ -0,0 +1 @@ +lmdbbackend.lo lmdb-safe.lo lmdb-typed.lo diff --git a/modules/lmdbbackend/OBJECTLIBS b/modules/lmdbbackend/OBJECTLIBS new file mode 100644 index 0000000..72a315e --- /dev/null +++ b/modules/lmdbbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(LMDB_LIBS) $(BOOST_SERIALIZATION_LIBS) diff --git a/modules/lmdbbackend/lmdb-safe.cc b/modules/lmdbbackend/lmdb-safe.cc new file mode 100644 index 0000000..f487426 --- /dev/null +++ b/modules/lmdbbackend/lmdb-safe.cc @@ -0,0 +1,373 @@ +#include "lmdb-safe.hh" +#include +#include +#include +#include +#include +#include + +using namespace std; + +static string MDBError(int rc) +{ + return mdb_strerror(rc); +} + +MDBDbi::MDBDbi(MDB_env* env, MDB_txn* txn, const string_view dbname, int flags) +{ + // A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function. + + int rc = mdb_dbi_open(txn, dbname.empty() ? 0 : &dbname[0], flags, &d_dbi); + if(rc) + throw std::runtime_error("Unable to open named database: " + MDBError(rc)); + + // Database names are keys in the unnamed database, and may be read but not written. +} + +MDBEnv::MDBEnv(const char* fname, int flags, int mode) +{ + mdb_env_create(&d_env); + uint64_t mapsizeMB = (sizeof(long)==4) ? 100 : 16000; + // on 32 bit platforms, there is just no room for more + if(mdb_env_set_mapsize(d_env, mapsizeMB * 1048576)) + throw std::runtime_error("setting map size"); + /* +Various other options may also need to be set before opening the handle, e.g. mdb_env_set_mapsize(), mdb_env_set_maxreaders(), mdb_env_set_maxdbs(), + */ + + mdb_env_set_maxdbs(d_env, 128); + + // we need MDB_NOTLS since we rely on its semantics + if(int rc=mdb_env_open(d_env, fname, flags | MDB_NOTLS, mode)) { + // If this function fails, mdb_env_close() must be called to discard the MDB_env handle. + mdb_env_close(d_env); + throw std::runtime_error("Unable to open database file "+std::string(fname)+": " + MDBError(rc)); + } +} + +void MDBEnv::incROTX() +{ + std::lock_guard l(d_countmutex); + ++d_ROtransactionsOut[std::this_thread::get_id()]; +} + +void MDBEnv::decROTX() +{ + std::lock_guard l(d_countmutex); + --d_ROtransactionsOut[std::this_thread::get_id()]; +} + +void MDBEnv::incRWTX() +{ + std::lock_guard l(d_countmutex); + ++d_RWtransactionsOut[std::this_thread::get_id()]; +} + +void MDBEnv::decRWTX() +{ + std::lock_guard l(d_countmutex); + --d_RWtransactionsOut[std::this_thread::get_id()]; +} + +int MDBEnv::getRWTX() +{ + std::lock_guard l(d_countmutex); + return d_RWtransactionsOut[std::this_thread::get_id()]; +} +int MDBEnv::getROTX() +{ + std::lock_guard l(d_countmutex); + return d_ROtransactionsOut[std::this_thread::get_id()]; +} + + +std::shared_ptr getMDBEnv(const char* fname, int flags, int mode) +{ + struct Value + { + weak_ptr wp; + int flags; + }; + + static std::map, Value> s_envs; + static std::mutex mut; + + struct stat statbuf; + if(stat(fname, &statbuf)) { + if(errno != ENOENT) + throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno))); + else { + std::lock_guard l(mut); + auto fresh = std::make_shared(fname, flags, mode); + if(stat(fname, &statbuf)) + throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno))); + auto key = std::tie(statbuf.st_dev, statbuf.st_ino); + s_envs[key] = {fresh, flags}; + return fresh; + } + } + + std::lock_guard l(mut); + auto key = std::tie(statbuf.st_dev, statbuf.st_ino); + auto iter = s_envs.find(key); + if(iter != s_envs.end()) { + auto sp = iter->second.wp.lock(); + if(sp) { + if(iter->second.flags != flags) + throw std::runtime_error("Can't open mdb with differing flags"); + + return sp; + } + else { + s_envs.erase(iter); // useful if make_shared fails + } + } + + auto fresh = std::make_shared(fname, flags, mode); + s_envs[key] = {fresh, flags}; + + return fresh; +} + + +MDBDbi MDBEnv::openDB(const string_view dbname, int flags) +{ + unsigned int envflags; + mdb_env_get_flags(d_env, &envflags); + /* + This function must not be called from multiple concurrent transactions in the same process. A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function. + */ + std::lock_guard l(d_openmut); + + if(!(envflags & MDB_RDONLY)) { + auto rwt = getRWTransaction(); + MDBDbi ret = rwt->openDB(dbname, flags); + rwt->commit(); + return ret; + } + + MDBDbi ret; + { + auto rwt = getROTransaction(); + ret = rwt->openDB(dbname, flags); + } + return ret; +} + +MDBRWTransactionImpl::MDBRWTransactionImpl(MDBEnv *parent, MDB_txn *txn): + MDBROTransactionImpl(parent, txn) + +{ + +} + +MDB_txn *MDBRWTransactionImpl::openRWTransaction(MDBEnv *env, MDB_txn *parent, int flags) +{ + MDB_txn *result; + if(env->getROTX() || env->getRWTX()) + throw std::runtime_error("Duplicate RW transaction"); + + for(int tries =0 ; tries < 3; ++tries) { // it might happen twice, who knows + if(int rc=mdb_txn_begin(env->d_env, parent, flags, &result)) { + if(rc == MDB_MAP_RESIZED && tries < 2) { + // "If the mapsize is increased by another process (..) mdb_txn_begin() will return MDB_MAP_RESIZED. + // call mdb_env_set_mapsize with a size of zero to adopt the new size." + mdb_env_set_mapsize(env->d_env, 0); + continue; + } + throw std::runtime_error("Unable to start RW transaction: "+std::string(mdb_strerror(rc))); + } + break; + } + env->incRWTX(); + return result; +} + +MDBRWTransactionImpl::MDBRWTransactionImpl(MDBEnv* parent, int flags): + MDBRWTransactionImpl(parent, openRWTransaction(parent, nullptr, flags)) +{ +} + +MDBRWTransactionImpl::~MDBRWTransactionImpl() +{ + abort(); +} + +void MDBRWTransactionImpl::commit() +{ + closeRORWCursors(); + if (!d_txn) { + return; + } + + if(int rc = mdb_txn_commit(d_txn)) { + throw std::runtime_error("committing: " + std::string(mdb_strerror(rc))); + } + environment().decRWTX(); + d_txn = nullptr; +} + +void MDBRWTransactionImpl::abort() +{ + closeRORWCursors(); + if (!d_txn) { + return; + } + + mdb_txn_abort(d_txn); + // prevent the RO destructor from cleaning up the transaction itself + environment().decRWTX(); + d_txn = nullptr; +} + +MDBROTransactionImpl::MDBROTransactionImpl(MDBEnv *parent, MDB_txn *txn): + d_parent(parent), + d_cursors(), + d_txn(txn) +{ + +} + +MDB_txn *MDBROTransactionImpl::openROTransaction(MDBEnv *env, MDB_txn *parent, int flags) +{ + if(env->getRWTX()) + throw std::runtime_error("Duplicate RO transaction"); + + /* + A transaction and its cursors must only be used by a single thread, and a thread may only have a single transaction at a time. If MDB_NOTLS is in use, this does not apply to read-only transactions. */ + MDB_txn *result = nullptr; + for(int tries =0 ; tries < 3; ++tries) { // it might happen twice, who knows + if(int rc=mdb_txn_begin(env->d_env, parent, MDB_RDONLY | flags, &result)) { + if(rc == MDB_MAP_RESIZED && tries < 2) { + // "If the mapsize is increased by another process (..) mdb_txn_begin() will return MDB_MAP_RESIZED. + // call mdb_env_set_mapsize with a size of zero to adopt the new size." + mdb_env_set_mapsize(env->d_env, 0); + continue; + } + + throw std::runtime_error("Unable to start RO transaction: "+string(mdb_strerror(rc))); + } + break; + } + env->incROTX(); + + return result; +} + +void MDBROTransactionImpl::closeROCursors() +{ + // we need to move the vector away to ensure that the cursors don’t mess with our iteration. + std::vector buf; + std::swap(d_cursors, buf); + for (auto &cursor: buf) { + cursor->close(); + } +} + +MDBROTransactionImpl::MDBROTransactionImpl(MDBEnv *parent, int flags): + MDBROTransactionImpl(parent, openROTransaction(parent, nullptr, flags)) +{ + +} + +MDBROTransactionImpl::~MDBROTransactionImpl() +{ + // this is safe because C++ will not call overrides of virtual methods in destructors. + commit(); +} + +void MDBROTransactionImpl::abort() +{ + closeROCursors(); + // if d_txn is non-nullptr here, either the transaction object was invalidated earlier (e.g. by moving from it), or it is an RW transaction which has already cleaned up the d_txn pointer (with an abort). + if (d_txn) { + d_parent->decROTX(); + mdb_txn_abort(d_txn); // this appears to work better than abort for r/o database opening + d_txn = nullptr; + } +} + +void MDBROTransactionImpl::commit() +{ + closeROCursors(); + // if d_txn is non-nullptr here, either the transaction object was invalidated earlier (e.g. by moving from it), or it is an RW transaction which has already cleaned up the d_txn pointer (with an abort). + if (d_txn) { + d_parent->decROTX(); + mdb_txn_commit(d_txn); // this appears to work better than abort for r/o database opening + d_txn = nullptr; + } +} + + + +void MDBRWTransactionImpl::clear(MDB_dbi dbi) +{ + if(int rc = mdb_drop(d_txn, dbi, 0)) { + throw runtime_error("Error clearing database: " + MDBError(rc)); + } +} + +MDBRWCursor MDBRWTransactionImpl::getRWCursor(const MDBDbi& dbi) +{ + MDB_cursor *cursor; + int rc= mdb_cursor_open(d_txn, dbi, &cursor); + if(rc) { + throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc))); + } + return MDBRWCursor(d_rw_cursors, cursor); +} + +MDBRWCursor MDBRWTransactionImpl::getCursor(const MDBDbi &dbi) +{ + return getRWCursor(dbi); +} + +MDBRWTransaction MDBRWTransactionImpl::getRWTransaction() +{ + MDB_txn *txn; + if (int rc = mdb_txn_begin(environment(), *this, 0, &txn)) { + throw std::runtime_error(std::string("failed to start child transaction: ")+mdb_strerror(rc)); + } + // we need to increase the counter here because commit/abort on the child transaction will decrease it + environment().incRWTX(); + return MDBRWTransaction(new MDBRWTransactionImpl(&environment(), txn)); +} + +MDBROTransaction MDBRWTransactionImpl::getROTransaction() +{ + return std::move(getRWTransaction()); +} + +MDBROTransaction MDBEnv::getROTransaction() +{ + return MDBROTransaction(new MDBROTransactionImpl(this)); +} +MDBRWTransaction MDBEnv::getRWTransaction() +{ + return MDBRWTransaction(new MDBRWTransactionImpl(this)); +} + + +void MDBRWTransactionImpl::closeRWCursors() +{ + decltype(d_rw_cursors) buf; + std::swap(d_rw_cursors, buf); + for (auto &cursor: buf) { + cursor->close(); + } +} + +MDBROCursor MDBROTransactionImpl::getCursor(const MDBDbi& dbi) +{ + return getROCursor(dbi); +} + +MDBROCursor MDBROTransactionImpl::getROCursor(const MDBDbi &dbi) +{ + MDB_cursor *cursor; + int rc= mdb_cursor_open(d_txn, dbi, &cursor); + if(rc) { + throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc))); + } + return MDBROCursor(d_cursors, cursor); +} diff --git a/modules/lmdbbackend/lmdb-safe.hh b/modules/lmdbbackend/lmdb-safe.hh new file mode 100644 index 0000000..e5fe14a --- /dev/null +++ b/modules/lmdbbackend/lmdb-safe.hh @@ -0,0 +1,623 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// apple compiler somehow has string_view even in c++11! +#if __cplusplus < 201703L && !defined(__APPLE__) +#include +#if BOOST_VERSION >= 106100 +#include +using boost::string_view; +#else +#include +using string_view = boost::string_ref; +#endif +#else // C++17 +using std::string_view; +#endif + + +/* open issues: + * + * - missing convenience functions (string_view, string) + */ + +/* +The error strategy. Anything that "should never happen" turns into an exception. But things like 'duplicate entry' or 'no such key' are for you to deal with. + */ + +/* + Thread safety: we are as safe as lmdb. You can talk to MDBEnv from as many threads as you want +*/ + +/** MDBDbi is our only 'value type' object, as 1) a dbi is actually an integer + and 2) per LMDB documentation, we never close it. */ +class MDBDbi +{ +public: + MDBDbi(): d_dbi(-1) + { + } + explicit MDBDbi(MDB_env* env, MDB_txn* txn, string_view dbname, int flags); + + operator const MDB_dbi&() const + { + return d_dbi; + } + + MDB_dbi d_dbi; +}; + +class MDBRWTransactionImpl; +class MDBROTransactionImpl; + +using MDBROTransaction = std::unique_ptr; +using MDBRWTransaction = std::unique_ptr; + +class MDBEnv +{ +public: + MDBEnv(const char* fname, int flags, int mode); + + ~MDBEnv() + { + // Only a single thread may call this function. All transactions, databases, and cursors must already be closed before calling this function + mdb_env_close(d_env); + // but, elsewhere, docs say database handles do not need to be closed? + } + + MDBDbi openDB(const string_view dbname, int flags); + + MDBRWTransaction getRWTransaction(); + MDBROTransaction getROTransaction(); + + operator MDB_env*& () + { + return d_env; + } + MDB_env* d_env; + + int getRWTX(); + void incRWTX(); + void decRWTX(); + int getROTX(); + void incROTX(); + void decROTX(); +private: + std::mutex d_openmut; + std::mutex d_countmutex; + std::map d_RWtransactionsOut; + std::map d_ROtransactionsOut; +}; + +std::shared_ptr getMDBEnv(const char* fname, int flags, int mode); + + + +struct MDBOutVal +{ + operator MDB_val&() + { + return d_mdbval; + } + + template ::value, + T>::type* = nullptr> const + T get() + { + T ret; + if(d_mdbval.mv_size != sizeof(T)) + throw std::runtime_error("MDB data has wrong length for type"); + + memcpy(&ret, d_mdbval.mv_data, sizeof(T)); + return ret; + } + + template ::value,T>::type* = nullptr> + T get() const; + + template + T get_struct() const + { + T ret; + if(d_mdbval.mv_size != sizeof(T)) + throw std::runtime_error("MDB data has wrong length for type"); + + memcpy(&ret, d_mdbval.mv_data, sizeof(T)); + return ret; + } + + template + const T* get_struct_ptr() const + { + if(d_mdbval.mv_size != sizeof(T)) + throw std::runtime_error("MDB data has wrong length for type"); + + return reinterpret_cast(d_mdbval.mv_data); + } + + + MDB_val d_mdbval; +}; + +template<> inline std::string MDBOutVal::get() const +{ + return std::string((char*)d_mdbval.mv_data, d_mdbval.mv_size); +} + +template<> inline string_view MDBOutVal::get() const +{ + return string_view((char*)d_mdbval.mv_data, d_mdbval.mv_size); +} + +class MDBInVal +{ +public: + MDBInVal(const MDBOutVal& rhs): d_mdbval(rhs.d_mdbval) + { + } + + template ::value, + T>::type* = nullptr> + MDBInVal(T i) + { + memcpy(&d_memory[0], &i, sizeof(i)); + d_mdbval.mv_size = sizeof(T); + d_mdbval.mv_data = d_memory;; + } + + MDBInVal(const char* s) + { + d_mdbval.mv_size = strlen(s); + d_mdbval.mv_data = (void*)s; + } + + MDBInVal(const string_view& v) + { + d_mdbval.mv_size = v.size(); + d_mdbval.mv_data = (void*)&v[0]; + } + + MDBInVal(const std::string& v) + { + d_mdbval.mv_size = v.size(); + d_mdbval.mv_data = (void*)&v[0]; + } + + + template + static MDBInVal fromStruct(const T& t) + { + MDBInVal ret; + ret.d_mdbval.mv_size = sizeof(T); + ret.d_mdbval.mv_data = (void*)&t; + return ret; + } + + operator MDB_val&() + { + return d_mdbval; + } + MDB_val d_mdbval; +private: + MDBInVal(){} + char d_memory[sizeof(double)]; + +}; + + + + +class MDBROCursor; + +class MDBROTransactionImpl +{ +protected: + MDBROTransactionImpl(MDBEnv *parent, MDB_txn *txn); + +private: + static MDB_txn *openROTransaction(MDBEnv *env, MDB_txn *parent, int flags=0); + + MDBEnv* d_parent; + std::vector d_cursors; + +protected: + MDB_txn* d_txn; + + void closeROCursors(); + +public: + explicit MDBROTransactionImpl(MDBEnv* parent, int flags=0); + + MDBROTransactionImpl(const MDBROTransactionImpl& src) = delete; + MDBROTransactionImpl &operator=(const MDBROTransactionImpl& src) = delete; + + // The move constructor/operator cannot be made safe due to Object Slicing with MDBRWTransaction. + MDBROTransactionImpl(MDBROTransactionImpl&& rhs) = delete; + MDBROTransactionImpl &operator=(MDBROTransactionImpl &&rhs) = delete; + + virtual ~MDBROTransactionImpl(); + + virtual void abort(); + virtual void commit(); + + int get(MDB_dbi dbi, const MDBInVal& key, MDBOutVal& val) + { + if(!d_txn) + throw std::runtime_error("Attempt to use a closed RO transaction for get"); + + int rc = mdb_get(d_txn, dbi, const_cast(&key.d_mdbval), + const_cast(&val.d_mdbval)); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc))); + + return rc; + } + + int get(MDB_dbi dbi, const MDBInVal& key, string_view& val) + { + MDBOutVal out; + int rc = get(dbi, key, out); + if(!rc) + val = out.get(); + return rc; + } + + + // this is something you can do, readonly + MDBDbi openDB(string_view dbname, int flags) + { + return MDBDbi( d_parent->d_env, d_txn, dbname, flags); + } + + MDBROCursor getCursor(const MDBDbi&); + MDBROCursor getROCursor(const MDBDbi&); + + operator MDB_txn*() + { + return d_txn; + } + + inline operator bool() const { + return d_txn; + } + + inline MDBEnv &environment() + { + return *d_parent; + } +}; + +/* + A cursor in a read-only transaction must be closed explicitly, before or after its transaction ends. It can be reused with mdb_cursor_renew() before finally closing it. + + "If the parent transaction commits, the cursor must not be used again." +*/ + +template +class MDBGenCursor +{ +private: + std::vector *d_registry; + MDB_cursor* d_cursor{nullptr}; + +public: + MDBGenCursor(): + d_registry(nullptr), + d_cursor(nullptr) + { + + } + + MDBGenCursor(std::vector ®istry, MDB_cursor *cursor): + d_registry(®istry), + d_cursor(cursor) + { + registry.emplace_back(static_cast(this)); + } + +private: + void move_from(MDBGenCursor *src) + { + if (!d_registry) { + return; + } + + auto iter = std::find(d_registry->begin(), + d_registry->end(), + src); + if (iter != d_registry->end()) { + *iter = static_cast(this); + } else { + d_registry->emplace_back(static_cast(this)); + } + } + +public: + MDBGenCursor(const MDBGenCursor &src) = delete; + + MDBGenCursor(MDBGenCursor &&src) noexcept: + d_registry(src.d_registry), + d_cursor(src.d_cursor) + { + move_from(&src); + src.d_registry = nullptr; + src.d_cursor = nullptr; + } + + MDBGenCursor &operator=(const MDBGenCursor &src) = delete; + + MDBGenCursor &operator=(MDBGenCursor &&src) noexcept + { + d_registry = src.d_registry; + d_cursor = src.d_cursor; + move_from(&src); + src.d_registry = nullptr; + src.d_cursor = nullptr; + return *this; + } + + ~MDBGenCursor() + { + close(); + } + +public: + int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) + { + int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc))); + return rc; + } + + int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) + { + key.d_mdbval = in.d_mdbval; + int rc=mdb_cursor_get(d_cursor, const_cast(&key.d_mdbval), &data.d_mdbval, MDB_SET); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("Unable to find from cursor: " + std::string(mdb_strerror(rc))); + return rc; + } + + int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) + { + key.d_mdbval = in.d_mdbval; + + int rc = mdb_cursor_get(d_cursor, const_cast(&key.d_mdbval), &data.d_mdbval, MDB_SET_RANGE); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("Unable to lower_bound from cursor: " + std::string(mdb_strerror(rc))); + return rc; + } + + + int nextprev(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) + { + int rc = mdb_cursor_get(d_cursor, const_cast(&key.d_mdbval), &data.d_mdbval, op); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("Unable to prevnext from cursor: " + std::string(mdb_strerror(rc))); + return rc; + } + + int next(MDBOutVal& key, MDBOutVal& data) + { + return nextprev(key, data, MDB_NEXT); + } + + int prev(MDBOutVal& key, MDBOutVal& data) + { + return nextprev(key, data, MDB_PREV); + } + + int currentlast(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) + { + int rc = mdb_cursor_get(d_cursor, const_cast(&key.d_mdbval), &data.d_mdbval, op); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("Unable to next from cursor: " + std::string(mdb_strerror(rc))); + return rc; + } + + int current(MDBOutVal& key, MDBOutVal& data) + { + return currentlast(key, data, MDB_GET_CURRENT); + } + int last(MDBOutVal& key, MDBOutVal& data) + { + return currentlast(key, data, MDB_LAST); + } + int first(MDBOutVal& key, MDBOutVal& data) + { + return currentlast(key, data, MDB_FIRST); + } + + operator MDB_cursor*() + { + return d_cursor; + } + + operator bool() const + { + return d_cursor; + } + + void close() + { + if (d_registry) { + auto iter = std::find(d_registry->begin(), + d_registry->end(), + static_cast(this)); + if (iter != d_registry->end()) { + d_registry->erase(iter); + } + d_registry = nullptr; + } + if (d_cursor) { + mdb_cursor_close(d_cursor); + d_cursor = nullptr; + } + } +}; + +class MDBROCursor : public MDBGenCursor +{ +public: + MDBROCursor() = default; + using MDBGenCursor::MDBGenCursor; + MDBROCursor(const MDBROCursor &src) = delete; + MDBROCursor(MDBROCursor &&src) = default; + MDBROCursor &operator=(const MDBROCursor &src) = delete; + MDBROCursor &operator=(MDBROCursor &&src) = default; + ~MDBROCursor() = default; + +}; + +class MDBRWCursor; + +class MDBRWTransactionImpl: public MDBROTransactionImpl +{ +protected: + MDBRWTransactionImpl(MDBEnv* parent, MDB_txn* txn); + +private: + static MDB_txn *openRWTransaction(MDBEnv* env, MDB_txn *parent, int flags); + +private: + std::vector d_rw_cursors; + + void closeRWCursors(); + inline void closeRORWCursors() { + closeROCursors(); + closeRWCursors(); + } + +public: + explicit MDBRWTransactionImpl(MDBEnv* parent, int flags=0); + + MDBRWTransactionImpl(const MDBRWTransactionImpl& rhs) = delete; + MDBRWTransactionImpl(MDBRWTransactionImpl&& rhs) = delete; + MDBRWTransactionImpl &operator=(const MDBRWTransactionImpl& rhs) = delete; + MDBRWTransactionImpl &operator=(MDBRWTransactionImpl&& rhs) = delete; + + ~MDBRWTransactionImpl() override; + + void commit() override; + void abort() override; + + void clear(MDB_dbi dbi); + + void put(MDB_dbi dbi, const MDBInVal& key, const MDBInVal& val, int flags=0) + { + if(!d_txn) + throw std::runtime_error("Attempt to use a closed RW transaction for put"); + int rc; + if((rc=mdb_put(d_txn, dbi, + const_cast(&key.d_mdbval), + const_cast(&val.d_mdbval), flags))) + throw std::runtime_error("putting data: " + std::string(mdb_strerror(rc))); + } + + + int del(MDBDbi& dbi, const MDBInVal& key, const MDBInVal& val) + { + int rc; + rc=mdb_del(d_txn, dbi, (MDB_val*)&key.d_mdbval, (MDB_val*)&val.d_mdbval); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc))); + return rc; + } + + int del(MDBDbi& dbi, const MDBInVal& key) + { + int rc; + rc=mdb_del(d_txn, dbi, (MDB_val*)&key.d_mdbval, 0); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc))); + return rc; + } + + + int get(MDBDbi& dbi, const MDBInVal& key, MDBOutVal& val) + { + if(!d_txn) + throw std::runtime_error("Attempt to use a closed RW transaction for get"); + + int rc = mdb_get(d_txn, dbi, const_cast(&key.d_mdbval), + const_cast(&val.d_mdbval)); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc))); + return rc; + } + + int get(MDBDbi& dbi, const MDBInVal& key, string_view& val) + { + MDBOutVal out; + int rc = get(dbi, key, out); + if(!rc) + val = out.get(); + return rc; + } + + MDBDbi openDB(string_view dbname, int flags) + { + return MDBDbi(environment().d_env, d_txn, dbname, flags); + } + + MDBRWCursor getRWCursor(const MDBDbi&); + MDBRWCursor getCursor(const MDBDbi&); + + MDBRWTransaction getRWTransaction(); + MDBROTransaction getROTransaction(); +}; + +/* "A cursor in a write-transaction can be closed before its transaction ends, and will otherwise be closed when its transaction ends" + This is a problem for us since it may means we are closing the cursor twice, which is bad +*/ +class MDBRWCursor : public MDBGenCursor +{ +public: + MDBRWCursor() = default; + using MDBGenCursor::MDBGenCursor; + MDBRWCursor(const MDBRWCursor &src) = delete; + MDBRWCursor(MDBRWCursor &&src) = default; + MDBRWCursor &operator=(const MDBRWCursor &src) = delete; + MDBRWCursor &operator=(MDBRWCursor &&src) = default; + ~MDBRWCursor() = default; + + void put(const MDBOutVal& key, const MDBInVal& data) + { + int rc = mdb_cursor_put(*this, + const_cast(&key.d_mdbval), + const_cast(&data.d_mdbval), MDB_CURRENT); + if(rc) + throw std::runtime_error("mdb_cursor_put: " + std::string(mdb_strerror(rc))); + } + + + int put(const MDBOutVal& key, const MDBOutVal& data, int flags=0) + { + // XXX check errors + return mdb_cursor_put(*this, + const_cast(&key.d_mdbval), + const_cast(&data.d_mdbval), flags); + } + + int del(int flags=0) + { + return mdb_cursor_del(*this, flags); + } + +}; + diff --git a/modules/lmdbbackend/lmdb-typed.cc b/modules/lmdbbackend/lmdb-typed.cc new file mode 100644 index 0000000..b4ecd38 --- /dev/null +++ b/modules/lmdbbackend/lmdb-typed.cc @@ -0,0 +1,14 @@ +#include "lmdb-typed.hh" + +unsigned int MDBGetMaxID(MDBRWTransaction& txn, MDBDbi& dbi) +{ + auto cursor = txn->getRWCursor(dbi); + MDBOutVal maxidval, maxcontent; + unsigned int maxid{0}; + if(!cursor.get(maxidval, maxcontent, MDB_LAST)) { + maxid = maxidval.get(); + } + return maxid; +} + + diff --git a/modules/lmdbbackend/lmdb-typed.hh b/modules/lmdbbackend/lmdb-typed.hh new file mode 100644 index 0000000..4887aa7 --- /dev/null +++ b/modules/lmdbbackend/lmdb-typed.hh @@ -0,0 +1,723 @@ +#pragma once +#include +#include "lmdb-safe.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +// using std::cout; +// using std::endl; + + +/* + Open issues: + + Everything should go into a namespace + What is an error? What is an exception? + could id=0 be magic? ('no such id') + yes + Is boost the best serializer? + good default + Perhaps use the separate index concept from multi_index + perhaps get eiter to be of same type so for(auto& a : x) works + make it more value "like" with unique_ptr +*/ + + +/** Return the highest ID used in a database. Returns 0 for an empty DB. + This makes us start everything at ID=1, which might make it possible to + treat id 0 as special +*/ +unsigned int MDBGetMaxID(MDBRWTransaction& txn, MDBDbi& dbi); + +/** This is our serialization interface. + You can define your own serToString for your type if you know better +*/ +template +std::string serToString(const T& t) +{ + std::string serial_str; + boost::iostreams::back_insert_device inserter(serial_str); + boost::iostreams::stream > s(inserter); + boost::archive::binary_oarchive oa(s, boost::archive::no_header | boost::archive::no_codecvt); + + oa << t; + return serial_str; +} + +template +void serFromString(const string_view& str, T& ret) +{ + ret = T(); + + boost::iostreams::array_source source(&str[0], str.size()); + boost::iostreams::stream stream(source); + boost::archive::binary_iarchive in_archive(stream, boost::archive::no_header|boost::archive::no_codecvt); + in_archive >> ret; + + /* + std::istringstream istr{str}; + boost::archive::binary_iarchive oi(istr,boost::archive::no_header|boost::archive::no_codecvt ); + oi >> ret; + */ +} + + +template +inline std::string keyConv(const T& t); + +template ::value,T>::type* = nullptr> +inline std::string keyConv(const T& t) +{ + return std::string((char*)&t, sizeof(t)); +} + +// this is how to override specific types.. it is ugly +template::value,T>::type* = nullptr> +inline std::string keyConv(const T& t) +{ + return t; +} + + +/** This is a struct that implements index operations, but + only the operations that are broadcast to all indexes. + Specifically, to deal with databases with less than the maximum + number of interfaces, this only includes calls that should be + ignored for empty indexes. + + this only needs methods that must happen for all indexes at once + so specifically, not size or get, people ask for those themselves, and + should no do that on indexes that don't exist */ + +template +struct LMDBIndexOps +{ + explicit LMDBIndexOps(Parent* parent) : d_parent(parent){} + void put(MDBRWTransaction& txn, const Class& t, uint32_t id, int flags=0) + { + txn->put(d_idx, keyConv(d_parent->getMember(t)), id, flags); + } + + void del(MDBRWTransaction& txn, const Class& t, uint32_t id) + { + if(int rc = txn->del(d_idx, keyConv(d_parent->getMember(t)), id)) { + throw std::runtime_error("Error deleting from index: " + std::string(mdb_strerror(rc))); + } + } + + void openDB(std::shared_ptr& env, string_view str, int flags) + { + d_idx = env->openDB(str, flags); + } + MDBDbi d_idx; + Parent* d_parent; +}; + +/** This is an index on a field in a struct, it derives from the LMDBIndexOps */ + +template +struct index_on : LMDBIndexOps> +{ + index_on() : LMDBIndexOps>(this) + {} + static Type getMember(const Class& c) + { + return c.*PtrToMember; + } + + typedef Type type; +}; + +/** This is a calculated index */ +template +struct index_on_function : LMDBIndexOps > +{ + index_on_function() : LMDBIndexOps >(this) + {} + static Type getMember(const Class& c) + { + Func f; + return f(c); + } + + typedef Type type; +}; + +/** nop index, so we can fill our N indexes, even if you don't use them all */ +struct nullindex_t +{ + template + void put(MDBRWTransaction& txn, const Class& t, uint32_t id, int flags=0) + {} + template + void del(MDBRWTransaction& txn, const Class& t, uint32_t id) + {} + + void openDB(std::shared_ptr& env, string_view str, int flags) + { + + } + typedef uint32_t type; // dummy +}; + + +/** The main class. Templatized only on the indexes and typename right now */ +template +class TypedDBI +{ +public: + TypedDBI(std::shared_ptr env, string_view name) + : d_env(env), d_name(name) + { + d_main = d_env->openDB(name, MDB_CREATE | MDB_INTEGERKEY); + + // now you might be tempted to go all MPL on this so we can get rid of the + // ugly macro. I'm not very receptive to that idea since it will make things + // EVEN uglier. +#define openMacro(N) std::get(d_tuple).openDB(d_env, std::string(name)+"_"#N, MDB_CREATE | MDB_DUPFIXED | MDB_DUPSORT); + openMacro(0); + openMacro(1); + openMacro(2); + openMacro(3); +#undef openMacro + } + + + // we get a lot of our smarts from this tuple, it enables get<0> etc + typedef std::tuple tuple_t; + tuple_t d_tuple; + + // We support readonly and rw transactions. Here we put the Readonly operations + // which get sourced by both kinds of transactions + template + struct ReadonlyOperations + { + ReadonlyOperations(Parent& parent) : d_parent(parent) + {} + + //! Number of entries in main database + uint32_t size() + { + MDB_stat stat; + mdb_stat(**d_parent.d_txn, d_parent.d_parent->d_main, &stat); + return stat.ms_entries; + } + + //! Number of entries in the various indexes - should be the same + template + uint32_t size() + { + MDB_stat stat; + mdb_stat(**d_parent.d_txn, std::get(d_parent.d_parent->d_tuple).d_idx, &stat); + return stat.ms_entries; + } + + //! Get item with id, from main table directly + bool get(uint32_t id, T& t) + { + MDBOutVal data; + if((*d_parent.d_txn)->get(d_parent.d_parent->d_main, id, data)) + return false; + + serFromString(data.get(), t); + return true; + } + + //! Get item through index N, then via the main database + template + uint32_t get(const typename std::tuple_element::type::type& key, T& out) + { + MDBOutVal id; + if(!(*d_parent.d_txn)->get(std::get(d_parent.d_parent->d_tuple).d_idx, keyConv(key), id)) { + if(get(id.get(), out)) + return id.get(); + } + return 0; + } + + //! Cardinality of index N + template + uint32_t cardinality() + { + auto cursor = (*d_parent.d_txn)->getCursor(std::get(d_parent.d_parent->d_tuple).d_idx); + bool first = true; + MDBOutVal key, data; + uint32_t count = 0; + while(!cursor.get(key, data, first ? MDB_FIRST : MDB_NEXT_NODUP)) { + ++count; + first=false; + } + return count; + } + + //! End iterator type + struct eiter_t + {}; + + // can be on main, or on an index + // when on main, return data directly + // when on index, indirect + // we can be limited to one key, or iterate over entire database + // iter requires you to put the cursor in the right place first! + struct iter_t + { + explicit iter_t(Parent* parent, typename Parent::cursor_t&& cursor, bool on_index, bool one_key, bool end=false) : + d_parent(parent), + d_cursor(std::move(cursor)), + d_on_index(on_index), // is this an iterator on main database or on index? + d_one_key(one_key), // should we stop at end of key? (equal range) + d_end(end) + { + if(d_end) + return; + d_prefix.clear(); + + if(d_cursor.get(d_key, d_id, MDB_GET_CURRENT)) { + d_end = true; + return; + } + + if(d_on_index) { + if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data)) + throw std::runtime_error("Missing id in constructor"); + serFromString(d_data.get(), d_t); + } + else + serFromString(d_id.get(), d_t); + } + + explicit iter_t(Parent* parent, typename Parent::cursor_t&& cursor, const std::string& prefix) : + d_parent(parent), + d_cursor(std::move(cursor)), + d_on_index(true), // is this an iterator on main database or on index? + d_one_key(false), + d_prefix(prefix), + d_end(false) + { + if(d_end) + return; + + if(d_cursor.get(d_key, d_id, MDB_GET_CURRENT)) { + d_end = true; + return; + } + + if(d_on_index) { + if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data)) + throw std::runtime_error("Missing id in constructor"); + serFromString(d_data.get(), d_t); + } + else + serFromString(d_id.get(), d_t); + } + + + std::function filter; + void del() + { + d_cursor.del(); + } + + bool operator!=(const eiter_t& rhs) const + { + return !d_end; + } + + bool operator==(const eiter_t& rhs) const + { + return d_end; + } + + const T& operator*() + { + return d_t; + } + + const T* operator->() + { + return &d_t; + } + + // implements generic ++ or -- + iter_t& genoperator(MDB_cursor_op dupop, MDB_cursor_op op) + { + MDBOutVal data; + int rc; + next:; + rc = d_cursor.get(d_key, d_id, d_one_key ? dupop : op); + if(rc == MDB_NOTFOUND) { + d_end = true; + } + else if(rc) { + throw std::runtime_error("in genoperator, " + std::string(mdb_strerror(rc))); + } + else if(!d_prefix.empty() && d_key.get().rfind(d_prefix, 0)!=0) { + d_end = true; + } + else { + if(d_on_index) { + if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, data)) + throw std::runtime_error("Missing id field"); + if(filter && !filter(data)) + goto next; + + serFromString(data.get(), d_t); + } + else { + if(filter && !filter(data)) + goto next; + + serFromString(d_id.get(), d_t); + } + } + return *this; + } + + iter_t& operator++() + { + return genoperator(MDB_NEXT_DUP, MDB_NEXT); + } + iter_t& operator--() + { + return genoperator(MDB_PREV_DUP, MDB_PREV); + } + + // get ID this iterator points to + uint32_t getID() + { + if(d_on_index) + return d_id.get(); + else + return d_key.get(); + } + + const MDBOutVal& getKey() + { + return d_key; + } + + + // transaction we are part of + Parent* d_parent; + typename Parent::cursor_t d_cursor; + + // gcc complains if I don't zero-init these, which is worrying XXX + MDBOutVal d_key{{0,0}}, d_data{{0,0}}, d_id{{0,0}}; + bool d_on_index; + bool d_one_key; + std::string d_prefix; + bool d_end{false}; + T d_t; + }; + + template + iter_t genbegin(MDB_cursor_op op) + { + typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get(d_parent.d_parent->d_tuple).d_idx); + + MDBOutVal out, id; + + if(cursor.get(out, id, op)) { + // on_index, one_key, end + return iter_t{&d_parent, std::move(cursor), true, false, true}; + } + + return iter_t{&d_parent, std::move(cursor), true, false}; + }; + + template + iter_t begin() + { + return genbegin(MDB_FIRST); + } + + template + iter_t rbegin() + { + return genbegin(MDB_LAST); + } + + iter_t begin() + { + typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(d_parent.d_parent->d_main); + + MDBOutVal out, id; + + if(cursor.get(out, id, MDB_FIRST)) { + // on_index, one_key, end + return iter_t{&d_parent, std::move(cursor), false, false, true}; + } + + return iter_t{&d_parent, std::move(cursor), false, false}; + }; + + eiter_t end() + { + return eiter_t(); + } + + // basis for find, lower_bound + template + iter_t genfind(const typename std::tuple_element::type::type& key, MDB_cursor_op op) + { + typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get(d_parent.d_parent->d_tuple).d_idx); + + std::string keystr = keyConv(key); + MDBInVal in(keystr); + MDBOutVal out, id; + out.d_mdbval = in.d_mdbval; + + if(cursor.get(out, id, op)) { + // on_index, one_key, end + return iter_t{&d_parent, std::move(cursor), true, false, true}; + } + + return iter_t{&d_parent, std::move(cursor), true, false}; + }; + + template + iter_t find(const typename std::tuple_element::type::type& key) + { + return genfind(key, MDB_SET); + } + + template + iter_t lower_bound(const typename std::tuple_element::type::type& key) + { + return genfind(key, MDB_SET_RANGE); + } + + + //! equal range - could possibly be expressed through genfind + template + std::pair equal_range(const typename std::tuple_element::type::type& key) + { + typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get(d_parent.d_parent->d_tuple).d_idx); + + std::string keyString=keyConv(key); + MDBInVal in(keyString); + MDBOutVal out, id; + out.d_mdbval = in.d_mdbval; + + if(cursor.get(out, id, MDB_SET)) { + // on_index, one_key, end + return {iter_t{&d_parent, std::move(cursor), true, true, true}, eiter_t()}; + } + + return {iter_t{&d_parent, std::move(cursor), true, true}, eiter_t()}; + }; + + //! equal range - could possibly be expressed through genfind + template + std::pair prefix_range(const typename std::tuple_element::type::type& key) + { + typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get(d_parent.d_parent->d_tuple).d_idx); + + std::string keyString=keyConv(key); + MDBInVal in(keyString); + MDBOutVal out, id; + out.d_mdbval = in.d_mdbval; + + if(cursor.get(out, id, MDB_SET_RANGE)) { + // on_index, one_key, end + return {iter_t{&d_parent, std::move(cursor), true, true, true}, eiter_t()}; + } + + return {iter_t(&d_parent, std::move(cursor), keyString), eiter_t()}; + }; + + + Parent& d_parent; + }; + + class ROTransaction : public ReadonlyOperations + { + public: + explicit ROTransaction(TypedDBI* parent) : ReadonlyOperations(*this), d_parent(parent), d_txn(std::make_shared(d_parent->d_env->getROTransaction())) + { + } + + explicit ROTransaction(TypedDBI* parent, std::shared_ptr txn) : ReadonlyOperations(*this), d_parent(parent), d_txn(txn) + { + } + + + ROTransaction(ROTransaction&& rhs) : + ReadonlyOperations(*this), d_parent(rhs.d_parent),d_txn(std::move(rhs.d_txn)) + + { + rhs.d_parent = 0; + } + + std::shared_ptr getTransactionHandle() + { + return d_txn; + } + + typedef MDBROCursor cursor_t; + + TypedDBI* d_parent; + std::shared_ptr d_txn; + }; + + + class RWTransaction : public ReadonlyOperations + { + public: + explicit RWTransaction(TypedDBI* parent) : ReadonlyOperations(*this), d_parent(parent) + { + d_txn = std::make_shared(d_parent->d_env->getRWTransaction()); + } + + explicit RWTransaction(TypedDBI* parent, std::shared_ptr txn) : ReadonlyOperations(*this), d_parent(parent), d_txn(txn) + { + } + + + RWTransaction(RWTransaction&& rhs) : + ReadonlyOperations(*this), + d_parent(rhs.d_parent), d_txn(std::move(rhs.d_txn)) + { + rhs.d_parent = 0; + } + + // insert something, with possibly a specific id + uint32_t put(const T& t, uint32_t id=0) + { + int flags = 0; + if(!id) { + id = MDBGetMaxID(*d_txn, d_parent->d_main) + 1; + flags = MDB_APPEND; + } + (*d_txn)->put(d_parent->d_main, id, serToString(t), flags); + +#define insertMacro(N) std::get(d_parent->d_tuple).put(*d_txn, t, id); + insertMacro(0); + insertMacro(1); + insertMacro(2); + insertMacro(3); +#undef insertMacro + + return id; + } + + // modify an item 'in place', plus update indexes + void modify(uint32_t id, std::function func) + { + T t; + if(!this->get(id, t)) + throw std::runtime_error("Could not modify id "+std::to_string(id)); + func(t); + + del(id); // this is the lazy way. We could test for changed index fields + put(t, id); + } + + //! delete an item, and from indexes + void del(uint32_t id) + { + T t; + if(!this->get(id, t)) + return; + + (*d_txn)->del(d_parent->d_main, id); + clearIndex(id, t); + } + + //! clear database & indexes (by hand!) + void clear() + { + auto cursor = (*d_txn)->getRWCursor(d_parent->d_main); + bool first = true; + MDBOutVal key, data; + while(!cursor.get(key, data, first ? MDB_FIRST : MDB_NEXT)) { + first = false; + T t; + serFromString(data.get(), t); + clearIndex(key.get(), t); + cursor.del(); + } + } + + //! commit this transaction + void commit() + { + (*d_txn)->commit(); + } + + //! abort this transaction + void abort() + { + (*d_txn)->abort(); + } + + typedef MDBRWCursor cursor_t; + + std::shared_ptr getTransactionHandle() + { + return d_txn; + } + + + private: + // clear this ID from all indexes + void clearIndex(uint32_t id, const T& t) + { +#define clearMacro(N) std::get(d_parent->d_tuple).del(*d_txn, t, id); + clearMacro(0); + clearMacro(1); + clearMacro(2); + clearMacro(3); +#undef clearMacro + } + + public: + TypedDBI* d_parent; + std::shared_ptr d_txn; + }; + + //! Get an RW transaction + RWTransaction getRWTransaction() + { + return RWTransaction(this); + } + + //! Get an RO transaction + ROTransaction getROTransaction() + { + return ROTransaction(this); + } + + //! Get an RW transaction + RWTransaction getRWTransaction(std::shared_ptr txn) + { + return RWTransaction(this, txn); + } + + //! Get an RO transaction + ROTransaction getROTransaction(std::shared_ptr txn) + { + return ROTransaction(this, txn); + } + + std::shared_ptr getEnv() + { + return d_env; + } + +private: + std::shared_ptr d_env; + MDBDbi d_main; + std::string d_name; +}; + + + + + diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc new file mode 100644 index 0000000..0104836 --- /dev/null +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -0,0 +1,1635 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/utility.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dns.hh" +#include "pdns/dnspacket.hh" +#include "pdns/base32.hh" +#include "pdns/dnssecinfra.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/version.hh" +#include "pdns/arguments.hh" +#include +#include +#include +#include +#include +// #include +// #include + +#include +// #include + + +#include "lmdbbackend.hh" + +#define SCHEMAVERSION 1 + +LMDBBackend::LMDBBackend(const std::string& suffix) +{ + setArgPrefix("lmdb"+suffix); + + string syncMode = toLower(getArg("sync-mode")); + + if(syncMode == "nosync") + d_asyncFlag = MDB_NOSYNC; + else if(syncMode == "nometasync") + d_asyncFlag = MDB_NOMETASYNC; + else if(syncMode == "mapasync") + d_asyncFlag = MDB_MAPASYNC; + else if(syncMode.empty() || syncMode == "sync") + d_asyncFlag = 0; + else + throw std::runtime_error("Unknown sync mode "+syncMode+" requested for LMDB backend"); + + d_tdomains = std::make_shared(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600), "domains"); + d_tmeta = std::make_shared(d_tdomains->getEnv(), "metadata"); + d_tkdb = std::make_shared(d_tdomains->getEnv(), "keydata"); + d_ttsig = std::make_shared(d_tdomains->getEnv(), "tsig"); + + auto pdnsdbi = d_tdomains->getEnv()->openDB("pdns", MDB_CREATE); + auto txn = d_tdomains->getEnv()->getRWTransaction(); + MDBOutVal _schemaversion; + if(!txn->get(pdnsdbi, "schemaversion", _schemaversion)) { + auto schemaversion = _schemaversion.get(); + if (schemaversion != SCHEMAVERSION) { + throw std::runtime_error("Expected LMDB schema version "+std::to_string(SCHEMAVERSION)+" but got "+std::to_string(schemaversion)); + } + } + else { + txn->put(pdnsdbi, "schemaversion", SCHEMAVERSION); + } + MDBOutVal shards; + if(!txn->get(pdnsdbi, "shards", shards)) { + + d_shards = shards.get(); + if(d_shards != atoi(getArg("shards").c_str())) { + g_log << Logger::Warning<<"Note: configured number of lmdb shards ("<put(pdnsdbi, "shards", d_shards); + } + txn->commit(); + d_trecords.resize(d_shards); + d_dolog = ::arg().mustDo("query-logging"); +} + + + +namespace boost { +namespace serialization { + +template +void save(Archive & ar, const DNSName& g, const unsigned int version) +{ + if(!g.empty()) { + std::string tmp = g.toDNSStringLC(); // g++ 4.8 woes + ar & tmp; + } + else + ar & ""; +} + +template +void load(Archive & ar, DNSName& g, const unsigned int version) +{ + string tmp; + ar & tmp; + if(tmp.empty()) + g = DNSName(); + else + g = DNSName(tmp.c_str(), tmp.size(), 0, false); +} + +template +void save(Archive & ar, const QType& g, const unsigned int version) +{ + uint16_t tmp = g.getCode(); // g++ 4.8 woes + ar & tmp; +} + +template +void load(Archive & ar, QType& g, const unsigned int version) +{ + uint16_t tmp; + ar & tmp; + g = QType(tmp); +} + +template +void serialize(Archive & ar, DomainInfo& g, const unsigned int version) +{ + ar & g.zone; + ar & g.last_check; + ar & g.account; + ar & g.masters; + ar & g.id; + ar & g.notified_serial; + ar & g.kind; +} + +template +void serialize(Archive & ar, LMDBBackend::DomainMeta& g, const unsigned int version) +{ + ar & g.domain & g.key & g.value; +} + +template +void serialize(Archive & ar, LMDBBackend::KeyDataDB& g, const unsigned int version) +{ + ar & g.domain & g.content & g.flags & g.active; +} + +template +void serialize(Archive & ar, TSIGKey& g, const unsigned int version) +{ + ar & g.name; + ar & g.algorithm; // this is the ordername + ar & g.key; +} + + + +} // namespace serialization +} // namespace boost + +BOOST_SERIALIZATION_SPLIT_FREE(DNSName); +BOOST_SERIALIZATION_SPLIT_FREE(QType); +BOOST_IS_BITWISE_SERIALIZABLE(ComboAddress); + +template<> +std::string serToString(const DNSResourceRecord& rr) +{ + // only does content, ttl, auth + std::string ret; + uint16_t len = rr.content.length(); + ret.reserve(2+len+8); + + ret.assign((const char*)&len, 2); + ret += rr.content; + ret.append((const char*)&rr.ttl, 4); + ret.append(1, (char)rr.auth); + ret.append(1, (char)false); + ret.append(1, (char)rr.disabled); + return ret; +} + +template<> +void serFromString(const string_view& str, DNSResourceRecord& rr) +{ + uint16_t len; + memcpy(&len, &str[0], 2); + rr.content.assign(&str[2], len); // len bytes + memcpy(&rr.ttl, &str[2] + len, 4); + rr.auth = str[str.size()-3]; + rr.disabled = str[str.size()-1]; + rr.wildcardname.clear(); +} + + +std::string serializeContent(uint16_t qtype, const DNSName& domain, const std::string& content) +{ + auto drc = DNSRecordContent::mastermake(qtype, 1, content); + return drc->serialize(domain, false); +} + +std::shared_ptr unserializeContentZR(uint16_t qtype, const DNSName& qname, const std::string& content) +{ + if(qtype == QType::A && content.size() == 4) { + return std::make_shared(*((uint32_t*)content.c_str())); + } + return DNSRecordContent::unserialize(qname, qtype, content); +} + + +/* design. If you ask a question without a zone id, we lookup the best + zone id for you, and answer from that. This is different than other backends, but I can't see why it would not work. + + The index we use is "zoneid,canonical relative name". This index is also used + for AXFR. + + Note - domain_id, name and type are ONLY present on the index! +*/ + +#if BOOST_VERSION >= 106100 +#define StringView string_view +#else +#define StringView string +#endif + +void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype) +{ + compoundOrdername co; + string match = co(domain_id); + + auto cursor = txn.txn->getCursor(txn.db->dbi); + MDBOutVal key, val; + // cout<<"Match: "<().rfind(match, 0) == 0) { + if(qtype == QType::ANY || co.getQType(key.get()) == qtype) + cursor.del(MDB_NODUPDATA); + if(cursor.next(key, val)) break; + } + } +} + +/* Here's the complicated story. Other backends have just one transaction, which is either + on or not. + + You can't call feedRecord without a transaction started with startTransaction. + + However, other functions can be called after startTransaction() or without startTransaction() + (like updateDNSSECOrderNameAndAuth) + + + +*/ + +bool LMDBBackend::startTransaction(const DNSName &domain, int domain_id) +{ + // cout <<"startTransaction("<getROTransaction(); + DomainInfo di; + real_id = rotxn.get<0>(domain, di); + // cout<<"real_id = "<= 0) { + deleteDomainRecords(*d_rwtxn, domain_id); + } + + return true; +} + +bool LMDBBackend::commitTransaction() +{ + // cout<<"Commit transaction" <txn->commit(); + d_rwtxn.reset(); + return true; +} + +bool LMDBBackend::abortTransaction() +{ + // cout<<"Abort transaction"<txn->abort(); + d_rwtxn.reset(); + + return true; +} + +// d_rwtxn must be set here +bool LMDBBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3) +{ + DNSResourceRecord rr(r); + rr.qname.makeUsRelative(d_transactiondomain); + rr.content = serializeContent(rr.qtype.getCode(), r.qname, rr.content); + rr.disabled = false; + + compoundOrdername co; + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(r.domain_id, rr.qname, rr.qtype.getCode()), serToString(rr)); + + if(ordernameIsNSEC3 && !ordername.empty()) { + MDBOutVal val; + if(d_rwtxn->txn->get(d_rwtxn->db->dbi, co(r.domain_id, rr.qname, QType::NSEC3), val)) { + rr.ttl = 0; + rr.content=rr.qname.toDNSStringLC(); + rr.auth = 0; + string ser = serToString(rr); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(r.domain_id, ordername, QType::NSEC3), ser); + + rr.ttl = 1; + rr.content = ordername.toDNSString(); + ser = serToString(rr); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(r.domain_id, rr.qname, QType::NSEC3), ser); + } + } + return true; +} + +bool LMDBBackend::feedEnts(int domain_id, map& nonterm) +{ + DNSResourceRecord rr; + rr.ttl = 0; + compoundOrdername co; + for(const auto& nt: nonterm) { + rr.qname = nt.first.makeRelative(d_transactiondomain); + rr.auth = nt.second; + rr.disabled = true; + + std::string ser = serToString(rr); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(domain_id, rr.qname, 0), ser); + } + return true; +} + +bool LMDBBackend::feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) +{ + string ser; + DNSName ordername; + DNSResourceRecord rr; + compoundOrdername co; + for(const auto& nt: nonterm) { + rr.qname = nt.first.makeRelative(domain); + rr.ttl = 0; + rr.auth = nt.second; + rr.disabled = nt.second; + ser = serToString(rr); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(domain_id, rr.qname, 0), ser); + + if(!narrow && rr.auth) { + rr.content = rr.qname.toDNSString(); + rr.auth = false; + rr.disabled = false; + ser = serToString(rr); + + ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3prc, nt.first))); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(domain_id, ordername, QType::NSEC3), ser); + + rr.ttl = 1; + rr.content = ordername.toDNSString(); + ser = serToString(rr); + d_rwtxn->txn->put(d_rwtxn->db->dbi, co(domain_id, rr.qname, QType::NSEC3), ser); + } + } + return true; +} + + +// might be called within a transaction, might also be called alone +bool LMDBBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) +{ + // zonk qname/qtype within domain_id (go through qname, check domain_id && qtype) + shared_ptr txn; + bool needCommit = false; + if(d_rwtxn && d_transactiondomainid==domain_id) { + txn = d_rwtxn; + // cout<<"Reusing open transaction"<getROTransaction().get(domain_id, di)) { + return false; + } + + compoundOrdername co; + auto cursor = txn->txn->getCursor(txn->db->dbi); + MDBOutVal key, val; + string match =co(domain_id, qname.makeRelative(di.zone), qt.getCode()); + if(!cursor.find(match, key, val)) { + do { + cursor.del(MDB_NODUPDATA); + } while(!cursor.next(key, val) && key.get().rfind(match, 0) == 0); + } + + for(auto rr : rrset) { + rr.content = serializeContent(rr.qtype.getCode(), rr.qname, rr.content); + rr.qname.makeUsRelative(di.zone); + txn->txn->put(txn->db->dbi, match, serToString(rr)); + } + + if(needCommit) + txn->txn->commit(); + + return true; +} + +// tempting to templatize these two functions but the pain is not worth it +std::shared_ptr LMDBBackend::getRecordsRWTransaction(uint32_t id) +{ + auto& shard =d_trecords[id % d_shards]; + if(!shard.env) { + shard.env = getMDBEnv( (getArg("filename")+"-"+std::to_string(id % d_shards)).c_str(), + MDB_NOSUBDIR | d_asyncFlag, 0600); + shard.dbi = shard.env->openDB("records", MDB_CREATE | MDB_DUPSORT); + } + auto ret = std::make_shared(shard.env->getRWTransaction()); + ret->db = std::make_shared(shard); + + return ret; +} + +std::shared_ptr LMDBBackend::getRecordsROTransaction(uint32_t id, std::shared_ptr rwtxn) +{ + auto& shard =d_trecords[id % d_shards]; + if(!shard.env) { + if (rwtxn) { + throw DBException("attempting to start nested transaction without open parent env"); + } + shard.env = getMDBEnv( (getArg("filename")+"-"+std::to_string(id % d_shards)).c_str(), + MDB_NOSUBDIR | d_asyncFlag, 0600); + shard.dbi = shard.env->openDB("records", MDB_CREATE | MDB_DUPSORT); + } + + if (rwtxn) { + auto ret = std::make_shared(rwtxn->txn->getROTransaction()); + ret->db = std::make_shared(shard); + return ret; + } else { + auto ret = std::make_shared(shard.env->getROTransaction()); + ret->db = std::make_shared(shard); + return ret; + } +} + + +bool LMDBBackend::deleteDomain(const DNSName &domain) +{ + auto doms = d_tdomains->getRWTransaction(); + + DomainInfo di; + auto id = doms.get<0>(domain, di); + if(!id) + return false; + + shared_ptr txn; + bool needCommit = false; + if(d_rwtxn && d_transactiondomainid == id) { + txn = d_rwtxn; + // cout<<"Reusing open transaction"<txn->getCursor(txn->db->dbi); + MDBOutVal key, val; + if(!cursor.find(match, key, val)) { + do { + cursor.del(MDB_NODUPDATA); + } while(!cursor.next(key, val) && key.get().rfind(match, 0) == 0); + } + + if(needCommit) + txn->txn->commit(); + + doms.commit(); + + return true; +} + +bool LMDBBackend::list(const DNSName &target, int id, bool include_disabled) +{ + d_inlist=true; + DomainInfo di; + { + auto dtxn = d_tdomains->getROTransaction(); + + if((di.id = dtxn.get<0>(target, di))) + ; // cout<<"Found domain "<(d_rotxn->txn->getCursor(d_rotxn->db->dbi)); + MDBOutVal key, val; + d_inlist = true; + + if(d_getcursor->lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { + // cout<<"Found nothing for list"<getROTransaction(); + + do { + zoneId = rotxn.get<0>(hunt, di); + } while (!zoneId && type != QType::SOA && hunt.chopOff()); + if(zoneId <= 0) { + // cout << "Did not find zone for "<< qdomain<getROTransaction().get(zoneId, di)) { + // cout<<"Could not find a zone with id "<(d_rotxn->txn->getCursor(d_rotxn->db->dbi)); + MDBOutVal key, val; + if(type.getCode() == QType::ANY) { + d_matchkey = co(zoneId,relqname); + } + else { + d_matchkey= co(zoneId,relqname, type.getCode()); + } + d_inlist=false; + + if(d_getcursor->lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { + d_getcursor.reset(); + if(d_dolog) { + g_log<getZoneRepresentation(true); + rr.domain_id = dzr.domain_id; + rr.auth = dzr.auth; + // cout<<"old school called for "<(dzr.dr); + sd.domain_id = dzr.domain_id; + sd.ttl = dzr.dr.d_ttl; + sd.qname = dzr.dr.d_name; + + sd.nameserver = src->d_mname; + sd.hostmaster = src->d_rname; + sd.serial = src->d_st.serial; + sd.refresh = src->d_st.refresh; + sd.retry = src->d_st.retry; + sd.expire = src->d_st.expire; + sd.default_ttl = src->d_st.minimum; + + sd.db = this; + found=true; + } + return found; +} +bool LMDBBackend::get_list(DNSZoneRecord& rr) +{ + for(;;) { + if(!d_getcursor) { + d_rotxn.reset(); + return false; + } + + MDBOutVal keyv, val; + + d_getcursor->current(keyv, val); + DNSResourceRecord drr; + serFromString(val.get(), drr); + + auto key = keyv.get(); + rr.dr.d_name = compoundOrdername::getQName(key) + d_lookupqname; + rr.domain_id = compoundOrdername::getDomainID(key); + rr.dr.d_type = compoundOrdername::getQType(key).getCode(); + rr.dr.d_ttl = drr.ttl; + rr.auth = drr.auth; + + if(rr.dr.d_type == QType::NSEC3) { + // cout << "Had a magic NSEC3, skipping it" << endl; + if(d_getcursor->next(keyv, val) || keyv.get().rfind(d_matchkey, 0) != 0) { + d_getcursor.reset(); + } + continue; + } + rr.dr.d_content = unserializeContentZR(rr.dr.d_type, rr.dr.d_name, drr.content); + + if(d_getcursor->next(keyv, val) || keyv.get().rfind(d_matchkey, 0) != 0) { + d_getcursor.reset(); + } + break; + } + return true; +} + + +bool LMDBBackend::get_lookup(DNSZoneRecord& rr) +{ + for(;;) { + if(!d_getcursor) { + d_rotxn.reset(); + return false; + } + MDBOutVal keyv, val; + d_getcursor->current(keyv, val); + DNSResourceRecord drr; + serFromString(val.get(), drr); + + auto key = keyv.get(); + + rr.dr.d_name = compoundOrdername::getQName(key) + d_lookupdomain; + + rr.domain_id = compoundOrdername::getDomainID(key); + // cout << "We found "<next(keyv, val) || keyv.get().rfind(d_matchkey, 0) != 0) { + d_getcursor.reset(); + d_rotxn.reset(); + } + continue; + } + + rr.dr.d_content = unserializeContentZR(rr.dr.d_type, rr.dr.d_name, drr.content); + rr.auth = drr.auth; + if(d_getcursor->next(keyv, val) || keyv.get().rfind(d_matchkey, 0) != 0) { + d_getcursor.reset(); + d_rotxn.reset(); + } + break; + } + + + return true; +} + + +bool LMDBBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial) +{ + auto txn = d_tdomains->getROTransaction(); + + if(!(di.id=txn.get<0>(domain, di))) + return false; + di.backend = this; + return true; +} + + +int LMDBBackend::genChangeDomain(const DNSName& domain, std::function func) +{ + auto txn = d_tdomains->getRWTransaction(); + + DomainInfo di; + + auto id = txn.get<0>(domain, di); + func(di); + txn.put(di, id); + + txn.commit(); + return true; +} + +int LMDBBackend::genChangeDomain(uint32_t id, std::function func) +{ + DomainInfo di; + + auto txn = d_tdomains->getRWTransaction(); + + if(!txn.get(id , di)) + return false; + + func(di); + + txn.put(di, id); + + txn.commit(); + return true; +} + + +bool LMDBBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind) +{ + return genChangeDomain(domain, [kind](DomainInfo& di) { + di.kind = kind; + }); +} + +bool LMDBBackend::setAccount(const DNSName &domain, const std::string& account) +{ + return genChangeDomain(domain, [account](DomainInfo& di) { + di.account = account; + }); +} + + +void LMDBBackend::setFresh(uint32_t domain_id) +{ + genChangeDomain(domain_id, [](DomainInfo& di) { + di.last_check = time(0); + }); +} + +void LMDBBackend::setNotified(uint32_t domain_id, uint32_t serial) +{ + genChangeDomain(domain_id, [serial](DomainInfo& di) { + di.serial = serial; + }); +} + + +bool LMDBBackend::setMaster(const DNSName &domain, const std::string& ips) +{ + vector masters; + vector parts; + stringtok(parts, ips, " \t;,"); + for(const auto& ip : parts) + masters.push_back(ComboAddress(ip, 53)); + + return genChangeDomain(domain, [&masters](DomainInfo& di) { + di.masters = masters; + }); +} + +bool LMDBBackend::createDomain(const DNSName &domain) +{ + return createDomain(domain, "NATIVE", "", ""); +} + +bool LMDBBackend::createDomain(const DNSName &domain, const string &type, const string &masters, const string &account) +{ + DomainInfo di; + + auto txn = d_tdomains->getRWTransaction(); + if(txn.get<0>(domain, di)) { + throw DBException("Domain '"+domain.toLogString()+"' exists already"); + } + + di.zone = domain; + if(pdns_iequals(type, "master")) + di.kind = DomainInfo::Master; + else if(pdns_iequals(type, "slave")) + di.kind = DomainInfo::Slave; + else if(pdns_iequals(type, "native")) + di.kind = DomainInfo::Native; + else + throw DBException("Unable to create domain of unknown type '"+type+"'"); + di.account = account; + + txn.put(di); + txn.commit(); + + return true; +} + +void LMDBBackend::getAllDomains(vector *domains, bool include_disabled) +{ + compoundOrdername co; + MDBOutVal val; + domains->clear(); + auto txn = d_tdomains->getROTransaction(); + for(auto iter = txn.begin(); iter != txn.end(); ++iter) { + DomainInfo di=*iter; + di.id = iter.getID(); + + auto txn2 = getRecordsROTransaction(iter.getID()); + if(!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) { + DNSResourceRecord rr; + serFromString(val.get(), rr); + + if(rr.content.size() >= 5 * sizeof(uint32_t)) { + uint32_t serial = *reinterpret_cast(&rr.content[rr.content.size() - (5 * sizeof(uint32_t))]); + di.serial = ntohl(serial); + } + } else if(!include_disabled) { + continue; + } + domains->push_back(di); + } +} + +void LMDBBackend::getUnfreshSlaveInfos(vector* domains) +{ + // cout<<"Start of getUnfreshSlaveInfos"<clear(); + auto txn = d_tdomains->getROTransaction(); + + time_t now = time(0); + for(auto iter = txn.begin(); iter != txn.end(); ++iter) { + if(iter->kind != DomainInfo::Slave) + continue; + + auto txn2 = getRecordsROTransaction(iter.getID()); + compoundOrdername co; + MDBOutVal val; + uint32_t serial = 0; + if(!txn2->txn->get(txn2->db->dbi, co(iter.getID(), g_rootdnsname, QType::SOA), val)) { + DNSResourceRecord rr; + serFromString(val.get(), rr); + struct soatimes st; + + memcpy(&st, &rr.content[rr.content.size()-sizeof(soatimes)], sizeof(soatimes)); + + if((time_t)(iter->last_check + ntohl(st.refresh)) >= now) { // still fresh + continue; // try next domain + } + // cout << di.last_check <<" + " < = " << now << "\n"; + serial = ntohl(st.serial); + } + else { + // cout << "Could not find SOA for "<zone<<" with id "<push_back(di); + } + // cout<<"END of getUnfreshSlaveInfos"< >& meta) +{ + meta.clear(); + auto txn = d_tmeta->getROTransaction(); + auto range = txn.equal_range<0>(name); + + for(auto& iter = range.first; iter != range.second; ++iter) { + meta[iter->key].push_back(iter->value); + } + return true; +} + +bool LMDBBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ + auto txn = d_tmeta->getRWTransaction(); + + auto range = txn.equal_range<0>(name); + + for(auto& iter = range.first; iter != range.second; ++iter) { + if(iter-> key == kind) + iter.del(); + } + + for(const auto& m : meta) { + DomainMeta dm{name, kind, m}; + txn.put(dm); + } + txn.commit(); + return true; + +} + +bool LMDBBackend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + auto txn = d_tkdb->getROTransaction(); + auto range = txn.equal_range<0>(name); + for(auto& iter = range.first; iter != range.second; ++iter) { + KeyData kd{iter->content, iter.getID(), iter->flags, iter->active}; + keys.push_back(kd); + } + + return true; +} + +bool LMDBBackend::removeDomainKey(const DNSName& name, unsigned int id) +{ + auto txn = d_tkdb->getRWTransaction(); + KeyDataDB kdb; + if(txn.get(id, kdb)) { + if(kdb.domain == name) { + txn.del(id); + txn.commit(); + return true; + } + } + // cout << "??? wanted to remove domain key for domain "<getRWTransaction(); + KeyDataDB kdb{name, key.content, key.flags, key.active}; + id = txn.put(kdb); + txn.commit(); + + return true; +} + +bool LMDBBackend::activateDomainKey(const DNSName& name, unsigned int id) +{ + auto txn = d_tkdb->getRWTransaction(); + KeyDataDB kdb; + if(txn.get(id, kdb)) { + if(kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) + { + kdbarg.active = true; + }); + txn.commit(); + return true; + } + } + + // cout << "??? wanted to activate domain key for domain "<getRWTransaction(); + KeyDataDB kdb; + if(txn.get(id, kdb)) { + if(kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) + { + kdbarg.active = false; + }); + txn.commit(); + return true; + } + } + // cout << "??? wanted to activate domain key for domain "<getROTransaction().get(id, di)) { + // domain does not exist, tough luck + return false; + } + // cout <<"Zone: "<txn->getCursor(txn->db->dbi); + MDBOutVal key, val; + + DNSResourceRecord rr; + + string matchkey = co(id, qname, QType::NSEC3); + if(cursor.lower_bound(matchkey, key, val)) { + // this is beyond the end of the database + // cout << "Beyond end of database!" << endl; + cursor.last(key, val); + + for(;;) { + if(co.getDomainID(key.get()) != id) { + //cout<<"Last record also not part of this zone!"<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) // the kind of NSEC3 we need + break; + } + if(cursor.prev(key, val)) { + // hit beginning of database, again means something is wrong with it + return false; + } + } + before = co.getQName(key.get()); + unhashed = DNSName(rr.content.c_str(), rr.content.size(), 0, false) + di.zone; + + // now to find after .. at the beginning of the zone + if(cursor.lower_bound(co(id), key, val)) { + // cout<<"hit end of zone find when we shouldn't"<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) + break; + } + + if(cursor.next(key, val) || co.getDomainID(key.get()) != id) { + // cout<<"hit end of zone or database when we shouldn't"<()); + // cout<<"returning: before="<()) <()); + if(before == qname) { + // cout << "Ended up on exact right node" << endl; + before = co.getQName(key.get()); + // unhashed should be correct now, maybe check? + if(cursor.next(key, val)) { + // xxx should find first hash now + + if(cursor.lower_bound(co(id), key, val)) { + // cout<<"hit end of zone find when we shouldn't for id "<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) + break; + } + + if(cursor.next(key, val) || co.getDomainID(key.get()) != id) { + // cout<<"hit end of zone or database when we shouldn't" << __LINE__<()); + // cout<<"returning: before="<()).canonCompare(qname) && co.getQType(key.get()) == QType::NSEC3) { + // cout<<"Potentially stopping traverse at "<< co.getQName(key.get()) <<", " << (co.getQName(key.get()).canonCompare(qname))<()) != id) { + //cout<<"Last record also not part of this zone!"<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) // the kind of NSEC3 we need + break; + } + if(cursor.prev(key, val)) { + // hit beginning of database, again means something is wrong with it + return false; + } + } + before = co.getQName(key.get()); + unhashed = DNSName(rr.content.c_str(), rr.content.size(), 0, false) + di.zone; + // cout <<"Should still find 'after'!"<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) + break; + } + + if(cursor.next(key, val)) { + // means database is wrong, nothing we can do + // cout<<"hit end of zone when we shouldn't 2"<()); + + + // cout<<"returning: before="<()); + unhashed = DNSName(rr.content.c_str(), rr.content.size(), 0, false) + di.zone; + // cout<<"Went backwards, found "<()) != id ) { + // cout <<"Hit end of database or zone, finding first hash then in zone "<()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) + break; + } + + if(cursor.next(key, val)) { + // means database is wrong, nothing we can do + // cout<<"hit end of zone when we shouldn't 2"<()); + + // cout<<"returning: before="<()) <()) == QType::NSEC3) { + serFromString(val.get(), rr); + if(!rr.ttl) { + break; + } + } + } + after = co.getQName(key.get()); + // cout<<"returning: before="<txn->getCursor(txn->db->dbi); + MDBOutVal key, val; + // cout<<"Lower_bound for "<()) == id) { + before = co.getQName(key.get()) + zonename; + after = zonename; + } + // else + // cout << "We were at end of database, but this zone is not there?!"<()) <<", in zone id "<())<< endl; + + if(co.getQType(key.get()).getCode() && co.getDomainID(key.get()) ==id && co.getQName(key.get()) == qname2) { // don't match ENTs + // cout << "Had an exact match!"<()) == id && key.get().rfind(matchkey, 0)==0) + continue; + DNSResourceRecord rr; + serFromString(val.get(), rr); + if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) + break; + } + if(rc || co.getDomainID(key.get()) != id) { + // cout << "We hit the end of the zone or database. 'after' is apex" << endl; + after=zonename; + return false; + } + after = co.getQName(key.get()) + zonename; + return true; + } + + + if(co.getDomainID(key.get()) != id) { + // cout << "Ended up in next zone, 'after' is zonename" <()) != id) { + // cout<<"Reversed into zone, but found wrong zone id " << co.getDomainID(key.get()) << " != "<(), rr); + if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) + break; + } + + before = co.getQName(key.get()) + zonename; + // cout<<"Found: "<< before<())<(), rr); + if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) { + after = co.getQName(key.get()) + zonename; + // cout <<"Found auth ("<()).getName()<<", ttl = "<()) << endl; + break; + } + // cout <<" oops, " << co.getQName(key.get()) << " was not auth "<()) != id ) { + // cout << " oops, hit end of database or zone. This means after is apex" <()) != id) { + // XX I don't think this case can happen + // cout << "We hit the beginning of the zone or database.. now what" << endl; + return false; + } + before = co.getQName(key.get()) + zonename; + DNSResourceRecord rr; + serFromString(val.get(), rr); + // cout<<"And before to "< txn; + bool needCommit = false; + if(d_rwtxn && d_transactiondomainid==domain_id) { + txn = d_rwtxn; + // cout<<"Reusing open transaction"<getROTransaction().get(domain_id, di)) { + // cout<<"Could not find domain_id "<txn->getCursor(txn->db->dbi); + MDBOutVal key, val; + if(cursor.lower_bound(matchkey, key, val)) { + // cout << "Could not find anything"<().rfind(matchkey,0) == 0; ) { + DNSResourceRecord rr; + rr.qtype = co.getQType(key.get()); + + if(rr.qtype != QType::NSEC3) { + serFromString(val.get(), rr); + if(!needNSEC3 && qtype != QType::ANY) { + needNSEC3 = (rr.disabled && QType(qtype) != rr.qtype); + } + + if((qtype == QType::ANY || QType(qtype) == rr.qtype) && (rr.disabled != hasOrderName || rr.auth != auth)) { + rr.auth = auth; + rr.disabled = hasOrderName; + string repl = serToString(rr); + cursor.put(key, repl); + } + } + + if(cursor.next(key, val)) + break; + } + + bool del = false; + DNSResourceRecord rr; + matchkey = co(domain_id,rel,QType::NSEC3); + if(!txn->txn->get(txn->db->dbi, matchkey, val)) { + serFromString(val.get(), rr); + + if(needNSEC3) { + if(hasOrderName && rr.content != ordername.toDNSStringLC()) { + del = true; + } + } else { + del = true; + } + if(del) { + txn->txn->del(txn->db->dbi, co(domain_id, DNSName(rr.content.c_str(), rr.content.size(), 0, false), QType::NSEC3)); + txn->txn->del(txn->db->dbi, matchkey); + } + } else { + del = true; + } + + if(hasOrderName && del) { + matchkey = co(domain_id,rel,QType::NSEC3); + + rr.ttl=0; + rr.auth=0; + rr.content=rel.toDNSStringLC(); + + string str = serToString(rr); + txn->txn->put(txn->db->dbi, co(domain_id,ordername,QType::NSEC3), str); + rr.ttl = 1; + rr.content = ordername.toDNSStringLC(); + str = serToString(rr); + txn->txn->put(txn->db->dbi, matchkey, str); // 2 + } + + if(needCommit) + txn->txn->commit(); + return false; +} + +bool LMDBBackend::updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) +{ + // cout << __PRETTY_FUNCTION__<< ": "<< domain_id << ", insert.size() "< txn; + if(d_rwtxn && d_transactiondomainid == domain_id) { + txn = d_rwtxn; + // cout<<"Reusing open transaction"<getROTransaction(); + if(!rotxn.get(domain_id, di)) { + // cout <<"No such domain with id "<txn->put(txn->db->dbi, co(domain_id, rr.qname, 0), ser); + + DNSResourceRecord rr2; + serFromString(ser, rr2); + + // cout <<" +"<txn->del(txn->db->dbi, co(domain_id, n, 0)); + } + } + if(needCommit) + txn->txn->commit(); + return false; +} + +/* TSIG */ +bool LMDBBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) +{ + auto txn = d_ttsig->getROTransaction(); + + TSIGKey tk; + if(!txn.get<0>(name, tk)) + return false; + if(algorithm) + *algorithm = tk.algorithm; + if(content) + *content = tk.key; + return true; + +} +// this deletes an old key if it has the same algorithm +bool LMDBBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ + auto txn = d_ttsig->getRWTransaction(); + + for(auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { + if(range.first->algorithm == algorithm) + range.first.del(); + } + + TSIGKey tk; + tk.name = name; + tk.algorithm = algorithm; + tk.key=content; + + txn.put(tk); + txn.commit(); + + return true; +} +bool LMDBBackend::deleteTSIGKey(const DNSName& name) +{ + auto txn = d_ttsig->getRWTransaction(); + TSIGKey tk; + + for(auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { + range.first.del(); + } + txn.commit(); + return true; +} +bool LMDBBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +{ + auto txn = d_ttsig->getROTransaction(); + + keys.clear(); + for(auto iter = txn.begin(); iter != txn.end(); ++iter) { + keys.push_back(*iter); + } + return false; +} + + + + +class LMDBFactory : public BackendFactory +{ +public: + LMDBFactory() : BackendFactory("lmdb") {} + void declareArguments(const string &suffix="") + { + declare(suffix,"filename","Filename for lmdb","./pdns.lmdb"); + declare(suffix,"sync-mode","Synchronisation mode: nosync, nometasync, mapasync, sync","mapasync"); + // there just is no room for more on 32 bit + declare(suffix,"shards","Records database will be split into this number of shards", (sizeof(long) == 4) ? "2" : "64"); + } + DNSBackend *make(const string &suffix="") + { + return new LMDBBackend(suffix); + } +}; + + + + +/* THIRD PART */ + +class LMDBLoader +{ +public: + LMDBLoader() + { + BackendMakers().report(new LMDBFactory); + g_log << Logger::Info << "[lmdbbackend] This is the lmdb backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + +static LMDBLoader randomLoader; diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh new file mode 100644 index 0000000..cd5647b --- /dev/null +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -0,0 +1,273 @@ +#pragma once +#include "pdns/dnsbackend.hh" +#include "lmdb-typed.hh" + +template::value,T>::type* = nullptr> +std::string keyConv(const T& t) +{ + /* www.ds9a.nl -> nl0ds9a0www0 + root -> 0 <- we need this to keep lmdb happy + nl -> nl0 + + */ + if(t.isRoot()) + return std::string(1, (char)0); + std::string in = t.labelReverse().toDNSStringLC(); // www.ds9a.nl is now 2nl4ds9a3www0 + std::string ret; + ret.reserve(in.size()); + + for(auto iter = in.begin(); iter != in.end(); ++iter) { + uint8_t len = *iter; + if(iter != in.begin()) + ret.append(1, (char)0); + if(!len) + break; + + ret.append(&*(iter+1), len); + iter+=len; + } + return ret; +} + + +class LMDBBackend : public DNSBackend +{ +public: + explicit LMDBBackend(const string &suffix=""); + + bool list(const DNSName &target, int id, bool include_disabled) override; + + bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true) override; + bool createDomain(const DNSName &domain, const string &type, const string &masters, const string &account); + + bool createDomain(const DNSName &domain) override; + + bool startTransaction(const DNSName &domain, int domain_id=-1) override; + bool commitTransaction() override; + bool abortTransaction() override; + bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + bool feedEnts(int domain_id, map& nonterm) override; + bool feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; + bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; + + void getAllDomains(vector *domains, bool include_disabled=false) override; + void lookup(const QType &type, const DNSName &qdomain, DNSPacket *p, int zoneId) override; + bool get(DNSResourceRecord &rr) override; + bool get(DNSZoneRecord& dzr) override; + + bool getSOA(const DNSName &domain, SOAData &sd) override; + void getUnfreshSlaveInfos(vector* domains) override; + + bool setMaster(const DNSName &domain, const string &ip) override; + bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) override; + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override + { + // std::cout<<"Request for metadata items for zone "< > metas; + if(getAllDomainMetadata(name, metas)) { + for(const auto& m : metas) { + if(m.first == kind) { + meta = m.second; + return true; + } + } + return true; + } + return false; + } + + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; + void setFresh(uint32_t domain_id) override; + void setNotified(uint32_t id, uint32_t serial) override; + bool setAccount(const DNSName &domain, const std::string& account) override; + bool deleteDomain(const DNSName &domain) override; + + bool getDomainKeys(const DNSName& name, std::vector& keys) override; + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + + // TSIG + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; + bool deleteTSIGKey(const DNSName& name) override; + bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + + + // DNSSEC + + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; + + virtual bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) override; + + bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype=QType::ANY) override; + + bool updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) override; + + bool doesDNSSEC() override + { + return true; + } +private: + + struct compoundOrdername + { + std::string operator()(uint32_t id, const DNSName& t, uint16_t qtype) + { + std::string ret = operator()(id, t); + uint16_t qt = htons(qtype); + ret.append((char*)&qt, 2); + return ret; + } + std::string operator()(uint32_t id, const DNSName& t) + { + std::string ret = operator()(id); + ret += keyConv(t); + ret.append(1, (char)0); // this means '00' really ends the zone + return ret; + } + std::string operator()(uint32_t id) + { + std::string ret; + id = htonl(id); + ret.assign((char*)&id, 4); + return ret; + } + + std::string operator()(const DNSResourceRecord& rr) + { + return operator()(rr.domain_id, rr.qname, rr.qtype.getCode()); + } + + static uint32_t getDomainID(const string_view& key) + { + uint32_t ret; + memcpy(&ret, &key[0], sizeof(ret)); + return ntohl(ret); + } + + static DNSName getQName(const string_view& key) + { + /* www.ds9a.nl -> nl0ds9a0www0 + root -> 0 <- we need this to keep lmdb happy + nl -> nl0 */ + DNSName ret; + auto iter = key.cbegin() + 4; + auto end = key.cend() - 2; + while(iter < end) { + auto startpos = iter; + while(iter != end && *iter) + ++iter; + if(iter == startpos) + break; + string part(&*startpos, iter-startpos); + ret.prependRawLabel(part); + // cout << "Prepending part: "< + > tdomains_t; + + + typedef TypedDBI + > tmeta_t; + + typedef TypedDBI + > tkdb_t; + + typedef TypedDBI + > ttsig_t; + + int d_shards; + int d_asyncFlag; + + struct RecordsDB + { + shared_ptr env; + MDBDbi dbi; + }; + + struct RecordsROTransaction + { + RecordsROTransaction(MDBROTransaction&& intxn) : txn(std::move(intxn)) + {} + shared_ptr db; + MDBROTransaction txn; + }; + struct RecordsRWTransaction + { + RecordsRWTransaction(MDBRWTransaction&& intxn) : txn(std::move(intxn)) + {} + shared_ptr db; + MDBRWTransaction txn; + }; + + vector d_trecords;; + + std::shared_ptr d_getcursor; + + shared_ptr d_tdomains; + shared_ptr d_tmeta; + shared_ptr d_tkdb; + shared_ptr d_ttsig; + + shared_ptr d_rotxn; // for lookup and list + shared_ptr d_rwtxn; // for feedrecord within begin/aborttransaction + std::shared_ptr getRecordsRWTransaction(uint32_t id); + std::shared_ptr getRecordsROTransaction(uint32_t id, std::shared_ptr rwtxn = nullptr); + int genChangeDomain(const DNSName& domain, std::function func); + int genChangeDomain(uint32_t id, std::function func); + void deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype=QType::ANY); + + bool get_list(DNSZoneRecord &rr); + bool get_lookup(DNSZoneRecord &rr); + bool d_inlist{false}; + QType d_lookuptype; // for get after lookup + std::string d_matchkey; + int32_t d_lookupdomainid; // for get after lookup + DNSName d_lookupqname; + DNSName d_lookupdomain; + + DNSName d_transactiondomain; + uint32_t d_transactiondomainid; + bool d_dolog; + DTime d_dtime; // used only for logging +}; diff --git a/modules/lua2backend/Makefile.am b/modules/lua2backend/Makefile.am new file mode 100644 index 0000000..841abe3 --- /dev/null +++ b/modules/lua2backend/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS += $(LUA_CFLAGS) \ + -I$(top_srcdir)/ext/luawrapper/include + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +pkglib_LTLIBRARIES = liblua2backend.la + +liblua2backend_la_SOURCES = \ + lua2backend.cc lua2backend.hh \ + lua2api2.hh lua2api2.cc + +liblua2backend_la_LDFLAGS = -module -avoid-version +liblua2backend_la_LIBADD = $(LUA_LIBS) diff --git a/modules/lua2backend/Makefile.in b/modules/lua2backend/Makefile.in new file mode 100644 index 0000000..8081745 --- /dev/null +++ b/modules/lua2backend/Makefile.in @@ -0,0 +1,831 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/lua2backend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +liblua2backend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_liblua2backend_la_OBJECTS = lua2backend.lo lua2api2.lo +liblua2backend_la_OBJECTS = $(am_liblua2backend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +liblua2backend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(liblua2backend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(liblua2backend_la_SOURCES) +DIST_SOURCES = $(liblua2backend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(LUA_CFLAGS) \ + -I$(top_srcdir)/ext/luawrapper/include +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = OBJECTFILES OBJECTLIBS +pkglib_LTLIBRARIES = liblua2backend.la +liblua2backend_la_SOURCES = \ + lua2backend.cc lua2backend.hh \ + lua2api2.hh lua2api2.cc + +liblua2backend_la_LDFLAGS = -module -avoid-version +liblua2backend_la_LIBADD = $(LUA_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/lua2backend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/lua2backend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +liblua2backend.la: $(liblua2backend_la_OBJECTS) $(liblua2backend_la_DEPENDENCIES) $(EXTRA_liblua2backend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liblua2backend_la_LINK) -rpath $(pkglibdir) $(liblua2backend_la_OBJECTS) $(liblua2backend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua2api2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua2backend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/lua2backend/OBJECTFILES b/modules/lua2backend/OBJECTFILES new file mode 100644 index 0000000..79d15f2 --- /dev/null +++ b/modules/lua2backend/OBJECTFILES @@ -0,0 +1 @@ +lua2backend.lo lua2api2.lo diff --git a/modules/lua2backend/OBJECTLIBS b/modules/lua2backend/OBJECTLIBS new file mode 100644 index 0000000..9094a02 --- /dev/null +++ b/modules/lua2backend/OBJECTLIBS @@ -0,0 +1 @@ +$(LUA_LIBS) diff --git a/modules/lua2backend/lua2api2.cc b/modules/lua2backend/lua2api2.cc new file mode 100644 index 0000000..df53d46 --- /dev/null +++ b/modules/lua2backend/lua2api2.cc @@ -0,0 +1,30 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTAPILITY 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "lua2backend.hh" + +Lua2BackendAPIv2::~Lua2BackendAPIv2() { + if (f_deinit) + f_deinit(); +} diff --git a/modules/lua2backend/lua2api2.hh b/modules/lua2backend/lua2api2.hh new file mode 100644 index 0000000..2acbf89 --- /dev/null +++ b/modules/lua2backend/lua2api2.hh @@ -0,0 +1,419 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTAPILITY 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#ifndef LUA2API_2_HH +#define LUA2API_2_HH 1 + +#include "boost/lexical_cast.hpp" +#include "boost/algorithm/string/join.hpp" +#include "pdns/arguments.hh" + +class Lua2BackendAPIv2 : public DNSBackend, AuthLua4 { +private: + typedef std::function init_call_t; + typedef std::function deinit_call_t; + + typedef std::vector > lookup_context_t; + + typedef std::vector > > > > lookup_result_t; + typedef std::function lookup_call_t; + + typedef boost::variant list_result_t; + typedef std::function list_call_t; + + typedef vector > > > domaininfo_result_t; + typedef boost::variant get_domaininfo_result_t; + typedef vector > get_all_domains_result_t; + typedef std::function get_domaininfo_call_t; + typedef std::function get_all_domains_call_t; + + typedef vector > domain_metadata_result_t; + typedef boost::variant get_domain_metadata_result_t; + typedef boost::variant > > get_all_domain_metadata_result_t; + typedef std::function get_domain_metadata_call_t; + typedef std::function get_all_domain_metadata_call_t; + + typedef vector > > keydata_result_t; + typedef boost::variant > > get_domain_keys_result_t; + typedef std::function get_domain_keys_call_t; + + typedef std::vector > > before_and_after_names_result_t; + typedef boost::variant get_before_and_after_names_absolute_result_t; + typedef std::function get_before_and_after_names_absolute_call_t; + + typedef std::function set_notified_call_t; + + typedef std::function direct_backend_cmd_call_t; +public: + Lua2BackendAPIv2(const string& suffix) { + setArgPrefix("lua2"+suffix); + d_debug_log = mustDo("query-logging"); + prepareContext(); + loadFile(getArg("filename")); + } + + ~Lua2BackendAPIv2(); + + #define logCall(func, var) { if (d_debug_log) { g_log<readVariable>("dns_lookup").get_value_or(0); + f_list = d_lw->readVariable>("dns_list").get_value_or(0); + f_get_all_domains = d_lw->readVariable>("dns_get_all_domains").get_value_or(0); + f_get_domaininfo = d_lw->readVariable>("dns_get_domaininfo").get_value_or(0); + f_get_domain_metadata = d_lw->readVariable>("dns_get_domain_metadata").get_value_or(0); + f_get_all_domain_metadata = d_lw->readVariable>("dns_get_all_domain_metadata").get_value_or(0); + f_get_domain_keys = d_lw->readVariable>("dns_get_domain_keys").get_value_or(0); + f_get_before_and_after_names_absolute = d_lw->readVariable>("dns_get_before_and_after_names_absolute").get_value_or(0); + f_set_notified = d_lw->readVariable>("dns_set_notified").get_value_or(0); + + auto init = d_lw->readVariable>("dns_init").get_value_or(0); + if (init) + init(); + + f_deinit = d_lw->readVariable>("dns_deinit").get_value_or(0); + + if (f_lookup == nullptr) + throw PDNSException("dns_lookup missing"); + + /* see if dnssec support is wanted */ + d_dnssec = d_lw->readVariable>("dns_dnssec").get_value_or(false); + if (d_dnssec) { + if (f_get_domain_metadata == nullptr) + throw PDNSException("dns_dnssec is true but dns_get_domain_metadata is missing"); + if (f_get_before_and_after_names_absolute == nullptr) + throw PDNSException("dns_dnssec is true but dns_get_before_and_after_names_absolute is missing"); + /* domain keys is not strictly speaking necessary for dnssec backend */ + if (f_get_domain_keys == nullptr) + g_log<(item.second)); + else if (item.second.which() == 3) + rec.qtype = boost::get(item.second); + else if (item.second.which() == 4) + rec.qtype = boost::get(item.second); + else + throw PDNSException("Unsupported value for type"); + } else if (item.first == "name") { + if (item.second.which() == 3) + rec.qname = DNSName(boost::get(item.second)); + else if (item.second.which() == 2) + rec.qname = boost::get(item.second); + else + throw PDNSException("Unsupported value for name"); + } else if (item.first == "domain_id") + rec.domain_id = boost::get(item.second); + else if (item.first == "auth") + rec.auth = boost::get(item.second); + else if (item.first == "last_modified") + rec.last_modified = static_cast(boost::get(item.second)); + else if (item.first == "ttl") + rec.ttl = boost::get(item.second); + else if (item.first == "content") + rec.setContent(boost::get(item.second)); + else if (item.first == "scopeMask") + rec.scopeMask = boost::get(item.second); + else + g_log<getRemote().toString()}); + ctx.emplace_back(lookup_context_t::value_type{"real_source_address", p->getRealRemote().toString()}); + } + + logCall("lookup", "qtype="<readVariable>(cmd).get_value_or(0); + if (f == nullptr) { + return cmd + "not found"; + } + logCall(cmd, "parameter="<(item.second); + else if (item.first == "last_check") + di.last_check = static_cast(boost::get(item.second)); + else if (item.first == "masters") + for(const auto& master: boost::get>(item.second)) + di.masters.push_back(ComboAddress(master, 53)); + else if (item.first == "id") + di.id = static_cast(boost::get(item.second)); + else if (item.first == "notified_serial") + di.notified_serial = static_cast(boost::get(item.second)); + else if (item.first == "serial") + di.serial = static_cast(boost::get(item.second)); + else if (item.first == "kind") + di.kind = DomainInfo::stringToKind(boost::get(item.second)); + else + g_log<push_back(di); + } + } + + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override { + if (f_get_all_domain_metadata == nullptr) + return false; + + logCall("get_all_domain_metadata","name="< > >(result)) { + meta[row.first].clear(); + for(const auto& item: row.second) + meta[row.first].push_back(item.second); + logResult("kind="<& meta) override { + if (f_get_domain_metadata == nullptr) + return false; + + logCall("get_domain_metadata","name="<(result)) + meta.push_back(item.second); + + logResult("value="<& keys) override { + if (f_get_domain_keys == nullptr) + return false; + + logCall("get_domain_keys","name="< > >(result)) { + DNSBackend::KeyData key; + for(const auto& item: row.second) { + if (item.first == "content") + key.content = boost::get(item.second); + else if (item.first == "id") + key.id = static_cast(boost::get(item.second)); + else if (item.first == "flags") + key.flags = static_cast(boost::get(item.second)); + else if (item.first == "active") + key.active = boost::get(item.second); + else + g_log<(result); + if (row.size() != 3) { + g_log<(item.second)); + else + value = DNSName(boost::get(item.second)); + if (item.first == "unhashed") + unhashed = value; + else if (item.first == "before") + before = value; + else if (item.first == "after") + after = value; + else { + g_log<&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/luabackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libluabackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libluabackend_la_OBJECTS = dnssec.lo lua_functions.lo luabackend.lo \ + master.lo minimal.lo private.lo reload.lo slave.lo \ + supermaster.lo +libluabackend_la_OBJECTS = $(am_libluabackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libluabackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libluabackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libluabackend_la_SOURCES) +DIST_SOURCES = $(libluabackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(LUA_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = OBJECTFILES OBJECTLIBS +pkglib_LTLIBRARIES = libluabackend.la +libluabackend_la_SOURCES = \ + dnssec.cc \ + lua_functions.cc lua_functions.hh \ + luabackend.cc luabackend.hh \ + master.cc \ + minimal.cc \ + private.cc \ + reload.cc \ + slave.cc \ + supermaster.cc + +libluabackend_la_LDFLAGS = -module -avoid-version +libluabackend_la_LIBADD = $(LUA_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/luabackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/luabackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libluabackend.la: $(libluabackend_la_OBJECTS) $(libluabackend_la_DEPENDENCIES) $(EXTRA_libluabackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libluabackend_la_LINK) -rpath $(pkglibdir) $(libluabackend_la_OBJECTS) $(libluabackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua_functions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/luabackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/master.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/private.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reload.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slave.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/supermaster.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/luabackend/OBJECTFILES b/modules/luabackend/OBJECTFILES new file mode 100644 index 0000000..0906c91 --- /dev/null +++ b/modules/luabackend/OBJECTFILES @@ -0,0 +1 @@ +luabackend.lo minimal.lo reload.lo lua_functions.lo master.lo private.lo slave.lo supermaster.lo dnssec.lo \ No newline at end of file diff --git a/modules/luabackend/OBJECTLIBS b/modules/luabackend/OBJECTLIBS new file mode 100644 index 0000000..9094a02 --- /dev/null +++ b/modules/luabackend/OBJECTLIBS @@ -0,0 +1 @@ +$(LUA_LIBS) diff --git a/modules/luabackend/README b/modules/luabackend/README new file mode 100644 index 0000000..312d8e3 --- /dev/null +++ b/modules/luabackend/README @@ -0,0 +1,191 @@ +==================================== +This is the luabackend for PowerDNS! +==================================== + +Note: shortly before the 3.2 release of PowerDNS, Fredrik Danerklinkt +(author of this Luabackend) opened https://github.com/fredan/luabackend +and is doing development there. + + +http://www.lua.org for more information about what Lua really is. + + +This backend is just a "glue" between PowerDNS and your own Lua application. + +What this means is that you can not have a working setup that can serve you +dns-questions directly from start. What you need to do is to program your own +backend completely in Lua! Which database server to use etc is now up to you! + +What you have here is the possibility to make your own "dns-server" without the +knowledge of programming in c/c++. + +There is one thing that needs to be said. Remember that each thread +PowerDNS launches of this backend is completely different so they cannot +share information between each other! + +You will need some kind of a database that can be shared for this. + +All the functionnames that PowerDNS accept for a backend should be the same +in your Lua script, in lowercase. Also, the parameters should be in the same +order. Where there is a structure in c/c++ there is a table in the Lua backend. +This is also true for return values. A few functions expect that you return a +table in a table. + + +============= +NEW FUNCTIONS +============= + +There is a couple of new functions for you to use in Lua: + +---------------------------------------- +logger(log_facility, "your", "messages") +---------------------------------------- + +All these log_facilities is available: +log_all, log_ntlog, log_alert, log_critical, log_error, log_warning, log_notice, +log_info, log_debug, log_none + + +----------- +dnspacket() +----------- + +This will give you back three parameters with +remote_ip, remote_port and local_ip in that order. + +Can only be used in the functions list() and getsoa(). + + +------------------------ +getarg("your_parameter") +------------------------ + +This one tries to get the value of the name "lua-your_parameter" from the +pdns.conf file. + + +------------------------ +mustdo("your_parameter") +------------------------ + +This is the same as getarg() but return a boolean instead of a string. + + +You also have all the different QTypes in a table called 'QTypes'. + + +==================== +WHAT HAS BEEN TESTED +==================== + +The only functionality of the minimal functions except zone-transfer has +been tested. + +In the included powerdns-luabackend.lua file there is a example of how +this can be done. Note that this is more or less a static example since +there is no possibility for each thread to know when something has changed. + +However, you can run 'pdns_control reload' and it should reload the hole thing +from scratch (does not work for the moment, PowerDNS only calls two thread with +the reload command - not all of them). + + +=========================================== +WHAT YOU WILL FIND UNDER THE TEST DIRECTORY +=========================================== + +The script 'pdns' is used to test the server on the ip address '127.0.0.1' with +the port 5300. You should be able to run the following test with the included +'powerdns-luabackend.lua' file: + +$dig any www.test.com @127.0.0.1 -p5300 +multiline +; <<>> DiG 9.7.3 <<>> any www.test.com @127.0.0.1 -p5300 +multiline +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1001 +;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 +;; WARNING: recursion requested but not available + +;; QUESTION SECTION: +;www.test.com. IN ANY + +;; ANSWER SECTION: +www.test.com. 120 IN CNAME host.test.com. +host.test.com. 120 IN A 10.11.12.13 +host.test.com. 120 IN AAAA 1:2:3:4:5:6:7:8 + +;; Query time: 1 msec +;; SERVER: 127.0.0.1#5300(127.0.0.1) +;; WHEN: Thu Jun 2 22:19:56 2011 +;; MSG SIZE rcvd: 93 + + +============================= +OPTIONS IN THE CONFIGURE FILE +============================= + +The default values is: + +lua-filename = powerdns-luabackend.lua +lua-logging-query = no + +You can also override all the default functionsnames for the luafunctions if you +want. The prefix is lua-f_=mynewfunction. For example: + +lua-f_lookup = mynewfunction + +will call the function 'mynewfunction' for the lookup-routine. + +If you want your own configuration parameters you can have that too. +Just call the function getarg("my_parameter") and it will return the value +of 'lua-my_parameter'. For boolean you use the function mustdo("my_parameter"). + + +============================== +YOUR OWN ERROR FUNCTION IN LUA +============================== + +You can have an error function in Lua when Lua gives back a error. + +First make your error function then you put this in pdns.conf: + +lua-f_exec_error = + + +====== +DNSSEC +====== + +You can have full dnssec support in our Lua application. You should note the +following regarding this: + +You don't have to implement the function 'updateDNSSECOrderAndAuth' since the +default code will work correctly for you via the backend itself. + +The functions activateDomainKey and deactivateDomainKey can be implemented via a +new function called updateDomainKey, which has three parameters (the other two +has only two parameters) where the third is a boolean which is true or false +depending on which function that was called from the beginning. + + +======================= +INFORMATION FOR LOGGING +======================= + +If you have the parameter 'query-logging' or 'lua-logging-query' set to +true/yes/on, then you will see what is happening in each function when PowerDNS +calls them. + +This can, hopefully, help you with some debugging if you run into some kind of +trouble with your Lua application. + + +=============== +ASKING QUESTION +=============== + +You can send question about this backend to >dev/null first and if you don't get any +answer from that you can try to send them to me at fredan-pdns@fredan.org + +Fredrik Danerklint. \ No newline at end of file diff --git a/modules/luabackend/dnssec.cc b/modules/luabackend/dnssec.cc new file mode 100644 index 0000000..076df6f --- /dev/null +++ b/modules/luabackend/dnssec.cc @@ -0,0 +1,603 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + + +bool LUABackend::updateDNSSECOrderAndAuth(uint32_t domain_id, const DNSName& zonename, const DNSName& qname, bool auth) { + + if(f_lua_updatednssecorderandauth == 0) { + + if(logging) + g_log << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) domain_id: '" << domain_id << "' zonename: '" << zonename << "' qname: '" << qname << "' auth: '" << auth << "'" << endl; + + string ins=qname.makeRelative(zonename).makeLowerCase().labelReverse().toString(" ", false); + return this->updateDNSSECOrderAndAuthAbsolute(domain_id, qname, ins, auth); + } + + if(logging) + g_log << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) BEGIN domain_id: '" << domain_id << "' zonename: '" << zonename << "' qname: '" << qname << "' auth: '" << auth << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauth); + + lua_pushinteger(lua, domain_id); + lua_pushstring(lua, zonename.toString().c_str()); + lua_pushstring(lua, qname.toString().c_str()); + lua_pushboolean(lua, auth); + + if(lua_pcall(lua, 4, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) END" << endl; + + return ok; +} + +bool LUABackend::updateDNSSECOrderNameAndAuth(unsigned int, DNSName const&, DNSName const&, bool, unsigned short) +{ + return false; +} + +bool LUABackend::updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const DNSName& qname, const std::string& ordername, bool auth) { + + if(f_lua_updatednssecorderandauthabsolute == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(updateDNSSECOrderAndAuthAbsolute) BEGIN domain_id: '" << domain_id << "' qname: '" << qname << "' ordername: '" << ordername << "' auth: '" << auth << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauthabsolute); + + lua_pushinteger(lua, domain_id); + lua_pushstring(lua, qname.toString().c_str()); + lua_pushstring(lua, ordername.c_str()); + lua_pushboolean(lua, auth); + + if(lua_pcall(lua, 4, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(updateDNSSECOrderAndAuthAbsolute) END" << endl; + + return ok; +} + +bool LUABackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) { + + if(f_lua_getbeforeandafternamesabsolute == 0) + return false; + + unhashed.clear(); + before.clear(); + after.clear(); + + if(logging) + g_log << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) BEGIN id: '" << id << "' qname: '" << qname << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauthabsolute); + + lua_pushinteger(lua, id); + lua_pushstring(lua, qname.toString().c_str()); + + if(lua_pcall(lua, 2, 3, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = returnedwhat == LUA_TSTRING; + + if (!ok) { + if(logging) + g_log << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) ERROR!" << endl; + + return false; + } + + //will this be correct since we are poping one at the time? + unhashed = DNSName(lua_tostring(lua, -1)); + lua_pop(lua, 1); + + returnedwhat = lua_type(lua, -1); + ok = (returnedwhat == LUA_TSTRING) && ok; + + before = DNSName(lua_tostring(lua, -1)); + lua_pop(lua, 1); + + returnedwhat = lua_type(lua, -1); + ok = (returnedwhat == LUA_TSTRING) && ok; + + after = DNSName(lua_tostring(lua, -1)); + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) END unhashed: '" << unhashed << "' before: '" << before << "' after: '" << after << "' " << endl; + + return ok; +} + +bool LUABackend::updateDomainKey(const DNSName& name, unsigned int &id, bool toowhat ) { + + if(f_lua_updatedomainkey == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(updateDomainKey) BEGIN name: '" << name << "' id: '" << id << "' toowhat: '" << toowhat << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatedomainkey); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushinteger(lua, id); + lua_pushboolean(lua, toowhat); + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(updateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::activateDomainKey(const DNSName& name, unsigned int id) { + + if(f_lua_activatedomainkey == 0) + return updateDomainKey(name, id, true); + + if(logging) + g_log << Logger::Info << backend_name << "(activateDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_activatedomainkey); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushinteger(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(activateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::deactivateDomainKey(const DNSName& name, unsigned int id) { + + if(f_lua_deactivatedomainkey == 0) + return updateDomainKey(name, id, false); + + if(logging) + g_log << Logger::Info << backend_name << "(deactivateDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_deactivatedomainkey); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushinteger(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(deactivateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::removeDomainKey(const DNSName& name, unsigned int id) { + + if(f_lua_removedomainkey == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(removeDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_removedomainkey); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushinteger(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(removeDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) { +// there is no logging function in pdnsutil when running this routine? + +//key = id, flags, active, content + + if(f_lua_adddomainkey == 0) + return false; + + if(logging) + //g_log << Logger::Info << backend_name << "(addDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + cerr << backend_name << "(addDomainKey) BEGIN name: '" << name << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_adddomainkey); + + lua_pushstring(lua, name.toString().c_str()); + + lua_newtable(lua); + + lua_pushliteral(lua, "flags"); + lua_pushinteger(lua, key.flags); + lua_settable(lua, -3); + + lua_pushliteral(lua, "active"); + lua_pushboolean(lua, key.active); + lua_settable(lua, -3); + + lua_pushliteral(lua, "content"); + lua_pushstring(lua, key.content.c_str()); + lua_settable(lua, -3); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + int ok = -1; + + if (returnedwhat == LUA_TNUMBER) + ok = lua_tonumber(lua, -1); + + lua_pop(lua, 1); + + if(logging) + cerr << backend_name << "(addDomainKey) END" << endl; + + return ok >= 0; +} + +bool LUABackend::getDomainKeys(const DNSName& name, std::vector& keys) { + if(f_lua_getdomainkeys == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(getDomainKeys) BEGIN name: '" << name << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomainkeys); + + lua_pushstring(lua, name.toString().c_str()); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1); + if(logging) + g_log << Logger::Info << backend_name << "(getDomainKeys) ERROR!" << endl; + + return false; + } + + lua_pushnil(lua); + + int j = 0; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TTABLE) { + KeyData kd; + bool i,f,a,c = false; + + i = getValueFromTable(lua, "id", kd.id); + f = getValueFromTable(lua, "flags", kd.flags); + a = getValueFromTable(lua, "active", kd.active); + c = getValueFromTable(lua, "content", kd.content); + + if (i && f && a && c) { + j++; + keys.push_back(kd); + } + } + + lua_pop(lua,1); + } + + if(logging) + g_log << Logger::Info << backend_name << "(getDomainKeys) END" << endl; + + return j > 0; +} + +bool LUABackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) { + + if(f_lua_gettsigkey == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(getTSIGKey) BEGIN name: '" << name << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_gettsigkey); + + lua_pushstring(lua, name.toString().c_str()); + + if(lua_pcall(lua, 1, 2, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + if ( (lua_type(lua, -1) != LUA_TSTRING) && (lua_type(lua, -2) != LUA_TSTRING) ) { + lua_pop(lua, 2); + if(logging) + g_log << Logger::Info << backend_name << "(getTSIGKey) ERROR" << endl; + return false; + } + + string a,c = ""; + + a = lua_tostring(lua, -1); + lua_pop(lua, 1); + + c = lua_tostring(lua, -1); + lua_pop(lua, 1); + + *algorithm = DNSName(a); + *content = c; + + if(logging) + g_log << Logger::Info << backend_name << "(getTSIGKey) END" << endl; + + return true; +} + +bool LUABackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) { + + if(f_lua_setdomainmetadata == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(setDomainMetadata) BEGIN name: '" << name << "' kind: '" << kind << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setdomainmetadata); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushstring(lua, kind.c_str()); + + lua_newtable(lua); + + std::vector::const_iterator i; + + int c = 0; + + for(i = meta.begin(); ic_str()); + lua_settable(lua, -3); + } + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + g_log << Logger::Info << backend_name << "(setDomainMetadata) END" << endl; + + return ok; + +} + +bool LUABackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { + if(f_lua_getdomainmetadata == 0) + return false; + + if(logging) + g_log << Logger::Info << backend_name << "(getDomainMetadata) BEGIN name: '" << name << "' kind: '" << kind << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomainmetadata); + + lua_pushstring(lua, name.toString().c_str()); + lua_pushstring(lua, kind.c_str()); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + if (lua_type(lua, -1) != LUA_TTABLE) + return false; + + lua_pushnil(lua); + + int j = 0; + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) { + j++; + meta.push_back(lua_tostring(lua, -1)); + } + + lua_pop(lua,1); + } + + if(logging) + g_log << Logger::Info << backend_name << "(getDomainMetadata) END" << endl; + + return j > 0; + +} + +void LUABackend::alsoNotifies(const DNSName& domain, set *ips) { + + if(f_lua_alsonotifies == 0) + return; + + if(logging) + g_log << Logger::Info << backend_name << "(alsonotifies) BEGIN domain: '" << domain << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_alsonotifies); + + lua_pushstring(lua, domain.toString().c_str()); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + if (lua_type(lua, -1) != LUA_TTABLE) + return; + + lua_pushnil(lua); + + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) { + ips->insert(lua_tostring(lua, -1)); + } + + lua_pop(lua,1); + } + + if(logging) + g_log << Logger::Info << backend_name << "(alsoNotifies) END" << endl; + + return; + +} diff --git a/modules/luabackend/lua_functions.cc b/modules/luabackend/lua_functions.cc new file mode 100644 index 0000000..cd57a00 --- /dev/null +++ b/modules/luabackend/lua_functions.cc @@ -0,0 +1,376 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define LUABACKEND_EXTERN_F_HH + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/dnspacket.hh" + +#include +#include +using namespace std; + +// It seems we don't want the coroutine standard library so we can't use +// luaL_openlibs(). FIXME: is the coroutine library really that bad? +const luaL_Reg lualibs[] = { +#if LUA_VERSION_NUM < 502 + {"", luaopen_base}, +#else + {"_G", luaopen_base}, +#endif + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, +#if LUA_VERSION_NUM == 502 || defined(LUA_COMPAT_BITLIB) + {LUA_BITLIBNAME, luaopen_bit32}, +#endif +#if LUA_VERSION_NUM == 503 + {LUA_UTF8LIBNAME, luaopen_utf8}, +#endif +// {LUA_COLIBNAME, luaopen_coroutine}, +#ifdef USE_LUAJIT + {"bit", luaopen_bit}, + {"jit", luaopen_jit}, +#endif + {NULL, NULL} +}; + +int my_lua_panic (lua_State *lua) { + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + assert(lua == lb->lua); + + stringstream e; + + e << lb->backend_name << "LUA PANIC! '" << lua_tostring(lua,-1) << "'" << endl; + + throw LUAException (e.str()); + + return 0; +} + +int l_arg_get (lua_State *lua) { + int i = lua_gettop(lua); + if (i < 1) + return 0; + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + string a = lua_tostring(lua, 1); + + if (::arg().isEmpty(a)) + lua_pushnil(lua); + else + lua_pushstring(lua, lb->my_getArg(a).c_str()); + + return 1; +} + +int l_arg_mustdo (lua_State *lua) { + int i = lua_gettop(lua); + if (i < 1) + return 0; + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + string a = lua_tostring(lua, 1); + + if (::arg().isEmpty(a)) + lua_pushnil(lua); + else + lua_pushboolean(lua, lb->my_mustDo(a)); + + return 1; +} + +int l_dnspacket (lua_State *lua) { + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + if (lb->dnspacket == NULL) { + lua_pushnil(lua); + + return 1; + } + + lua_pushstring(lua, lb->dnspacket->getRemote().toString().c_str()); + lua_pushinteger(lua, lb->dnspacket->getRemotePort()); + lua_pushstring(lua, lb->dnspacket->getLocal().toString().c_str()); + lua_pushstring(lua, lb->dnspacket->getRealRemote().toString().c_str()); + + return 4; +} + +int l_logger (lua_State *lua) { +// assert(lua == lb->lua); + + int i = lua_gettop(lua); + if (i < 1) + return 0; + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + int log_level = 0; + stringstream s; + int j; + const char *ss; + + log_level = lua_tointeger(lua, 1); + + string space = ""; + + for(j=2; j<=i; j++) { + ss = lua_tostring(lua, j); + s << space << ss; + space = " "; + } + + g_log.log(lb->backend_name + s.str(), (Logger::Urgency) log_level); + + return 0; +} + +void register_lua_functions(lua_State *lua) { + lua_gc(lua, LUA_GCSTOP, 0); // stop collector during initialization + + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { +#if LUA_VERSION_NUM < 502 + lua_pushcfunction(lua, lib->func); + lua_pushstring(lua, lib->name); + lua_call(lua, 1, 0); +#else + luaL_requiref(lua, lib->name, lib->func, 1); + lua_pop(lua, 1); /* remove lib */ +#endif + } + + lua_gc(lua, LUA_GCRESTART, 0); + + lua_pushinteger(lua, Logger::All); + lua_setglobal(lua, "log_all"); + + lua_pushinteger(lua, Logger::Alert); + lua_setglobal(lua, "log_alert"); + + lua_pushinteger(lua, Logger::Critical); + lua_setglobal(lua, "log_critical"); + + lua_pushinteger(lua, Logger::Error); + lua_setglobal(lua, "log_error"); + + lua_pushinteger(lua, Logger::Warning); + lua_setglobal(lua, "log_warning"); + + lua_pushinteger(lua, Logger::Notice); + lua_setglobal(lua, "log_notice"); + + lua_pushinteger(lua, Logger::Info); + lua_setglobal(lua, "log_info"); + + lua_pushinteger(lua, Logger::Debug); + lua_setglobal(lua, "log_debug"); + + lua_pushinteger(lua, Logger::None); + lua_setglobal(lua, "log_none"); + + lua_pushcfunction(lua, l_dnspacket); + lua_setglobal(lua, "dnspacket"); + + lua_pushcfunction(lua, l_logger); + lua_setglobal(lua, "logger"); + + lua_pushcfunction(lua, l_arg_get); + lua_setglobal(lua, "getarg"); + + lua_pushcfunction(lua, l_arg_mustdo); + lua_setglobal(lua, "mustdo"); + + lua_newtable(lua); + for(vector::const_iterator iter = QType::names.begin(); iter != QType::names.end(); ++iter) { + lua_pushinteger(lua, iter->second); + lua_setfield(lua, -2, iter->first.c_str()); + } + lua_pushinteger(lua, 3); + lua_setfield(lua, -2, "NXDOMAIN"); + lua_setglobal(lua, "QTypes"); +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, string& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_tostring(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, DNSName& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = DNSName(lua_tostring(lua, -1)); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, uint32_t key, string& value) { + lua_pushinteger(lua, key); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_tostring(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +#if !(defined(__i386__) && defined(__FreeBSD__)) +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, time_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (time_t)lua_tonumber(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} +#endif + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, uint32_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (uint32_t)lua_tointeger(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, uint16_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (uint16_t)lua_tointeger(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, uint8_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (uint8_t)lua_tointeger(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, int& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (int)lua_tointeger(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, bool& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_toboolean(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} diff --git a/modules/luabackend/lua_functions.hh b/modules/luabackend/lua_functions.hh new file mode 100644 index 0000000..eb95d24 --- /dev/null +++ b/modules/luabackend/lua_functions.hh @@ -0,0 +1,30 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LUABACKEND_EXTERN_F_HH +#define LUABACKEND_EXTERN_F_HH + +//extern LUABackend* lb; +extern int my_lua_panic(lua_State* lua); +extern void register_lua_functions(lua_State* lua); + +#endif diff --git a/modules/luabackend/luabackend.cc b/modules/luabackend/luabackend.cc new file mode 100644 index 0000000..57d059c --- /dev/null +++ b/modules/luabackend/luabackend.cc @@ -0,0 +1,68 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" +#include "pdns/logger.hh" + +/* SECOND PART */ + +class LUAFactory : public BackendFactory +{ +public: + LUAFactory() : BackendFactory("lua") {} + + void declareArguments(const string &suffix="") + { + + declare(suffix,"filename","Filename of the script for lua backend","powerdns-luabackend.lua"); + declare(suffix,"logging-query","Logging of the LUA Backend","no"); + + } + + DNSBackend *make(const string &suffix="") + { + return new LUABackend(suffix); + } + +}; + +/* THIRD PART */ + +class LUALoader +{ +public: + LUALoader() + { + BackendMakers().report(new LUAFactory); + + g_log << Logger::Info << "[luabackend] This is the lua backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + +static LUALoader luaLoader; diff --git a/modules/luabackend/luabackend.hh b/modules/luabackend/luabackend.hh new file mode 100644 index 0000000..38971a4 --- /dev/null +++ b/modules/luabackend/luabackend.hh @@ -0,0 +1,250 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LUABACKEND_HH +#define LUABACKEND_HH + +#include "lua.hpp" + +//extern "C" { +//#include "lua.h" +//#include "lualib.h" +//#include "lauxlib.h" +//} + +#include "pdns/dnsbackend.hh" + +#include +using std::string; + + + + +class LUAException { +public: + LUAException(const string &ex) : what(ex){} + string what; +}; + +class LUABackend : public DNSBackend { + +public: + +// MINIMAL BACKEND + + LUABackend(const string &suffix=""); + ~LUABackend(); + bool list(const DNSName &target, int domain_id, bool include_disabled=false) override; + void lookup(const QType &qtype, const DNSName &qname, DNSPacket *p, int domain_id) override; + bool get(DNSResourceRecord &rr) override; + //! fills the soadata struct with the SOA details. Returns false if there is no SOA. + bool getSOA(const DNSName &name, SOAData &soadata) override; + + +// MASTER BACKEND + + void getUpdatedMasters(vector* domains) override; + void setNotified(uint32_t id, uint32_t serial) override; + + +// SLAVE BACKEND + + bool getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial=true) override; + void getUnfreshSlaveInfos(vector* domains) override; + void setFresh(uint32_t id) override; + + bool startTransaction(const DNSName &qname, int id) override; + bool commitTransaction() override; + bool abortTransaction() override; + bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + + +// SUPERMASTER BACKEND + + bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) override; + bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) override; + + +// DNSSEC BACKEND + + //! get a list of IP addresses that should also be notified for a domain + void alsoNotifies(const DNSName &domain, set *ips) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; + + bool getDomainKeys(const DNSName& name, std::vector& keys) override ; + bool removeDomainKey(const DNSName& name, unsigned int id) override ; + bool activateDomainKey(const DNSName& name, unsigned int id) override ; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override ; + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override ; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override ; + bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const DNSName& qname, const std::string& ordername, bool auth); + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; + bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype=QType::ANY) override; + bool updateDNSSECOrderAndAuth(uint32_t domain_id, const DNSName& zonename, const DNSName& qname, bool auth); +// OTHER + void reload() override ; + void rediscover(string* status=0) override ; + + + string backend_name; + lua_State *lua; + DNSPacket *dnspacket; + + //private.cc + string my_getArg(string a); + bool my_mustDo(string a); + +private: + + pthread_t backend_pid; + unsigned int backend_count{0}; + + int f_lua_exec_error; + + //minimal functions.... + int f_lua_list; + int f_lua_lookup; + int f_lua_get; + int f_lua_getsoa; + + //master functions.... + int f_lua_getupdatedmasters; + int f_lua_setnotified; + + //slave functions.... + int f_lua_getdomaininfo; + int f_lua_ismaster; + int f_lua_getunfreshslaveinfos; + int f_lua_setfresh; + + int f_lua_starttransaction; + int f_lua_committransaction; + int f_lua_aborttransaction; + int f_lua_feedrecord; + + //supermaster functions.... + int f_lua_supermasterbackend; + int f_lua_createslavedomain; + + //rediscover + int f_lua_rediscover; + + //dnssec + int f_lua_alsonotifies; + int f_lua_getdomainmetadata; + int f_lua_setdomainmetadata; + + int f_lua_getdomainkeys; + int f_lua_removedomainkey; + int f_lua_activatedomainkey; + int f_lua_deactivatedomainkey; + int f_lua_updatedomainkey; + int f_lua_gettsigkey; + int f_lua_adddomainkey; + + int f_lua_getbeforeandafternamesabsolute; + int f_lua_updatednssecorderandauthabsolute; + int f_lua_updatednssecorderandauth; + + +// int my_lua_panic (lua_State *lua); + +// FUNCTIONS TO THIS BACKEND + bool getValueFromTable(lua_State *lua, const std::string& key, string& value); + bool getValueFromTable(lua_State *lua, const std::string& key, DNSName& value); + bool getValueFromTable(lua_State *lua, uint32_t key, string& value); +#if !(defined(__i386__) && defined(__FreeBSD__)) + bool getValueFromTable(lua_State *lua, const std::string& key, time_t& value); +#endif + bool getValueFromTable(lua_State *lua, const std::string& key, uint32_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, uint16_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, uint8_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, int& value); + bool getValueFromTable(lua_State *lua, const std::string& key, bool& value); + + //private.cc + bool domaininfo_from_table(DomainInfo *di); + void domains_from_table(vector* domains, const char *f_name); + void dnsrr_to_table(lua_State *lua, const DNSResourceRecord *rr); + + //reload.cc + void get_lua_function(lua_State *lua, const char *name, int *function); + + bool dnssec; + + bool logging; + + //dnssec.cc + bool updateDomainKey(const DNSName& name, unsigned int &id, bool toowhat); + + +/* + //minimal.cc + bool content(DNSResourceRecord* rr); + + void getTheFreshOnes(vector* domains, string *type, string *f_name); + bool checkDomainInfo(const string *domain, mongo::BSONObj *mongo_r, string *f_name, string *mongo_q, DomainInfo *di, SOAData *soadata = NULL); + + + //crc32.cc + int generateCRC32(const string& my_string); + + string mongo_db; + string collection_domains; + string collection_records; + + string collection_domainmetadata; + string collection_cryptokeys; + string collection_tsigkeys; + + mongo::DBClientConnection m_db; + + auto_ptr cursor; + + string q_name; + +// long long unsigned int count; + mongo::Query mongo_query; + mongo::BSONObj mongo_record; + bool elements; + DNSResourceRecord rr_record; + string type; + mongo::BSONObjIterator* contents; + + + + unsigned int default_ttl; + + bool logging_cerr; + bool logging_content; + + bool checkindex; + + bool use_default_ttl; + + bool axfr_soa; + SOAData last_soadata; +*/ +}; + +#endif diff --git a/modules/luabackend/master.cc b/modules/luabackend/master.cc new file mode 100644 index 0000000..6ca3dc6 --- /dev/null +++ b/modules/luabackend/master.cc @@ -0,0 +1,85 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +void LUABackend::getUpdatedMasters(vector* domains) { + + if (f_lua_getupdatedmasters == 0) + return; + + if (logging) + g_log << Logger::Info << backend_name << "(getUpdatedMasters) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getupdatedmasters); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return; + } + + domains_from_table(domains, "getUpdatedMasters"); + + if (logging) + g_log << Logger::Info << backend_name << "(getUpdatedMasters) END" << endl; +} + +void LUABackend::setNotified(uint32_t id, uint32_t serial) { + + if (f_lua_setnotified == 0) + return; + + if (logging) + g_log << Logger::Info << backend_name << "(setNotified) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setnotified); + + lua_pushinteger(lua, id); + lua_pushinteger(lua, serial); + + if(lua_pcall(lua, 2, 0, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + if (logging) + g_log << Logger::Info << backend_name << "(setNotified) END" << endl; +} + diff --git a/modules/luabackend/minimal.cc b/modules/luabackend/minimal.cc new file mode 100644 index 0000000..04af2b4 --- /dev/null +++ b/modules/luabackend/minimal.cc @@ -0,0 +1,243 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +//#include "lua_functions.hh" + +/* FIRST PART */ + +LUABackend::LUABackend(const string &suffix) { + + setArgPrefix("lua"+suffix); + + try { + + if (pthread_equal(backend_pid, pthread_self())) { + backend_count++; + } else { + backend_count = 1; + backend_pid = pthread_self(); + } + +// lb = NULL; + lua = NULL; + dnspacket = NULL; + dnssec = false; + + reload(); + } + + catch(LUAException &e) { + g_log< 0) + soadata.ttl = soadata.default_ttl; + + if (soadata.ttl == 0) { + lua_pop(lua, 1 ); + return false; + } + + if (!getValueFromTable(lua, "nameserver", soadata.nameserver)) { + soadata.nameserver = DNSName(arg()["default-soa-name"]); + if (soadata.nameserver.empty()) { + g_log<backend = NULL; + + if (!getValueFromTable(lua, "id", di->id)) + return false; + + if (!getValueFromTable(lua, "zone", di->zone)) + return false; + + if (!getValueFromTable(lua, "serial", di->serial)) + return false; + + getValueFromTable(lua, "notified_serial", di->notified_serial); + getValueFromTable(lua, "last_check", di->last_check); + + di->kind = DomainInfo::Native; + + string kind; + if (getValueFromTable(lua, "kind", kind)) { + + if (kind == "MASTER") + di->kind = DomainInfo::Master; + else if (kind == "SLAVE") + di->kind = DomainInfo::Slave; + } + + lua_pushstring(lua, "masters"); + lua_gettable(lua, -2); + + if(!lua_isnil(lua, -1)) { + lua_pushnil(lua); + const char *value; + while (lua_next(lua, -2)) { + value = lua_tostring(lua, -1); + lua_pop(lua,1); + di->masters.push_back(ComboAddress(value, 53)); + } + } + + lua_pop(lua, 1); + + di->backend = this; + + return true; +} + +void LUABackend::domains_from_table(vector* domains, const char *f_name) { + lua_pushnil(lua); + + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TTABLE) { + DomainInfo di; + + if (domaininfo_from_table(&di)) + domains->push_back(di); + } + + lua_pop(lua,1); + } +} + + +void LUABackend::dnsrr_to_table(lua_State *lua, const DNSResourceRecord *rr) { + + lua_newtable(lua); + + lua_pushliteral(lua, "qtype"); + lua_pushstring(lua, rr->qtype.getName().c_str()); + lua_settable(lua, -3); + + lua_pushliteral(lua, "qclass"); + lua_pushinteger(lua, rr->qclass); + lua_settable(lua, -3); + + lua_pushliteral(lua, "ttl"); + lua_pushinteger(lua, rr->ttl); + lua_settable(lua, -3); + + lua_pushliteral(lua, "auth"); + lua_pushboolean(lua, rr->auth); + lua_settable(lua, -3); + + lua_pushliteral(lua, "content"); + lua_pushstring(lua, rr->content.c_str()); + lua_settable(lua, -3); + +} diff --git a/modules/luabackend/reload.cc b/modules/luabackend/reload.cc new file mode 100644 index 0000000..43b29d5 --- /dev/null +++ b/modules/luabackend/reload.cc @@ -0,0 +1,195 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +#include +#include +using namespace std; + +#include "lua_functions.hh" + +/* + virtual void reload(); + virtual void rediscover(string* status=0); +*/ + +void LUABackend::get_lua_function(lua_State *lua, const char *name, int *function) { + *function = 0; + + string f = "f_"; + f.append(name); + + string arg = ""; + if (!::arg().isEmpty(f)) + arg = getArg(f); + + lua_getglobal(lua, arg == "" ? name : arg.c_str()); + if (!lua_isnil(lua, -1)) { + lua_pushvalue(lua, -1); + *function = luaL_ref(lua, LUA_REGISTRYINDEX); + } +} + + +void LUABackend::reload() { + + backend_name.clear(); + +// backend_name = "[LUABackend: " + uitoa(backend_pid) + " (" + uitoa(backend_count) +")] "; + backend_name = "[LUABackend: (" + uitoa(backend_count) +")] "; + + if (lua) + lua_close(lua); + + logging = ::arg().mustDo("query-logging") || mustDo("logging-query"); + +#if LUA_VERSION_NUM >= 502 + lua = luaL_newstate(); +#else + lua = lua_open(); +#endif + + if (lua != NULL) { + lua_atpanic(lua, my_lua_panic); + + string filename = getArg("filename"); //"powerdns-luabackend.lua"; + + if (luaL_loadfile (lua, filename.c_str()) != 0) { + stringstream e; + e << backend_name << "Error loading the file '" << filename << "' : " << lua_tostring(lua,-1) << endl; + + lua_pop(lua, 1); + throw LUAException (e.str()); + } else { + + lua_pushlightuserdata(lua, (void*)this); + lua_setfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + + register_lua_functions(lua); + + if(lua_pcall(lua, 0, 0, 0)) { + stringstream e; + e << backend_name << "Error running the file '" << filename << "' : " << lua_tostring(lua,-1) << endl; + + lua_pop(lua, 1); + throw LUAException (e.str()); + + } else { + get_lua_function(lua, "exec_error", &f_lua_exec_error); + + //minimal functions.... + get_lua_function(lua, "list", &f_lua_list); + get_lua_function(lua, "lookup", &f_lua_lookup); + get_lua_function(lua, "get", &f_lua_get); + get_lua_function(lua, "getsoa", &f_lua_getsoa); + + if (f_lua_list == 0 || f_lua_lookup == 0 || f_lua_get == 0 || f_lua_getsoa == 0) { + throw LUAException (backend_name + "MINIMAL BACKEND: Missing required function(s)!"); + } + + //master functions.... + get_lua_function(lua, "getupdatedmasters", &f_lua_getupdatedmasters); + get_lua_function(lua, "setnotified", &f_lua_setnotified); + + //slave functions.... + get_lua_function(lua, "getdomaininfo", &f_lua_getdomaininfo); + get_lua_function(lua, "ismaster", &f_lua_ismaster); + get_lua_function(lua, "getunfreshslaveinfos", &f_lua_getunfreshslaveinfos); + get_lua_function(lua, "setfresh", &f_lua_setfresh); + get_lua_function(lua, "starttransaction", &f_lua_starttransaction); + get_lua_function(lua, "committransaction", &f_lua_committransaction); + get_lua_function(lua, "aborttransaction", &f_lua_aborttransaction); + get_lua_function(lua, "feedrecord", &f_lua_feedrecord); + + //supermaster functions.... + get_lua_function(lua, "supermasterbackend", &f_lua_supermasterbackend); + get_lua_function(lua, "createslavedomain", &f_lua_createslavedomain); + + //rediscover + get_lua_function(lua, "rediscover", &f_lua_rediscover); + + //dnssec + get_lua_function(lua, "alsonotifies", &f_lua_alsonotifies); + get_lua_function(lua, "getdomainmetadata", &f_lua_getdomainmetadata); + get_lua_function(lua, "setdomainmetadata", &f_lua_setdomainmetadata); + + get_lua_function(lua, "getdomainkeys", &f_lua_getdomainkeys); + get_lua_function(lua, "removedomainkey", &f_lua_removedomainkey); + get_lua_function(lua, "activatedomainkey", &f_lua_activatedomainkey); + get_lua_function(lua, "deactivatedomainkey", &f_lua_deactivatedomainkey); + get_lua_function(lua, "updatedomainkey", &f_lua_updatedomainkey); + get_lua_function(lua, "adddomainkey", &f_lua_adddomainkey); + + get_lua_function(lua, "gettsigkey", &f_lua_gettsigkey); + + get_lua_function(lua, "getbeforeandafternamesabsolute", &f_lua_getbeforeandafternamesabsolute); + get_lua_function(lua, "updatednssecorderandauthabsolute", &f_lua_updatednssecorderandauthabsolute); + get_lua_function(lua, "updatednssecorderandauth", &f_lua_updatednssecorderandauth); // not needed... + + } + } + } else { + //a big kaboom here! + throw LUAException (backend_name + "LUA OPEN FAILED!"); + } +} + +void LUABackend::rediscover(string* status) { + + if (f_lua_rediscover == 0) + return; + + if (logging) + g_log << Logger::Info << backend_name << "(rediscover) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_rediscover); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TSTRING) { + lua_pop(lua, 1 ); + return; + } + + string s = lua_tostring(lua, -1); + lua_pop(lua, 1 ); + *status = s; + + if (logging) + g_log << Logger::Info << backend_name << "(rediscover) END" << endl; + + return; +} + diff --git a/modules/luabackend/slave.cc b/modules/luabackend/slave.cc new file mode 100644 index 0000000..ff90067 --- /dev/null +++ b/modules/luabackend/slave.cc @@ -0,0 +1,254 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + + virtual bool startTransaction(const string &qname, int id); + virtual bool commitTransaction(); + virtual bool abortTransaction(); + virtual bool feedRecord(const DNSResourceRecord &rr, DNSName &ordername, bool ordernameIsNSEC3); + + virtual bool getDomainInfo(const string &domain, DomainInfo &di); + virtual void getUnfreshSlaveInfos(vector* domains); + virtual void setFresh(uint32_t id); +*/ + +bool LUABackend::startTransaction(const DNSName& qname, int id) { + + if (f_lua_starttransaction == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(startTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_starttransaction); + + lua_pushstring(lua, qname.toString().c_str()); + lua_pushinteger(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + g_log << Logger::Info << backend_name << "(startTransaction) END" << endl; + + return ok; +} + +bool LUABackend::commitTransaction() { + + if (f_lua_committransaction == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(commitTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_committransaction); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + g_log << Logger::Info << backend_name << "(commitTransaction) END" << endl; + + return ok; +} + +bool LUABackend::abortTransaction() { + + if (f_lua_aborttransaction == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(abortTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_aborttransaction); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + g_log << Logger::Info << backend_name << "(abortTransaction) END" << endl; + return ok; +} + +bool LUABackend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3) { + + if (f_lua_feedrecord == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(feedRecord) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_feedrecord); + dnsrr_to_table(lua, &rr); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + g_log << Logger::Info << backend_name << "(feedRecord) END" << endl; + + return ok; +} + +void LUABackend::setFresh(uint32_t id) { + + if (f_lua_setfresh == 0) + return; + + if (logging) + g_log << Logger::Info << backend_name << "(setFresh) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setfresh); + + lua_pushinteger(lua, id); + + if(lua_pcall(lua, 1, 0, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + if (logging) + g_log << Logger::Info << backend_name << "(setFresh) END" << endl; + +} + +void LUABackend::getUnfreshSlaveInfos(vector* domains) { + + if (f_lua_getunfreshslaveinfos == 0) + return; + + if (logging) + g_log << Logger::Info << backend_name << "(getUnfreshSlaveInfos) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getunfreshslaveinfos); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return; + } + + domains_from_table(domains, "getUnfreshSlaveInfos"); + + if (logging) + g_log << Logger::Info << backend_name << "(getUnfreshSlaveInfos) END" << endl; + +} + +bool LUABackend::getDomainInfo(const DNSName&domain, DomainInfo &di, bool getSerial) { + if (f_lua_getdomaininfo == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(getDomainInfo) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomaininfo); + + lua_pushstring(lua, domain.toString().c_str()); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return false; + } + + if (logging) + g_log << Logger::Info << backend_name << "(getDomainInfo) END" << endl; + + return domaininfo_from_table(&di); +} diff --git a/modules/luabackend/supermaster.cc b/modules/luabackend/supermaster.cc new file mode 100644 index 0000000..e3075ae --- /dev/null +++ b/modules/luabackend/supermaster.cc @@ -0,0 +1,139 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Fredrik Danerklint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + //! determine if ip is a supermaster for a domain + virtual bool superMasterBackend(const string &ip, const string &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) + + //! called by PowerDNS to create a slave record for a superMaster + virtual bool createSlaveDomain(const string &ip, const string &domain, const string &nameserver, const string &account) + +*/ + +bool LUABackend::superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) { + + if (f_lua_supermasterbackend == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(superMasterBackend) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_supermasterbackend); + + lua_pushstring(lua, ip.c_str()); + lua_pushstring(lua, domain.toString().c_str()); + + + lua_newtable(lua); + int c = 0; + for(vector::const_iterator i=nsset.begin();i!=nsset.end();++i) { + c++; + lua_pushinteger(lua, c); + + DNSResourceRecord rr; + + rr.qtype = i->qtype; + rr.qclass = i->qclass; + rr.ttl = i->ttl; + rr.auth = i->auth; + rr.content = i->content; + + dnsrr_to_table(lua, &rr); + lua_settable(lua, -3); + } + + if(lua_pcall(lua, 3, 2, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + string a = ""; + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) + a = lua_tostring(lua, -1); + lua_pop(lua, 1); + + if (ok) { + *account = a; + *db = this; + } + + if (logging) + g_log << Logger::Info << backend_name << "(superMasterBackend) END" << endl; + + return ok; +} + +bool LUABackend::createSlaveDomain(const string &ip, const DNSName& domain, const string &nameserver, const string &account) { + + if (f_lua_createslavedomain == 0) + return false; + + if (logging) + g_log << Logger::Info << backend_name << "(createSlaveDomain) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_createslavedomain); + + lua_pushstring(lua, ip.c_str()); + lua_pushstring(lua, domain.toString().c_str()); + lua_pushstring(lua, account.c_str()); + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + g_log << Logger::Info << backend_name << "(createSlaveDomain) END" << endl; + + return ok; +} diff --git a/modules/mydnsbackend/Makefile.am b/modules/mydnsbackend/Makefile.am new file mode 100644 index 0000000..1053d24 --- /dev/null +++ b/modules/mydnsbackend/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS += $(MYSQL_CFLAGS) +pkglib_LTLIBRARIES = libmydnsbackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + schema.mydns.sql + +dist_doc_DATA = schema.mydns.sql + +libmydnsbackend_la_SOURCES = \ + mydnsbackend.cc mydnsbackend.hh + +libmydnsbackend_la_LDFLAGS = -module -avoid-version +libmydnsbackend_la_LIBADD = \ + ../gmysqlbackend/smysql.lo \ + $(MYSQL_LIBS) diff --git a/modules/mydnsbackend/Makefile.in b/modules/mydnsbackend/Makefile.in new file mode 100644 index 0000000..519514a --- /dev/null +++ b/modules/mydnsbackend/Makefile.in @@ -0,0 +1,862 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/mydnsbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmydnsbackend_la_DEPENDENCIES = ../gmysqlbackend/smysql.lo \ + $(am__DEPENDENCIES_1) +am_libmydnsbackend_la_OBJECTS = mydnsbackend.lo +libmydnsbackend_la_OBJECTS = $(am_libmydnsbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmydnsbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libmydnsbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmydnsbackend_la_SOURCES) +DIST_SOURCES = $(libmydnsbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(MYSQL_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libmydnsbackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + schema.mydns.sql + +dist_doc_DATA = schema.mydns.sql +libmydnsbackend_la_SOURCES = \ + mydnsbackend.cc mydnsbackend.hh + +libmydnsbackend_la_LDFLAGS = -module -avoid-version +libmydnsbackend_la_LIBADD = \ + ../gmysqlbackend/smysql.lo \ + $(MYSQL_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/mydnsbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/mydnsbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmydnsbackend.la: $(libmydnsbackend_la_OBJECTS) $(libmydnsbackend_la_DEPENDENCIES) $(EXTRA_libmydnsbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libmydnsbackend_la_LINK) -rpath $(pkglibdir) $(libmydnsbackend_la_OBJECTS) $(libmydnsbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mydnsbackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/mydnsbackend/OBJECTFILES b/modules/mydnsbackend/OBJECTFILES new file mode 100644 index 0000000..e1c69a1 --- /dev/null +++ b/modules/mydnsbackend/OBJECTFILES @@ -0,0 +1 @@ +mydnsbackend.lo diff --git a/modules/mydnsbackend/OBJECTLIBS b/modules/mydnsbackend/OBJECTLIBS new file mode 100644 index 0000000..11d4311 --- /dev/null +++ b/modules/mydnsbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(MYSQL_LIBS) diff --git a/modules/mydnsbackend/mydnsbackend.cc b/modules/mydnsbackend/mydnsbackend.cc new file mode 100644 index 0000000..b8a3714 --- /dev/null +++ b/modules/mydnsbackend/mydnsbackend.cc @@ -0,0 +1,500 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Jonathan Oddy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * The schema used by MyDNS isn't suitable for retrieving results with a single + * query. This means that existing PowerDNS backends are unable to make use of + * the schema without lame hackery (or awful performance.) This module does + * the nasty lookup logic required to make use of the schema, and should be as + * tolerant as MyDNS when it comes to things being fully qualified or not. + * + * A known "bug" is that AXFRs will fail if your rr table contains invalid + * junk. I'm not sure this is really a bug, if you've decided to put free-form + * text in your data for an A record you have bigger issues. + * + * I'd advise avoiding the MyDNS schema if at all possible as the query count + * for even simple lookups is daft. It's quite trivial to craft a request + * that'll require 128 database queries to answer with a servfail! + * + * If you do not know what mydns is: http://mydns.bboy.net/ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include + +#include "pdns/namespaces.hh" + +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "mydnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +#include + +static string backendName="[MyDNSbackend]"; + +MyDNSBackend::MyDNSBackend(const string &suffix) { + setArgPrefix("mydns"+suffix); + + try { + d_db = new SMySQL(getArg("dbname"), + getArg("host"), + getArgAsNum("port"), + getArg("socket"), + getArg("user"), + getArg("password")); + d_db->setLog(::arg().mustDo("query-logging")); + } + catch(SSqlException &e) { + g_log<prepare(domainIdQuery, 1); + d_domainNoIdQuery_stmt = d_db->prepare(domainNoIdQuery, 1); + d_soaQuery_stmt = d_db->prepare(soaQuery, 1); + d_allDomainsQuery_stmt = d_db->prepare(allDomainsQuery, 0); + + string listQuery = "SELECT type, data, aux, ttl, zone, name FROM `"+rrtable+"` WHERE zone = ?"; + string basicQuery = "SELECT type, data, aux, ttl, zone FROM `"+rrtable+"` WHERE zone = ? AND (name = ? OR name = ?) AND type = ?"; + string anyQuery = "(SELECT type, data, aux, ttl, zone FROM `"+rrtable+"` WHERE zone = ? AND (name = ? OR name = ?)"; + + if (!rrwhere.empty()) { + listQuery += " AND "+rrwhere; + basicQuery += " AND " + rrwhere; + anyQuery += " AND " + rrwhere; + } + + d_listQuery_stmt = d_db->prepare(listQuery, 1); + + anyQuery += ") UNION (SELECT 'SOA' AS type, CONCAT_WS(' ', ns, mbox,serial,refresh,retry,expire,minimum) AS data, '0' AS aux, ttl, id AS zone FROM `"+soatable+"` WHERE id = ? AND origin = ?"; + + if (!soawhere.empty()) { + anyQuery += " AND "+soawhere; + } + + basicQuery += " ORDER BY type,aux,data"; + anyQuery += ") ORDER BY type,aux,data"; + + d_basicQuery_stmt = d_db->prepare(basicQuery, 4); + d_anyQuery_stmt = d_db->prepare(anyQuery, 5); + } catch (SSqlException &e) { + g_log< + bind("domain_id", zoneId)-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to list domain_id "+itoa(zoneId)+": "+e.txtReason()); + } + + if (d_result.empty()) + return false; // No such zone + + d_origin = d_result[0][0]; + if (d_origin[d_origin.length()-1] == '.') + d_origin.erase(d_origin.length()-1); + d_minimum = pdns_stou(d_result[0][1]); + + if (d_result.size()>1) { + g_log< + bind("domain_id", zoneId)-> + execute(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to list domain_id "+itoa(zoneId)+": "+e.txtReason()); + } + + d_qname = ""; + return true; +} + +bool MyDNSBackend::getSOA(const DNSName& name, SOAData& soadata) { + string query; + SSqlStatement::row_t rrow; + + if (name.empty()) + return false; + + try { + d_soaQuery_stmt-> + bind("origin", name.toString())-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to get soa for domain "+name.toLogString()+": "+e.txtReason()); + } + + if (d_result.empty()) { + return false; + } + + rrow = d_result[0]; + + soadata.qname = name; + soadata.domain_id = pdns_stou(rrow[0]); + soadata.hostmaster = DNSName(rrow[1]); + soadata.serial = pdns_stou(rrow[2]); + soadata.nameserver = DNSName(rrow[3]); + soadata.refresh = pdns_stou(rrow[4]); + soadata.retry = pdns_stou(rrow[5]); + soadata.expire = pdns_stou(rrow[6]); + soadata.default_ttl = pdns_stou(rrow[7]); + soadata.ttl = pdns_stou(rrow[8]); + if (d_useminimalttl) { + soadata.ttl = std::min(soadata.ttl, soadata.default_ttl); + } + soadata.db = this; + + if (d_result.size()>1) { + g_log< + bind("domain", sdom.toString())-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+qname.toLogString()+": "+e.txtReason()); + } + + if (d_result.empty() == false) { + rrow = d_result[0]; + zoneId = pdns_stou(rrow[0]); + d_origin = stripDot(rrow[1]); + d_minimum = pdns_stou(rrow[2]); + found = true; + break; + } + + } while(sdom.chopOff()); + + } else { + try { + d_domainIdQuery_stmt-> + bind("domain_id", zoneId)-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+qname.toLogString()+": "+e.txtReason()); + } + + if(d_result.empty()) { + return; // just return if zone was not found instead of throwing an error + } + + rrow = d_result[0]; + + found = true; + d_origin = stripDot(rrow[0]); + d_minimum = pdns_stou(rrow[1]); + } + + if (found) { + + if (d_result.size()>1) { + g_log< + bind("domain_id", zoneId)-> + bind("host", host)-> + bind("qname", qname.toString())-> + bind("domain_id", zoneId)-> // this is because positional arguments + bind("qname2", sdom.toString())-> + execute(); + } else { + DLOG(g_log< + bind("domain_id", zoneId)-> + bind("host", host)-> + bind("qname", qname.toString())-> + bind("qtype", qtype.getName())-> + execute(); + } + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+qname.toLogString()+": "+e.txtReason()); + } + + d_qname = qname.toString(); + } + +} + +bool MyDNSBackend::get(DNSResourceRecord &rr) { + if (d_origin.empty()) { + if (d_query_stmt) { + try { + (*d_query_stmt)->reset(); + } catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+d_qname+": "+e.txtReason()); + } + d_query_stmt = NULL; + } + // This happens if lookup() couldn't find the zone + return false; + } + + SSqlStatement::row_t rrow; + + if ((*d_query_stmt)->hasNextRow()) { + try { + (*d_query_stmt)->nextRow(rrow); + } catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+d_qname+": "+e.txtReason()); + } + rr.qtype=rrow[0]; + rr.content = rrow[1]; + + if(!d_qname.empty()) { + // use this to distinguish between select with 'name' field (list()) and one without + rr.qname=DNSName(d_qname); + } else { + string tmpQname = rrow[5]; + + //TODO: Refactor + if (!tmpQname.empty() && tmpQname[tmpQname.length()-1] == '.') { + tmpQname.erase(tmpQname.length()-1); // Fully qualified, nuke the last . + } else { + if (!tmpQname.empty()) { + tmpQname += "."; + } + tmpQname += d_origin; // Not fully qualified + } + rr.qname = DNSName(tmpQname); + } + + if (rr.qtype.getCode() == QType::NS || rr.qtype.getCode()==QType::MX || + rr.qtype.getCode() == QType::CNAME || rr.qtype.getCode() == QType::PTR) { + if (!rr.content.empty() && rr.content[rr.content.length()-1] == '.') { + if (rr.content.length() > 1) + rr.content.erase(rr.content.length()-1); // Fully qualified, nuke the last . + } else { + if (rr.content != ".") + rr.content += "."; + rr.content += d_origin; + } + } + + if (rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) + rr.content=rrow[2]+" "+rr.content; + + rr.ttl = pdns_stou(rrow[3]); + if (d_useminimalttl) + rr.ttl = std::min(rr.ttl, d_minimum); + rr.domain_id=pdns_stou(rrow[4]); + + rr.last_modified=0; + + return true; + } + + try { + (*d_query_stmt)->reset(); + } catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to lookup "+d_qname+": "+e.txtReason()); + } + + d_query_stmt = NULL; + + return false; +} + +void MyDNSBackend::getAllDomains(vector *domains, bool include_disabled) { + /* include_disabled is unfortunately ignored here */ + try { + d_allDomainsQuery_stmt-> + execute(); + + while(d_allDomainsQuery_stmt->hasNextRow()) { + SSqlStatement::row_t row; + DomainInfo di; + d_allDomainsQuery_stmt->nextRow(row); + + di.id = pdns_stou(row[0]); + di.zone = DNSName(row[1]); + di.serial = pdns_stou(row[2]); + di.kind = DomainInfo::Native; + di.backend = this; + + domains->push_back(di); + } + + d_allDomainsQuery_stmt-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("MyDNSBackend unable to list all domains: "+e.txtReason()); + } +} + +class MyDNSFactory : public BackendFactory { + +public: + MyDNSFactory() : BackendFactory("mydns") {} + + void declareArguments(const string &suffix = "") { + declare(suffix,"dbname","Pdns backend database name to connect to","mydns"); + declare(suffix,"user","Pdns backend user to connect as","powerdns"); + declare(suffix,"host","Pdns backend host to connect to",""); + declare(suffix,"port","Pdns backend host to connect to",""); + declare(suffix,"password","Pdns backend password to connect with",""); + declare(suffix,"socket","Pdns backend socket to connect to",""); + declare(suffix,"rr-table","Name of RR table to use","rr"); + declare(suffix,"soa-table","Name of SOA table to use","soa"); + declare(suffix,"soa-where","Additional WHERE clause for SOA","1 = 1"); + declare(suffix,"rr-where","Additional WHERE clause for RR","1 = 1"); + declare(suffix,"soa-active","Use the active column in the SOA table","yes"); + declare(suffix,"rr-active","Use the active column in the RR table","yes"); + declare(suffix,"use-minimal-ttl","Setting this to 'yes' will make the backend behave like MyDNS on the TTL values. Setting it to 'no' will make it ignore the minimal-ttl of the zone.","yes"); + } + + DNSBackend *make(const string &suffix="") { + return new MyDNSBackend(suffix); + } + +}; + +class MyDNSLoader { + +public: + MyDNSLoader() { + BackendMakers().report(new MyDNSFactory()); + g_log << Logger::Info << "[mydnsbackend] This is the mydns backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + +static MyDNSLoader mydnsloader; diff --git a/modules/mydnsbackend/mydnsbackend.hh b/modules/mydnsbackend/mydnsbackend.hh new file mode 100644 index 0000000..1e19af2 --- /dev/null +++ b/modules/mydnsbackend/mydnsbackend.hh @@ -0,0 +1,65 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Jonathan Oddy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef MYDNSBACKEND_HH +#define MYDNSBACKEND_HH + +#include +#include + +#include "pdns/namespaces.hh" + +#include + +class MyDNSBackend : public DNSBackend +{ +public: + MyDNSBackend(const string &suffix); + ~MyDNSBackend(); + + void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1) override; + bool list(const DNSName &target, int domain_id, bool include_disabled=false) override; + bool get(DNSResourceRecord &r) override; + bool getSOA(const DNSName& name, SOAData& soadata) override; + void getAllDomains(vector *domains, bool include_disabled=false) override; + +private: + SMySQL *d_db; + + string d_qname; + string d_origin; + bool d_useminimalttl; + unsigned int d_minimum; + + SSqlStatement::result_t d_result; + + std::unique_ptr* d_query_stmt; + std::unique_ptr d_domainIdQuery_stmt; + std::unique_ptr d_domainNoIdQuery_stmt; + std::unique_ptr d_listQuery_stmt; + std::unique_ptr d_soaQuery_stmt; + std::unique_ptr d_basicQuery_stmt; + std::unique_ptr d_anyQuery_stmt; + std::unique_ptr d_allDomainsQuery_stmt; +}; + +#endif /* MYDNSBACKEND_HH */ diff --git a/modules/mydnsbackend/schema.mydns.sql b/modules/mydnsbackend/schema.mydns.sql new file mode 100644 index 0000000..2e85d04 --- /dev/null +++ b/modules/mydnsbackend/schema.mydns.sql @@ -0,0 +1,42 @@ +-- +-- Table layouts for mydns 1.2.8.31 (Dec 2014) +-- Copyright (C) 2002-2005 Don Moore 2007-2008 Howard Wilkinson +-- +-- You might create these tables with a command like: +-- +-- $ mydns --create-tables | mysql -hHOST -p -uUSER DATABASE +-- +-- Originally licensed under the GNU GPLv2 or higher + +-- +-- Table structure for table 'soa' (zones of authority) +-- +CREATE TABLE IF NOT EXISTS soa ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + origin CHAR(255) NOT NULL, + ns CHAR(255) NOT NULL, + mbox CHAR(255) NOT NULL, + serial INT UNSIGNED NOT NULL default '1', + refresh INT UNSIGNED NOT NULL default '28800', + retry INT UNSIGNED NOT NULL default '7200', + expire INT UNSIGNED NOT NULL default '604800', + minimum INT UNSIGNED NOT NULL default '86400', + ttl INT UNSIGNED NOT NULL default '86400', + active ENUM('Y', 'N') NOT NULL DEFAULT 'Y', + UNIQUE KEY (origin) +) Engine=MyISAM; + +-- +-- Table structure for table 'rr' (resource records) +-- +CREATE TABLE IF NOT EXISTS rr ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + zone INT UNSIGNED NOT NULL, + name CHAR(200) NOT NULL, + data VARBINARY(128) NOT NULL, + aux INT UNSIGNED NOT NULL, + ttl INT UNSIGNED NOT NULL default '86400', + type ENUM('A','AAAA','CNAME','HINFO','MX','NAPTR','NS','PTR','RP','SRV','TXT'), + active ENUM('Y', 'N') NOT NULL DEFAULT 'Y', + UNIQUE KEY rr (zone,name,type,data,aux,active) +) Engine=MyISAM; diff --git a/modules/opendbxbackend/Makefile.am b/modules/opendbxbackend/Makefile.am new file mode 100644 index 0000000..494c99a --- /dev/null +++ b/modules/opendbxbackend/Makefile.am @@ -0,0 +1,10 @@ +pkglib_LTLIBRARIES = libopendbxbackend.la + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +libopendbxbackend_la_SOURCES = \ + odbxbackend.cc odbxbackend.hh \ + odbxprivate.cc + +libopendbxbackend_la_LDFLAGS = -module -avoid-version +libopendbxbackend_la_LIBADD = $(OPENDBX_LIBS) diff --git a/modules/opendbxbackend/Makefile.in b/modules/opendbxbackend/Makefile.in new file mode 100644 index 0000000..d0ac33b --- /dev/null +++ b/modules/opendbxbackend/Makefile.in @@ -0,0 +1,830 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/opendbxbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libopendbxbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libopendbxbackend_la_OBJECTS = odbxbackend.lo odbxprivate.lo +libopendbxbackend_la_OBJECTS = $(am_libopendbxbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libopendbxbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libopendbxbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libopendbxbackend_la_SOURCES) +DIST_SOURCES = $(libopendbxbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libopendbxbackend.la +EXTRA_DIST = OBJECTFILES OBJECTLIBS +libopendbxbackend_la_SOURCES = \ + odbxbackend.cc odbxbackend.hh \ + odbxprivate.cc + +libopendbxbackend_la_LDFLAGS = -module -avoid-version +libopendbxbackend_la_LIBADD = $(OPENDBX_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/opendbxbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/opendbxbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libopendbxbackend.la: $(libopendbxbackend_la_OBJECTS) $(libopendbxbackend_la_DEPENDENCIES) $(EXTRA_libopendbxbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libopendbxbackend_la_LINK) -rpath $(pkglibdir) $(libopendbxbackend_la_OBJECTS) $(libopendbxbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odbxbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odbxprivate.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/opendbxbackend/OBJECTFILES b/modules/opendbxbackend/OBJECTFILES new file mode 100644 index 0000000..f2a813e --- /dev/null +++ b/modules/opendbxbackend/OBJECTFILES @@ -0,0 +1 @@ +odbxbackend.lo odbxprivate.lo diff --git a/modules/opendbxbackend/OBJECTLIBS b/modules/opendbxbackend/OBJECTLIBS new file mode 100644 index 0000000..ffc7f01 --- /dev/null +++ b/modules/opendbxbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(OPENDBX_LIBS) diff --git a/modules/opendbxbackend/README b/modules/opendbxbackend/README new file mode 100644 index 0000000..a4c39c6 --- /dev/null +++ b/modules/opendbxbackend/README @@ -0,0 +1,2 @@ +For more information, see +http://wiki.linuxnetworks.de/doc/index.php/PowerDNS_OpenDBX_Backend \ No newline at end of file diff --git a/modules/opendbxbackend/odbxbackend.cc b/modules/opendbxbackend/odbxbackend.cc new file mode 100644 index 0000000..d9d8a5c --- /dev/null +++ b/modules/opendbxbackend/odbxbackend.cc @@ -0,0 +1,777 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "odbxbackend.hh" + + + +inline string& strbind( const string& search, const string& replace, string& subject ) +{ + size_t pos = 0; + + while( ( pos = subject.find( search, pos ) ) != string::npos ) + { + subject.replace( pos, search.size(), replace ); + pos += replace.size(); + } + + return subject; +} + + + +OdbxBackend::OdbxBackend( const string& suffix ) +{ + vector hosts; + + + try + { + m_result = NULL; + m_handle[READ] = NULL; + m_handle[WRITE] = NULL; + m_myname = "[OpendbxBackend]"; + m_default_ttl = arg().asNum( "default-ttl" ); + m_qlog = arg().mustDo( "query-logging" ); + + setArgPrefix( "opendbx" + suffix ); + + if( getArg( "host" ).size() > 0 ) + { + g_log.log( m_myname + " WARNING: Using deprecated opendbx-host parameter", Logger::Warning ); + stringtok( m_hosts[READ], getArg( "host" ), ", " ); + m_hosts[WRITE] = m_hosts[READ]; + } + else + { + stringtok( m_hosts[READ], getArg( "host-read" ), ", " ); + stringtok( m_hosts[WRITE], getArg( "host-write" ), ", " ); + } + + if( !connectTo( m_hosts[READ], READ ) ) { throw( PDNSException( "Fatal: Connecting to server for reading failed" ) ); } + if( !connectTo( m_hosts[WRITE], WRITE ) ) { throw( PDNSException( "Fatal: Connecting to server for writing failed" ) ); } + } + catch( std::exception& e ) + { + g_log.log( m_myname + " OdbxBackend(): Caught STL exception - " + e.what(), Logger::Error ); + throw( PDNSException( "Fatal: STL exception" ) ); + } +} + + + +OdbxBackend::~OdbxBackend() +{ + odbx_unbind( m_handle[WRITE] ); + odbx_unbind( m_handle[READ] ); + + odbx_finish( m_handle[WRITE] ); + odbx_finish( m_handle[READ] ); +} + + + +bool OdbxBackend::getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial ) +{ + const char* tmp; + + + try + { + DLOG( g_log.log( m_myname + " getDomainInfo()", Logger::Debug ) ); + + string stmt = getArg( "sql-zoneinfo" ); + string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } + if( !getRecord( READ ) ) { return false; } + + do + { + di.id = 0; + di.zone.clear(); + di.masters.clear(); + di.last_check = 0; + di.notified_serial = 0; + di.kind = DomainInfo::Native; + di.backend = this; + di.serial = 0; + + if( getSerial && ( tmp = odbx_field_value( m_result, 6 ) ) != NULL ) + { + SOAData sd; + + sd.serial = 0; + fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd ); + + if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) + { + sd.serial = strtol( tmp, NULL, 10 ); + } + + di.serial = sd.serial; + } + + if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) + { + di.last_check = strtol( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + { + vector masters; + stringtok(masters, string( tmp, odbx_field_length( m_result, 3 ) ), ", \t"); + for(const auto& m : masters) + { + di.masters.emplace_back(m, 53); + } + } + + if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) + { + if( !strncmp( tmp, "SLAVE", 5 ) ) + { + di.kind = DomainInfo::Slave; + } + else if( !strncmp( tmp, "MASTER", 6 ) ) + { + di.kind = DomainInfo::Master; + } + } + + if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + { + di.zone = DNSName(string( tmp, odbx_field_length( m_result, 1 ) )); + } + + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + { + di.id = strtol( tmp, NULL, 10 ); + } + } + while( getRecord( READ ) ); + } + catch( std::exception& e ) + { + g_log.log( m_myname + " getDomainInfo: Caught STL std::exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd ) +{ + const char* tmp; + + + try + { + DLOG( g_log.log( m_myname + " getSOA()", Logger::Debug ) ); + + string stmt = getArg( "sql-lookupsoa" ); + string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } + if( !getRecord( READ ) ) { return false; } + + do + { + sd.qname = domain; + sd.serial = 0; + sd.ttl = m_default_ttl; + + if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + { + fillSOAData( string( tmp, odbx_field_length( m_result, 3 ) ), sd ); + } + + if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) + { + sd.ttl = strtoul( tmp, NULL, 10 ); + } + + if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + { + sd.serial = strtol( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + { + sd.domain_id = strtol( tmp, NULL, 10 ); + } + + if( sd.nameserver.empty() ) + { + sd.nameserver = DNSName(arg()["default-soa-name"]); + } + + if( sd.hostmaster.empty() ) + { + sd.hostmaster = DNSName("hostmaster") + DNSName(domain); + } + + sd.db = this; + } + while( getRecord( READ ) ); + } + catch( std::exception& e ) + { + g_log.log( m_myname + " getSOA: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::list( const DNSName& target, int zoneid, bool include_disabled ) +{ + try + { + DLOG( g_log.log( m_myname + " list()", Logger::Debug ) ); + + m_qname.clear(); + m_result = NULL; + + int len = snprintf( m_buffer, sizeof( m_buffer ), "%d", zoneid ); + + if( len < 0 ) + { + g_log.log( m_myname + " list: Unable to convert zone id to string - format error", Logger::Error ); + return false; + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " list: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); + return false; + } + + string stmt = getArg( "sql-list" ); + string& stmtref = strbind( ":id", string( m_buffer, len ), stmt ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } + } + catch( std::exception& e ) + { + g_log.log( m_myname + " list: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +void OdbxBackend::lookup( const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid ) +{ + try + { + DLOG( g_log.log( m_myname + " lookup()", Logger::Debug ) ); + + string stmt; + string& stmtref = stmt; + + m_result = NULL; + m_qname = qname; + + if( zoneid < 0 ) + { + if( qtype.getCode() == QType::ANY ) + { + stmt = getArg( "sql-lookup" ); + } else { + stmt = getArg( "sql-lookuptype" ); + stmtref = strbind( ":type", qtype.getName(), stmt ); + } + } + else + { + if( qtype.getCode() == QType::ANY ) + { + stmt = getArg( "sql-lookupid" ); + } else { + stmt = getArg( "sql-lookuptypeid" ); + stmtref = strbind( ":type", qtype.getName(), stmt ); + } + + int len = snprintf( m_buffer, sizeof( m_buffer ), "%d", zoneid ); + + if( len < 0 ) + { + g_log.log( m_myname + " lookup: Unable to convert zone id to string - format error", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " lookup: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + stmtref = strbind( ":id", string( m_buffer, len ), stmtref ); + } + + stmtref = strbind( ":name", escape( qname.makeLowerCase().toStringRootDot(), READ ), stmtref ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) + { + throw( DBException( "Error: DB statement failed" ) ); + } + } + catch( std::exception& e ) + { + g_log.log( m_myname + " lookup: Caught STL exception - " + e.what(), Logger::Error ); + throw( DBException( "Error: STL exception" ) ); + } +} + + + +bool OdbxBackend::get( DNSResourceRecord& rr ) +{ + const char* tmp; + string priority; + + try + { + DLOG( g_log.log( m_myname + " get()", Logger::Debug ) ); + + if( getRecord( READ ) ) + { + + rr.content = ""; + rr.domain_id = 0; + rr.last_modified = 0; + rr.ttl = m_default_ttl; + rr.qname = m_qname; + + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + { + rr.domain_id = strtol( tmp, NULL, 10 ); + } + + if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + { + rr.qname = DNSName( string(tmp, odbx_field_length( m_result, 1 ) )); + } + + if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) + { + rr.qtype = tmp; + } + + if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + { + rr.ttl = strtoul( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) + { + priority = string( tmp, odbx_field_length( m_result, 4 ) ); + } + + if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) + { + rr.content = string( tmp, odbx_field_length( m_result, 5 ) ); + } + + if (rr.qtype==QType::MX || rr.qtype==QType::SRV) + rr.content = priority + " " + rr.content; + + return true; + } + } + catch( std::exception& e ) + { + g_log.log( m_myname + " get: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return false; +} + + +void OdbxBackend::setFresh( uint32_t domain_id ) +{ + int len; + + + try + { + DLOG( g_log.log( m_myname + " setFresh()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error ); + throw( DBException( "Error: Server unreachable" ) ); + } + + len = snprintf( m_buffer, sizeof( m_buffer ), getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id ); + + if( len < 0 ) + { + g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - format error", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - insufficient buffer space", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + if( !execStmt( m_buffer, len, WRITE ) ) + { + throw( DBException( "Error: DB statement failed" ) ); + } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " setFresh: Caught STL exception - " + e.what(), Logger::Error ); + throw( DBException( "Error: STL exception" ) ); + } +} + + + +void OdbxBackend::setNotified( uint32_t domain_id, uint32_t serial ) +{ + try + { + DLOG( g_log.log( m_myname + " setNotified()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error ); + throw( DBException( "Error: Server unreachable" ) ); + } + + int len = snprintf( m_buffer, sizeof( m_buffer ), getArg( "sql-update-serial" ).c_str(), serial, domain_id ); + + if( len < 0 ) + { + g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - format error", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - insufficient buffer space", Logger::Error ); + throw( DBException( "Error: Libc error" ) ); + } + + if( !execStmt( m_buffer, len, WRITE ) ) + { + throw( DBException( "Error: DB statement failed" ) ); + } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " setNotified: Caught STL exception - " + e.what(), Logger::Error ); + throw( DBException( "Error: STL exception" ) ); + } +} + + + +void OdbxBackend::getUnfreshSlaveInfos( vector* unfresh ) +{ + try + { + DLOG( g_log.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) ); + + if( unfresh == NULL ) + { + g_log.log( m_myname + " getUnfreshSlaveInfos: invalid parameter - NULL pointer", Logger::Error ); + return; + } + + getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave ); + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(), Logger::Error ); + } +} + + + +void OdbxBackend::getUpdatedMasters( vector* updated ) +{ + try + { + DLOG( g_log.log( m_myname + " getUpdatedMasters()", Logger::Debug ) ); + + if( updated == NULL ) + { + g_log.log( m_myname + " getUpdatedMasters: invalid parameter - NULL pointer", Logger::Error ); + return; + } + + getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster ); + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(), Logger::Error ); + } +} + + + +bool OdbxBackend::superMasterBackend( const string& ip, const DNSName& domain, const vector& set, string *nameserver, string* account, DNSBackend** ddb ) +{ + try + { + DLOG( g_log.log( m_myname + " superMasterBackend()", Logger::Debug ) ); + + if( account != NULL && ddb != NULL ) + { + vector::const_iterator i; + + for( i = set.begin(); i != set.end(); i++ ) + { + string stmt = getArg( "sql-supermaster" ); + string& stmtref = strbind( ":ip", escape( ip, READ ), stmt ); + stmtref = strbind( ":ns", escape( i->content, READ ), stmtref ); + + if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } + + if( getRecord( READ ) ) + { + if( odbx_field_value( m_result, 0 ) != NULL ) + { + *account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) ); + } + + while( getRecord( READ ) ); + + *ddb=this; + return true; + } + } + } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return false; +} + + + +bool OdbxBackend::createSlaveDomain( const string& ip, const DNSName& domain, const string &nameserver, const string& account ) +{ + try + { + DLOG( g_log.log( m_myname + " createSlaveDomain()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " createSlaveDomain: Master server is unreachable", Logger::Error ); + return false; + } + + int len = snprintf( m_buffer, sizeof( m_buffer ), getArg( "sql-insert-slave" ).c_str(), escape( domain.makeLowerCase().toStringRootDot(), WRITE ).c_str(), + escape( ip, WRITE ).c_str(), escape( account, WRITE ).c_str() ); + + if( len < 0 ) + { + g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - format error", Logger::Error ); + return false; + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - insufficient buffer space", Logger::Error ); + return false; + } + + if( !execStmt( m_buffer, len, WRITE ) ) { return false; } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::feedRecord( const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3 ) +{ + try + { + DLOG( g_log.log( m_myname + " feedRecord()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " feedRecord: Master server is unreachable", Logger::Error ); + return false; + } + + unsigned int priority=0; + string content(rr.content); + + if(rr.qtype == QType::MX || rr.qtype == QType::SRV) { + priority=pdns_stou(content); + string::size_type pos = content.find_first_not_of("0123456789"); + if(pos != string::npos) + boost::erase_head(content, pos); + trim_left(content); + } + + int len = snprintf( m_buffer, sizeof( m_buffer ), getArg( "sql-insert-record" ).c_str(), rr.domain_id, + escape( rr.qname.makeLowerCase().toStringRootDot(), WRITE ).c_str(), rr.qtype.getName().c_str(), rr.ttl, priority, + escape( content, WRITE ).c_str() ); + + if( len < 0 ) + { + g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - format error", Logger::Error ); + return false; + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - insufficient buffer space", Logger::Error ); + return false; + } + + if( !execStmt( m_buffer, len, WRITE ) ) { return false; } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " feedRecord: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::startTransaction( const DNSName& domain, int zoneid ) +{ + try + { + DLOG( g_log.log( m_myname + " startTransaction()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " startTransaction: Master server is unreachable", Logger::Error ); + return false; + } + + string stmtref = getArg( "sql-transactbegin" ); + if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; } + int len = snprintf( m_buffer, sizeof( m_buffer ), "%d", zoneid ); + + if( len < 0 ) + { + g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - format error", Logger::Error ); + return false; + } + + if( len > static_cast(sizeof( m_buffer )) - 1 ) + { + g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); + return false; + } + + if(zoneid >= 0) { + string stmt = getArg( "sql-zonedelete" ); + stmtref = strbind( ":id", string( m_buffer, len ), stmt ); + if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; } + } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " startTransaction: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::commitTransaction() +{ + try + { + DLOG( g_log.log( m_myname + " commitTransaction()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " commitTransaction: Master server is unreachable", Logger::Error ); + return false; + } + + const string& stmt = getArg( "sql-transactend" ); + if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} + + + +bool OdbxBackend::abortTransaction() +{ + try + { + DLOG( g_log.log( m_myname + " abortTransaction()", Logger::Debug ) ); + + if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) + { + g_log.log( m_myname + " abortTransaction: Master server is unreachable", Logger::Error ); + return false; + } + + const string& stmt = getArg( "sql-transactabort" ); + if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; } + } + catch ( std::exception& e ) + { + g_log.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(), Logger::Error ); + return false; + } + + return true; +} diff --git a/modules/opendbxbackend/odbxbackend.hh b/modules/opendbxbackend/odbxbackend.hh new file mode 100644 index 0000000..4a8b910 --- /dev/null +++ b/modules/opendbxbackend/odbxbackend.hh @@ -0,0 +1,180 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#include +#include +#include +#include "pdns/dns.hh" +#include "pdns/utility.hh" +#include "pdns/dnspacket.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/arguments.hh" +#include "pdns/logger.hh" +#include + + +#ifndef ODBXBACKEND_HH +#define ODBXBACKEND_HH + + +#define BUFLEN 512 + + +using std::string; +using std::vector; + + + +bool checkSlave( uint32_t last, uint32_t notified, SOAData* sd, DomainInfo* di ); +bool checkMaster( uint32_t last, uint32_t notified, SOAData* sd, DomainInfo* di ); + + +class OdbxBackend : public DNSBackend +{ + enum QueryType { READ, WRITE }; + + string m_myname; + DNSName m_qname; + int m_default_ttl; + bool m_qlog; + odbx_t* m_handle[2]; + odbx_result_t* m_result; + char m_escbuf[BUFLEN]; + char m_buffer[2*BUFLEN]; + vector m_hosts[2]; + + string escape( const string& str, QueryType type ); + bool connectTo( const vector& host, QueryType type ); + bool getDomainList( const string& query, vector* list, bool (*check_fcn)(uint32_t,uint32_t,SOAData*,DomainInfo*) ); + bool execStmt( const char* stmt, unsigned long length, QueryType type ); + bool getRecord( QueryType type ); + + +public: + + OdbxBackend( const string& suffix="" ); + ~OdbxBackend(); + + void lookup( const QType& qtype, const DNSName& qdomain, DNSPacket* p = 0, int zoneid = -1 ) override; + bool getSOA( const DNSName& domain, SOAData& sd ) override; + bool list( const DNSName& target, int domain_id, bool include_disabled=false ) override; + bool get( DNSResourceRecord& rr ) override; + + bool startTransaction( const DNSName& domain, int domain_id ) override; + bool commitTransaction() override; + bool abortTransaction() override; + + bool getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial=true ) override; + bool feedRecord( const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3=false ) override; + bool createSlaveDomain( const string& ip, const DNSName& domain, const string &nameserver, const string& account ) override; + bool superMasterBackend( const string& ip, const DNSName& domain, const vector& nsset, string *nameserver, string* account, DNSBackend** ddb ) override; + + void getUpdatedMasters( vector* updated ) override; + void getUnfreshSlaveInfos( vector* unfresh ) override; + + void setFresh( uint32_t domain_id ) override; + void setNotified( uint32_t domain_id, uint32_t serial ) override; +}; + + + +class OdbxFactory : public BackendFactory +{ + +public: + + OdbxFactory() : BackendFactory( "opendbx" ) {} + + + void declareArguments( const string &suffix="" ) + { + declare( suffix, "backend", "OpenDBX backend","mysql" ); + declare( suffix, "host-read", "Name or address of one or more DBMS server to read from","127.0.0.1" ); + declare( suffix, "host-write", "Name or address of one or more DBMS server used for updates","127.0.0.1" ); + declare( suffix, "port", "Port the DBMS server are listening to","" ); + declare( suffix, "database", "Database name containing the DNS records","powerdns" ); + declare( suffix, "username","User for connecting to the DBMS","powerdns"); + declare( suffix, "password","Password for connecting to the DBMS",""); + + declare( suffix, "sql-list", "AXFR query", "SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id" ); + + declare( suffix, "sql-lookup", "Lookup query","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"name\"=':name'" ); + declare( suffix, "sql-lookupid", "Lookup query with id","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id AND r.\"name\"=':name'" ); + declare( suffix, "sql-lookuptype", "Lookup query with type","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"name\"=':name' AND r.\"type\"=':type'" ); + declare( suffix, "sql-lookuptypeid", "Lookup query with type and id","SELECT r.\"domain_id\", r.\"name\", r.\"type\", r.\"ttl\", r.\"prio\", r.\"content\" FROM \"records\" r WHERE r.\"domain_id\"=:id AND r.\"name\"=':name' AND r.\"type\"=':type'" ); + declare( suffix, "sql-lookupsoa","Lookup query for SOA record","SELECT d.\"id\", d.\"auto_serial\", r.\"ttl\", r.\"content\" FROM \"records\" r JOIN \"domains\" d ON r.\"domain_id\"=d.\"id\" WHERE r.\"name\"=':name' AND r.\"type\"='SOA' AND d.\"status\"='A'" ); + + declare( suffix, "sql-zonedelete","Delete all records for this zone","DELETE FROM \"records\" WHERE \"domain_id\"=:id" ); + declare( suffix, "sql-zoneinfo","Get domain info","SELECT d.\"id\", d.\"name\", d.\"type\", d.\"master\", d.\"last_check\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"name\"=':name' AND d.\"status\"='A'" ); + + declare( suffix, "sql-transactbegin", "Start transaction", "BEGIN" ); + declare( suffix, "sql-transactend", "Finish transaction", "COMMIT" ); + declare( suffix, "sql-transactabort", "Abort transaction", "ROLLBACK" ); + + declare( suffix, "sql-insert-slave","Add slave domain", "INSERT INTO \"domains\" ( \"name\", \"type\", \"master\", \"account\" ) VALUES ( '%s', 'SLAVE', '%s', '%s' )" ); + declare( suffix, "sql-insert-record","Feed record into table", "INSERT INTO \"records\" ( \"domain_id\", \"name\", \"type\", \"ttl\", \"prio\", \"content\" ) VALUES ( %d, '%s', '%s', %d, %d, '%s' )" ); + + declare( suffix, "sql-update-serial", "Set zone to notified", "UPDATE \"domains\" SET \"notified_serial\"=%d WHERE \"id\"=%d" ); + declare( suffix, "sql-update-lastcheck", "Set time of last check", "UPDATE \"domains\" SET \"last_check\"=%d WHERE \"id\"=%d" ); + + declare( suffix, "sql-master", "Get master record for zone", "SELECT d.\"master\" FROM \"domains\" d WHERE d.\"name\"=':name' AND d.\"status\"='A' AND d.\"type\"='SLAVE'" ); + declare( suffix, "sql-supermaster","Get supermaster info", "SELECT s.\"account\" FROM \"supermasters\" s WHERE s.\"ip\"=':ip' AND s.\"nameserver\"=':ns'" ); + + declare( suffix, "sql-infoslaves", "Get all unfresh slaves", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"last_check\", d.\"notified_serial\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"status\"='A' AND d.\"type\"='SLAVE'" ); + declare( suffix, "sql-infomasters", "Get all updated masters", "SELECT d.\"id\", d.\"name\", d.\"master\", d.\"last_check\", d.\"notified_serial\", d.\"auto_serial\", r.\"content\" FROM \"domains\" d LEFT JOIN \"records\" r ON ( d.\"id\"=r.\"domain_id\" AND r.\"type\"='SOA' ) WHERE d.\"status\"='A' AND d.\"type\"='MASTER'" ); + + declare( suffix, "host", "deprecated, use host-read and host-write instead","" ); + } + + + DNSBackend* make( const string &suffix="" ) + { + return new OdbxBackend( suffix ); + } +}; + + +class OdbxLoader +{ + OdbxFactory factory; + +public: + + OdbxLoader() + { + BackendMakers().report( &factory ); + g_log<< Logger::Info << "[opendbxbackend] This is the opendbx backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } +}; + + +static OdbxLoader odbxloader; + + + +#endif /* ODBXBACKEND_HH */ diff --git a/modules/opendbxbackend/odbxprivate.cc b/modules/opendbxbackend/odbxprivate.cc new file mode 100644 index 0000000..03308d0 --- /dev/null +++ b/modules/opendbxbackend/odbxprivate.cc @@ -0,0 +1,289 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "odbxbackend.hh" + + + +unsigned int odbx_host_index[2] = { 0, 0 }; + + + +bool OdbxBackend::connectTo( const vector& hosts, QueryType type ) +{ + int err; + unsigned int h, i; + int idx = odbx_host_index[type]++ % hosts.size(); + + + if( m_handle[type] != NULL ) + { + odbx_unbind( m_handle[type] ); + odbx_finish( m_handle[type] ); + m_handle[type] = NULL; + } + + if( type == WRITE && getArg( "backend" ) == "sqlite" ) + { + g_log.log( m_myname + " Using same SQLite connection for reading and writing to '" + hosts[odbx_host_index[READ]] + "'", Logger::Notice ); + m_handle[WRITE] = m_handle[READ]; + return true; + } + + for( i = 0; i < hosts.size(); i++ ) + { + h = ( idx + i ) % hosts.size(); + + if( ( err = odbx_init( &(m_handle[type]), getArg( "backend" ).c_str(), hosts[h].c_str(), getArg( "port" ).c_str() ) ) == ODBX_ERR_SUCCESS ) + { + if( ( err = odbx_bind( m_handle[type], getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str(), ODBX_BIND_SIMPLE ) ) == ODBX_ERR_SUCCESS ) + { + g_log.log( m_myname + " Database connection (" + (type ? "write" : "read") + ") to '" + hosts[h] + "' succeeded", Logger::Notice ); + return true; + } + + g_log.log( m_myname + " Unable to bind to database on host " + hosts[h] + " - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + continue; + } + + g_log.log( m_myname + " Unable to connect to server on host " + hosts[h] + " - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + } + + m_handle[type] = NULL; + return false; +} + + + +bool OdbxBackend::execStmt( const char* stmt, unsigned long length, QueryType type ) +{ + int err; + + + DLOG( g_log.log( m_myname + " execStmt()", Logger::Debug ) ); + + if( m_qlog ) { g_log.log( m_myname + " Query: " + stmt, Logger::Info ); } + + if( ( err = odbx_query( m_handle[type], stmt, length ) ) < 0 ) + { + g_log.log( m_myname + " execStmt: Unable to execute query - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + + if( err != -ODBX_ERR_PARAM && odbx_error_type( m_handle[type], err ) > 0 ) { return false; } // ODBX_ERR_PARAM workaround + if( !connectTo( m_hosts[type], type ) ) { return false; } + if( odbx_query( m_handle[type], stmt, length ) < 0 ) { return false; } + } + + if( type == WRITE ) { while( getRecord( type ) ); } + + return true; +} + + + +bool OdbxBackend::getRecord( QueryType type ) +{ + int err = 3; + + + DLOG( g_log.log( m_myname + " getRecord()", Logger::Debug ) ); + + do + { + if( err < 0 ) + { + g_log.log( m_myname + " getRecord: Unable to get next result - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + throw( PDNSException( "Error: odbx_result() failed" ) ); + } + + if( m_result != NULL ) + { + if( err == 3 ) + { + if( ( err = odbx_row_fetch( m_result ) ) < 0 ) + { + g_log.log( m_myname + " getRecord: Unable to get next row - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + throw( PDNSException( "Error: odbx_row_fetch() failed" ) ); + } + + if( err > 0 ) + { +#ifdef VERBOSELOG + unsigned int i; + string fields; + + for( i = 0; i < odbx_column_count( m_result ); i++ ) + { + fields += string( odbx_column_name( m_result, i ) ); + + if( odbx_field_value( m_result, i ) != NULL ) + { + fields += "=" + string( odbx_field_value( m_result, i ) ) + ", "; + } + else + { + fields += "=NULL, "; + } + } + + g_log.log( m_myname + " Values: " + fields, Logger::Error ); +#endif + return true; + } + + } + + odbx_result_free( m_result ); + m_result = NULL; + } + } + while( ( err = odbx_result( m_handle[type], &m_result, NULL, 0 ) ) != 0 ); + + m_result = NULL; + return false; +} + + + +string OdbxBackend::escape( const string& str, QueryType type ) +{ + int err; + unsigned long len = sizeof( m_escbuf ); + + + DLOG( g_log.log( m_myname + " escape(string)", Logger::Debug ) ); + + if( ( err = odbx_escape( m_handle[type], str.c_str(), str.size(), m_escbuf, &len ) ) < 0 ) + { + g_log.log( m_myname + " escape(string): Unable to escape string - " + string( odbx_error( m_handle[type], err ) ), Logger::Error ); + + if( err != -ODBX_ERR_PARAM && odbx_error_type( m_handle[type], err ) > 0 ) { throw( runtime_error( "odbx_escape() failed" ) ); } // ODBX_ERR_PARAM workaround + if( !connectTo( m_hosts[type], type ) ) { throw( runtime_error( "odbx_escape() failed" ) ); } + if( odbx_escape( m_handle[type], str.c_str(), str.size(), m_escbuf, &len ) < 0 ) { throw( runtime_error( "odbx_escape() failed" ) ); } + } + + return string( m_escbuf, len ); +} + + + +bool OdbxBackend::getDomainList( const string& stmt, vector* list, bool (*check_fcn)(uint32_t,uint32_t,SOAData*,DomainInfo*) ) +{ + const char* tmp; + uint32_t nlast, nserial; + + SOAData sd; + + DLOG( g_log.log( m_myname + " getDomainList()", Logger::Debug ) ); + + if( !execStmt( stmt.c_str(), stmt.size(), READ ) ) { return false; } + if( !getRecord( READ ) ) { return false; } + + do + { + DomainInfo di; + nlast = 0; + nserial = 0; + sd.serial = 0; + sd.refresh = 0; + + if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL ) + { + fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd ); + } + + if( !sd.serial && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) + { + sd.serial = strtol( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) + { + nserial = strtol( tmp, NULL, 10 ); + } + + if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) + { + nlast = strtol( tmp, NULL, 10 ); + } + + if( (*check_fcn)( nlast, nserial, &sd, &di ) ) + { + if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) + { + vector masters; + stringtok(masters, string( tmp, odbx_field_length( m_result, 2 )), ", \t" ); + for(const auto& m : masters) + { + di.masters.emplace_back(m, 53); + } + } + + if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) + { + di.zone = DNSName( string(tmp, odbx_field_length( m_result, 1 )) ); + } + + if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) + { + di.id = strtol( tmp, NULL, 10 ); + } + + di.last_check = nlast; + di.notified_serial = nserial; + di.serial = sd.serial; + di.backend = this; + + list->push_back( di ); + } + } + while( getRecord( READ ) ); + + return true; +} + + + +bool checkSlave( uint32_t nlast, uint32_t nserial, SOAData* sd, DomainInfo* di ) +{ + if( nlast + sd->refresh < (uint32_t) time( 0 ) ) + { + di->kind = DomainInfo::Slave; + return true; + } + + return false; +} + + + +bool checkMaster( uint32_t nlast, uint32_t nserial, SOAData* sd, DomainInfo* di ) +{ + if( nserial != sd->serial ) + { + di->kind = DomainInfo::Master; + return true; + } + + return false; +} diff --git a/modules/oraclebackend/ChangeLog b/modules/oraclebackend/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/modules/oraclebackend/INSTALL b/modules/oraclebackend/INSTALL new file mode 100644 index 0000000..e69de29 diff --git a/modules/oraclebackend/Makefile.am b/modules/oraclebackend/Makefile.am new file mode 100644 index 0000000..84c476d --- /dev/null +++ b/modules/oraclebackend/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS += $(ORACLE_CFLAGS) + +pkglib_LTLIBRARIES = liboraclebackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + drop-schema.oracle.sql \ + schema.oracle.sql + +dist_doc_DATA = \ + schema.oracle.sql \ + drop-schema.oracle.sql + +liboraclebackend_la_SOURCES = oraclebackend.cc oraclebackend.hh +liboraclebackend_la_LDFLAGS = -module -avoid-version +liboraclebackend_la_LIBADD = $(ORACLE_LIBS) -lclntsh diff --git a/modules/oraclebackend/Makefile.in b/modules/oraclebackend/Makefile.in new file mode 100644 index 0000000..7f7fef4 --- /dev/null +++ b/modules/oraclebackend/Makefile.in @@ -0,0 +1,860 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/oraclebackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" "$(DESTDIR)$(docdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +liboraclebackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_liboraclebackend_la_OBJECTS = oraclebackend.lo +liboraclebackend_la_OBJECTS = $(am_liboraclebackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +liboraclebackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(liboraclebackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(liboraclebackend_la_SOURCES) +DIST_SOURCES = $(liboraclebackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(dist_doc_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp ChangeLog INSTALL README TODO +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(ORACLE_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = liboraclebackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + drop-schema.oracle.sql \ + schema.oracle.sql + +dist_doc_DATA = \ + schema.oracle.sql \ + drop-schema.oracle.sql + +liboraclebackend_la_SOURCES = oraclebackend.cc oraclebackend.hh +liboraclebackend_la_LDFLAGS = -module -avoid-version +liboraclebackend_la_LIBADD = $(ORACLE_LIBS) -lclntsh +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/oraclebackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/oraclebackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +liboraclebackend.la: $(liboraclebackend_la_OBJECTS) $(liboraclebackend_la_DEPENDENCIES) $(EXTRA_liboraclebackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liboraclebackend_la_LINK) -rpath $(pkglibdir) $(liboraclebackend_la_OBJECTS) $(liboraclebackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oraclebackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-dist_docDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_docDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_docDATA uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/oraclebackend/OBJECTFILES b/modules/oraclebackend/OBJECTFILES new file mode 100644 index 0000000..570c62e --- /dev/null +++ b/modules/oraclebackend/OBJECTFILES @@ -0,0 +1 @@ +oraclebackend.lo diff --git a/modules/oraclebackend/OBJECTLIBS b/modules/oraclebackend/OBJECTLIBS new file mode 100644 index 0000000..e69de29 diff --git a/modules/oraclebackend/README b/modules/oraclebackend/README new file mode 100644 index 0000000..5ae864b --- /dev/null +++ b/modules/oraclebackend/README @@ -0,0 +1,43 @@ +An Oracle Database backend was originally contributed to PowerDNS in +2002 by Stefan Arentz. + +A new version amounting to a complete rewrite was contributed in 2011 by +Maik Zumstrull , then at the Steinbuch Centre for +Computing at the Karlsruhe Institute of +Technology . + +--- + +Licensing + +Any contributions submitted to PowerDNS.COM BV by Maik Zumstrull / SCC are +released under the conditions of the MIT license. Note that additional or +different licensing terms may apply to code as redistributed by +PowerDNS.COM BV. The terms of the license are found below. + +--- + +The MIT License + +Copyright (c) 2010-2011 + Maik Zumstrull + Steinbuch Centre for Computing + Karlsruhe Institute of Technology + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/modules/oraclebackend/TODO b/modules/oraclebackend/TODO new file mode 100644 index 0000000..db61fa5 --- /dev/null +++ b/modules/oraclebackend/TODO @@ -0,0 +1,6 @@ + +Oracle Backend + +todo Clean up our stuff in the destructor + write configure.in stuff + diff --git a/modules/oraclebackend/drop-schema.oracle.sql b/modules/oraclebackend/drop-schema.oracle.sql new file mode 100644 index 0000000..1e4997f --- /dev/null +++ b/modules/oraclebackend/drop-schema.oracle.sql @@ -0,0 +1,23 @@ +DROP PROCEDURE get_hashed_prev_next; +DROP PROCEDURE get_canonical_prev_next; + +DROP FUNCTION dnsname_to_hashname; +DROP FUNCTION base32hex_encode; +DROP FUNCTION dnsname_to_raw; +DROP FUNCTION label_reverse; + +DROP TABLE Records; +DROP SEQUENCE records_id_seq; +DROP TABLE AccessControlList; +DROP TABLE TSIGKeys; +DROP TABLE ZoneDNSKeys; +DROP SEQUENCE zonednskeys_id_seq; +DROP TABLE ZoneMetadata; +DROP TABLE Supermasters; +DROP SEQUENCE supermasters_id_seq; +DROP TABLE Zonemasters; +DROP TABLE ZoneAlsoNotify; +DROP TABLE Zones; +DROP SEQUENCE zones_id_seq; + +-- vi: set sw=2 et : -- diff --git a/modules/oraclebackend/oraclebackend.cc b/modules/oraclebackend/oraclebackend.cc new file mode 100644 index 0000000..b0abaa4 --- /dev/null +++ b/modules/oraclebackend/oraclebackend.cc @@ -0,0 +1,2259 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Maik Zumstrull + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "pdns/namespaces.hh" + +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "oraclebackend.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/lock.hh" + +#include + +static const char *basicQueryKey = "PDNS_Basic_Query"; +static const char *basicQueryDefaultAuthSQL = + "SELECT fqdn, ttl, type, content, zone_id, auth " + "FROM Records " + "WHERE type = :type AND fqdn = lower(:name)"; + +static const char *basicQueryDefaultSQL = "SELECT fqdn, ttl, type, content, zone_id, " + "FROM Records " + "WHERE type = :type AND fqdn = lower(:name)"; + +static const char *basicIdQueryKey = "PDNS_Basic_Id_Query"; +static const char *basicIdQueryDefaultAuthSQL = + "SELECT fqdn, ttl, type, content, zone_id, auth " + "FROM Records " + "WHERE type = :type AND fqdn = lower(:name) AND zone_id = :zoneid"; + +static const char *basicIdQueryDefaultSQL = + "SELECT fqdn, ttl, type, content, zone_id, " + "FROM Records " + "WHERE type = :type AND fqdn = lower(:name) AND zone_id = :zoneid"; + +static const char *anyQueryKey = "PDNS_ANY_Query"; +static const char *anyQueryDefaultAuthSQL = + "SELECT fqdn, ttl, type, content, zone_id, auth " + "FROM Records " + "WHERE fqdn = lower(:name)" + " AND type IS NOT NULL " + "ORDER BY type"; + +static const char *anyQueryDefaultSQL = + "SELECT fqdn, ttl, type, content, zone_id, " + "FROM Records " + "WHERE fqdn = lower(:name)" + " AND type IS NOT NULL " + "ORDER BY type"; + +static const char *anyIdQueryKey = "PDNS_ANY_Id_Query"; +static const char *anyIdQueryDefaultAuthSQL = + "SELECT fqdn, ttl, type, content, zone_id, auth " + "FROM Records " + "WHERE fqdn = lower(:name)" + " AND zone_id = :zoneid" + " AND type IS NOT NULL " + "ORDER BY type"; + +static const char *anyIdQueryDefaultSQL = + "SELECT fqdn, ttl, type, content, zone_id, " + "FROM Records " + "WHERE fqdn = lower(:name)" + " AND zone_id = :zoneid" + " AND type IS NOT NULL " + "ORDER BY type"; + + +static const char *listQueryKey = "PDNS_List_Query"; +static const char *listQueryDefaultAuthSQL = + "SELECT fqdn, ttl, type, content, zone_id, auth " + "FROM Records " + "WHERE zone_id = :zoneid" + " AND type IS NOT NULL " + "ORDER BY fqdn, type"; + +static const char *listQueryDefaultSQL = + "SELECT fqdn, ttl, type, content, zone_id, " + "FROM Records " + "WHERE zone_id = :zoneid" + " AND type IS NOT NULL " + "ORDER BY fqdn, type"; + + +static const char *zoneInfoQueryKey = "PDNS_Zone_Info_Query"; +static const char *zoneInfoQueryDefaultSQL = + "SELECT id, name, type, last_check, serial, notified_serial " + "FROM Zones " + "WHERE name = lower(:name)"; + +static const char *alsoNotifyQueryKey = "PDNS_Also_Notify_Query"; +static const char *alsoNotifyQueryDefaultSQL = + "SELECT an.hostaddr " + "FROM Zones z JOIN ZoneAlsoNotify an ON z.id = an.zone_id " + "WHERE z.name = lower(:name)"; + +static const char *zoneMastersQueryKey = "PDNS_Zone_Masters_Query"; +static const char *zoneMastersQueryDefaultSQL = + "SELECT master " + "FROM Zonemasters " + "WHERE zone_id = :zoneid"; + +static const char *deleteZoneQueryKey = "PDNS_Delete_Zone_Query"; +static const char *deleteZoneQueryDefaultSQL = + "DELETE FROM Records WHERE zone_id = :zoneid"; + +static const char *zoneSetLastCheckQueryKey = "PDNS_Zone_Set_Last_Check_Query"; +static const char *zoneSetLastCheckQueryDefaultSQL = + "UPDATE Zones SET last_check = :lastcheck WHERE id = :zoneid"; + +static const char *zoneSetNotifiedSerialQueryKey = "PDNS_Zone_Set_NSerial_Query"; +static const char *zoneSetNotifiedSerialQueryDefaultSQL = + "UPDATE Zones SET notified_serial = :serial WHERE id = :zoneid"; + +static const char *insertRecordQueryKey = "PDNS_Insert_Record_Query"; +static const char *insertRecordQueryDefaultSQL = + "INSERT INTO Records (id, fqdn, zone_id, ttl, type, content) " + "VALUES (records_id_seq.NEXTVAL, lower(:name), :zoneid, :ttl, :type, :content)"; + +static const char *finalizeAXFRQueryKey = "PDNS_Finalize_AXFR"; +static const char *finalizeAXFRQueryDefaultSQL = + "DECLARE\n" + " zone_id INTEGER := :zoneid;\n" + "BEGIN\n" + " NULL;\n" + "END;"; + +static const char *unfreshZonesQueryKey = "PDNS_Unfresh_Zones_Query"; +static const char *unfreshZonesQueryDefaultSQL = + "SELECT z.id, z.name, z.last_check, z.serial, zm.master " + "FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id " + "WHERE z.type = 'SLAVE' " + " AND (z.last_check IS NULL OR z.last_check + z.refresh < :ts)" + "ORDER BY z.id"; + +static const char *updatedMastersQueryKey = "PDNS_Updated_Masters_Query"; +static const char *updatedMastersQueryDefaultSQL = + "SELECT id, name, serial, notified_serial " + "FROM Zones " + "WHERE type = 'MASTER' " + "AND (notified_serial IS NULL OR notified_serial < serial)"; + +static const char *acceptSupernotificationQueryKey = "PDNS_Accept_Supernotification_Query"; +static const char *acceptSupernotificationQueryDefaultSQL = + "SELECT name " + "FROM Supermasters " + "WHERE ip = :ip AND nameserver = lower(:ns)"; + +static const char *insertSlaveQueryKey = "PDNS_Insert_Slave_Query"; +static const char *insertSlaveQueryDefaultSQL = + "INSERT INTO Zones (id, name, type) " + "VALUES (zones_id_seq.NEXTVAL, lower(:zone), 'SLAVE') " + "RETURNING id INTO :zoneid"; + +static const char *insertMasterQueryKey = "PDNS_Insert_Master_Query"; +static const char *insertMasterQueryDefaultSQL = + "INSERT INTO Zonemasters (zone_id, master) " + "VALUES (:zoneid, :ip)"; + +static const char *prevNextNameQueryKey = "PDNS_Prev_Next_Name_Query"; +static const char *prevNextNameQueryDefaultSQL = + "BEGIN\n" + " get_canonical_prev_next(:zoneid, :name, :prev, :next);\n" + "END;"; + +static const char *prevNextHashQueryKey = "PDNS_Prev_Next_Hash_Query"; +static const char *prevNextHashQueryDefaultSQL = + "BEGIN\n" + " get_hashed_prev_next(:zoneid, :hash, :unhashed, :prev, :next);\n" + "END;"; + +static const char *getAllZoneMetadataQueryKey = "PDNS_Get_All_Zone_Metadata"; +static const char *getAllZoneMetadataQueryDefaultSQL = + "SELECT md.meta_type, md.meta_content " + "FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id " + "WHERE z.name = lower(:name) " + "ORDER BY md.meta_ind"; + +static const char *getZoneMetadataQueryKey = "PDNS_Get_Zone_Metadata"; +static const char *getZoneMetadataQueryDefaultSQL = + "SELECT md.meta_content " + "FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id " + "WHERE z.name = lower(:name) AND md.meta_type = :kind " + "ORDER BY md.meta_ind"; + +static const char *delZoneMetadataQueryKey = "PDNS_Del_Zone_Metadata"; +static const char *delZoneMetadataQueryDefaultSQL = + "DELETE FROM ZoneMetadata md " + "WHERE zone_id = (SELECT id FROM Zones z WHERE z.name = lower(:name)) " + " AND md.meta_type = :kind"; + +static const char *setZoneMetadataQueryKey = "PDNS_Set_Zone_Metadata"; +static const char *setZoneMetadataQueryDefaultSQL = + "INSERT INTO ZoneMetadata (zone_id, meta_type, meta_ind, meta_content) " + "VALUES (" + " (SELECT id FROM Zones WHERE name = lower(:name))," + " :kind, :i, :content" + ")"; + +static const char *getTSIGKeyQueryKey = "PDNS_Get_TSIG_Key"; +static const char *getTSIGKeyQueryDefaultSQL = + "SELECT algorithm, secret " + "FROM TSIGKeys " + "WHERE name = :name"; + +static const char *delTSIGKeyQueryKey = "PDNS_Del_TSIG_Key"; +static const char *delTSIGKeyQueryDefaultSQL = + "DELETE FROM TSIGKeys " + "WHERE name = :name"; + +static const char *setTSIGKeyQueryKey = "PDNS_Set_TSIG_Key"; +static const char *setTSIGKeyQueryDefaultSQL = + "INSERT INTO TSIGKeys (name, algorithm, secret) " + "VALUES (:name, :algorithm, :secret)"; + +static const char *getTSIGKeysQueryKey = "PDNS_Get_TSIG_Keys"; +static const char *getTSIGKeysQueryDefaultSQL = + "SELECT name, algorithm, secret " + "FROM TSIGKeys"; + +static const char *getZoneKeysQueryKey = "PDNS_Get_Zone_Keys"; +static const char *getZoneKeysQueryDefaultSQL = + "SELECT k.id, k.flags, k.active, k.keydata " + "FROM ZoneDNSKeys k JOIN Zones z ON z.id = k.zone_id " + "WHERE z.name = lower(:name)"; + +static const char *delZoneKeyQueryKey = "PDNS_Del_Zone_Key"; +static const char *delZoneKeyQueryDefaultSQL = + "DELETE FROM ZoneDNSKeys WHERE id = :keyid"; + +static const char *addZoneKeyQueryKey = "PDNS_Add_Zone_Key"; +static const char *addZoneKeyQueryDefaultSQL = + "INSERT INTO ZoneDNSKeys (id, zone_id, flags, active, keydata) " + "VALUES (" + " zonednskeys_id_seq.NEXTVAL," + " (SELECT id FROM Zones WHERE name = lower(:name))," + " :flags," + " :active," + " :content" + ") RETURNING id INTO :keyid"; + +static const char *setZoneKeyStateQueryKey = "PDNS_Set_Zone_Key_State"; +static const char *setZoneKeyStateQueryDefaultSQL = + "UPDATE ZoneDNSKeys SET active = :active WHERE id = :keyid"; + + +static void +string_to_cbuf (char *buf, const string& s, size_t bufsize) +{ + if (s.size() >= bufsize) { + throw std::overflow_error("OracleBackend: string does not fit into char buffer"); + } + strncpy(buf, s.c_str(), bufsize); +} + +static void +DNSName_to_cbuf (char *buf, const DNSName& n, size_t bufsize) +{ + string s = toLower(n.toStringNoDot()); + if (s.size() >= bufsize) { + throw std::overflow_error("OracleBackend: DNSName does not fit into char buffer"); + } + strncpy(buf, s.c_str(), bufsize); +} + +OracleBackend::OracleBackend (const string &suffix, OCIEnv *envh, + char *poolname) +{ + setArgPrefix(string("oracle") + suffix); + sword err; + + // Initialize everything in a known state + oraenv = envh; + oraerr = NULL; + pooledSvcCtx = NULL; + masterAuthHandle = NULL; + masterSvcCtx = NULL; + curStmtHandle = NULL; + openTransactionZoneID = -1; + + try + { + d_dnssecQueries = mustDo("dnssec"); + } + catch (ArgException e) + { + d_dnssecQueries = false; + } + + // Process configuration options + string_to_cbuf(myServerName, getArg("nameserver-name"), sizeof(myServerName)); + + if (d_dnssecQueries) { + basicQuerySQL = getArg("basic-query-auth"); + basicIdQuerySQL = getArg("basic-id-query-auth"); + anyQuerySQL = getArg("any-query-auth"); + anyIdQuerySQL = getArg("any-id-query-auth"); + listQuerySQL = getArg("list-query-auth"); + } else { + basicQuerySQL = getArg("basic-query"); + basicIdQuerySQL = getArg("basic-id-query"); + anyQuerySQL = getArg("any-query"); + anyIdQuerySQL = getArg("any-id-query"); + listQuerySQL = getArg("list-query"); + } + + zoneInfoQuerySQL = getArg("zone-info-query"); + alsoNotifyQuerySQL = getArg("also-notify-query"); + zoneMastersQuerySQL = getArg("zone-masters-query"); + deleteZoneQuerySQL = getArg("delete-zone-query"); + zoneSetLastCheckQuerySQL = getArg("zone-set-last-check-query"); + insertRecordQuerySQL = getArg("insert-record-query"); + finalizeAXFRQuerySQL = getArg("finalize-axfr-query"); + unfreshZonesQuerySQL = getArg("unfresh-zones-query"); + updatedMastersQuerySQL = getArg("updated-masters-query"); + acceptSupernotificationQuerySQL = getArg("accept-supernotification-query"); + insertSlaveQuerySQL = getArg("insert-slave-query"); + insertMasterQuerySQL = getArg("insert-master-query"); + zoneSetNotifiedSerialQuerySQL = getArg("zone-set-notified-serial-query"); + prevNextNameQuerySQL = getArg("prev-next-name-query"); + prevNextHashQuerySQL = getArg("prev-next-hash-query"); + getAllZoneMetadataQuerySQL = getArg("get-all-zone-metadata-query"); + getZoneMetadataQuerySQL = getArg("get-zone-metadata-query"); + delZoneMetadataQuerySQL = getArg("del-zone-metadata-query"); + setZoneMetadataQuerySQL = getArg("set-zone-metadata-query"); + getTSIGKeyQuerySQL = getArg("get-tsig-key-query"); + delTSIGKeyQuerySQL = getArg("del-tsig-key-query"); + setTSIGKeyQuerySQL = getArg("set-tsig-key-query"); + getTSIGKeysQuerySQL = getArg("get-tsig-keys-query"); + getZoneKeysQuerySQL = getArg("get-zone-keys-query"); + delZoneKeyQuerySQL = getArg("del-zone-key-query"); + addZoneKeyQuerySQL = getArg("add-zone-key-query"); + setZoneKeyStateQuerySQL = getArg("set-zone-key-state-query"); + + // Allocate an error handle + err = OCIHandleAlloc(oraenv, (void**) &oraerr, + OCI_HTYPE_ERROR, 0, NULL); + if (err == OCI_ERROR) { + throw OracleException("OCIHandleAlloc"); + } + + // Logon to the database + err = OCISessionGet(oraenv, oraerr, &pooledSvcCtx, NULL, (OraText*) poolname, strlen(poolname), NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL); + + if (err == OCI_ERROR) { + throw OracleException("Opening Oracle session", oraerr); + } +} + +void +OracleBackend::openMasterConnection () +{ + sword err; + + if (masterSvcCtx == NULL) { + err = OCIHandleAlloc(oraenv, (void**) &masterAuthHandle, OCI_HTYPE_AUTHINFO, 0, NULL); + if (err == OCI_ERROR) { + throw OracleException("openMasterConnection: allocating auth handle"); + } + + string database = getArg("master-database"); + string username = getArg("master-username"); + string password = getArg("master-password"); + + err = OCIAttrSet(masterAuthHandle, OCI_HTYPE_AUTHINFO, (void*)username.c_str(), username.size(), OCI_ATTR_USERNAME, oraerr); + if (err == OCI_ERROR) { + throw OracleException("openMasterConnection: setting username"); + } + + err = OCIAttrSet(masterAuthHandle, OCI_HTYPE_AUTHINFO, (void*)password.c_str(), password.size(), OCI_ATTR_PASSWORD, oraerr); + if (err == OCI_ERROR) { + throw OracleException("openMasterConnection: setting password"); + } + + err = OCISessionGet(oraenv, oraerr, &masterSvcCtx, masterAuthHandle, + (OraText*)database.c_str(), database.size(), + NULL, 0, NULL, NULL, NULL, OCI_SESSGET_STMTCACHE); + if (err == OCI_ERROR) { + throw OracleException("openMasterConnection OCISessionGet"); + } + } +} + +OracleBackend::~OracleBackend () +{ + Cleanup(); +} + +void +OracleBackend::lookup (const QType &qtype, const DNSName& qname, + DNSPacket *p, int zoneId) +{ + sword rc; + + if (qtype.getCode() != QType::ANY) { + if (zoneId < 0) { + if (curStmtHandle != NULL) throw OracleException("Invalid state"); + curStmtHandle = prepare_query(pooledSvcCtx, basicQuerySQL, basicQueryKey); + curStmtKey = basicQueryKey; + define_fwd_query(curStmtHandle); + bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName)); + bind_str(curStmtHandle, ":type", mQueryType, sizeof(mQueryType)); + } else { + if (curStmtHandle != NULL) throw OracleException("Invalid state"); + curStmtHandle = prepare_query(pooledSvcCtx, basicIdQuerySQL, basicIdQueryKey); + curStmtKey = basicIdQueryKey; + define_fwd_query(curStmtHandle); + bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName)); + bind_str(curStmtHandle, ":type", mQueryType, sizeof(mQueryType)); + bind_int(curStmtHandle, ":zoneid", &mQueryZoneId); + } + } else { + if (zoneId < 0) { + if (curStmtHandle != NULL) throw OracleException("Invalid state"); + curStmtHandle = prepare_query(pooledSvcCtx, anyQuerySQL, anyQueryKey); + curStmtKey = anyQueryKey; + define_fwd_query(curStmtHandle); + bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName)); + } else { + if (curStmtHandle != NULL) throw OracleException("Invalid state"); + curStmtHandle = prepare_query(pooledSvcCtx, anyIdQuerySQL, anyIdQueryKey); + curStmtKey = anyIdQueryKey; + define_fwd_query(curStmtHandle); + bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName)); + bind_int(curStmtHandle, ":zoneid", &mQueryZoneId); + } + } + + DNSName_to_cbuf(mQueryName, qname, sizeof(mQueryName)); + string_to_cbuf(mQueryType, qtype.getName(), sizeof(mQueryType)); + mQueryZoneId = zoneId; + + rc = OCIStmtExecute(pooledSvcCtx, curStmtHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle Lookup", oraerr); + } + + if (rc == OCI_NO_DATA) { + release_query(curStmtHandle, curStmtKey); + curStmtHandle = NULL; + } +} + +bool +OracleBackend::getBeforeAndAfterNames ( + uint32_t zoneId, const DNSName& zone, + const DNSName& name, DNSName& before, DNSName& after) +{ + if(!d_dnssecQueries) + return -1; + + sword rc; + OCIStmt *stmt; + + (void)zone; + + stmt = prepare_query(pooledSvcCtx, prevNextNameQuerySQL, prevNextNameQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str_ind(stmt, ":prev", mResultPrevName, sizeof(mResultPrevName), &mResultPrevNameInd); + bind_str_ind(stmt, ":next", mResultNextName, sizeof(mResultNextName), &mResultNextNameInd); + bind_uint32(stmt, ":zoneid", &zoneId); + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + mResultPrevNameInd = -1; + mResultNextNameInd = -1; + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "Oracle getBeforeAndAfterNames", oraerr + ); + } + + check_indicator(mResultPrevNameInd, false); + check_indicator(mResultNextNameInd, false); + + before = DNSName(mResultPrevName); + after = DNSName(mResultNextName); + + release_query(stmt, prevNextNameQueryKey); + return true; +} + +bool +OracleBackend::getBeforeAndAfterNamesAbsolute(uint32_t zoneId, + const DNSName& name, DNSName& unhashed, DNSName& before, DNSName& after) +{ + if(!d_dnssecQueries) + return -1; + + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, prevNextHashQuerySQL, prevNextHashQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":hash", mQueryName, sizeof(mQueryName)); + bind_str_ind(stmt, ":unhashed", mResultName, sizeof(mResultName), &mResultNameInd); + bind_str_ind(stmt, ":prev", mResultPrevName, sizeof(mResultPrevName), &mResultPrevNameInd); + bind_str_ind(stmt, ":next", mResultNextName, sizeof(mResultNextName), &mResultNextNameInd); + bind_uint32(stmt, ":zoneid", &zoneId); + string_to_cbuf(mQueryName, name.labelReverse().toString(" ", false)), sizeof(mQueryName)); + mResultNameInd = -1; + mResultPrevNameInd = -1; + mResultNextNameInd = -1; + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "Oracle getBeforeAndAfterNamesAbsolute", oraerr + ); + } + + check_indicator(mResultNameInd, false); + check_indicator(mResultPrevNameInd, false); + check_indicator(mResultNextNameInd, false); + + unhashed = DNSName(mResultName); + before = DNSName(boost::replace_all_copy(mResultPrevName," ",".")).labelReverse(); + after = DNSName(boost::replace_all_copy(mResultNextName," ",".")).labelReverse(); + + release_query(stmt, prevNextHashQueryKey); + return true; +} + +vector +OracleBackend::getDomainMasters (const DNSName& domain, int zoneId) +{ + sword rc; + OCIStmt *stmt; + + (void)domain; + + vector masters; + char master[512]; + sb2 master_ind; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, zoneMastersQuerySQL, zoneMastersQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":zoneid", &mQueryZoneId); + + mQueryZoneId = zoneId; + define_output_str(stmt, 1, &master_ind, master, sizeof(master)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle getDomainMasters", oraerr); + } + + while (rc != OCI_NO_DATA) { + check_indicator(master_ind, false); + + masters.push_back(master); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "OracleBackend, fetching next zone master", oraerr + ); + } + } + + release_query(stmt, zoneMastersQueryKey); + + return masters; +} + +bool +OracleBackend::getDomainInfo (const DNSName& domain, DomainInfo &di) +{ + sword rc; + OCIStmt *stmt; + + int zone_id; + sb2 zone_id_ind; + int last_check; + sb2 last_check_ind; + uint32_t serial; + sb2 serial_ind; + uint32_t notified_serial; + sb2 notified_serial_ind; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, zoneInfoQuerySQL, zoneInfoQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + define_output_int(stmt, 1, &zone_id_ind, &zone_id); + define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName)); + define_output_str(stmt, 3, &mResultTypeInd, mResultType, sizeof(mResultType)); + define_output_int(stmt, 4, &last_check_ind, &last_check); + define_output_uint32(stmt, 5, &serial_ind, &serial); + define_output_uint32(stmt, 6, ¬ified_serial_ind, ¬ified_serial); + + DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone)); + bind_str(stmt, ":name", mQueryZone, sizeof(mQueryZone)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle getDomainInfo", oraerr); + } + + if (rc == OCI_NO_DATA) { + release_query(stmt, zoneInfoQueryKey); + return false; + } + + check_indicator(zone_id_ind, false); + check_indicator(mResultNameInd, false); + check_indicator(serial_ind, true); + + if (zone_id < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t"); + + di.id = zone_id; + di.zone = DNSName(mResultName); + di.serial = serial; + di.backend = this; + + check_indicator(mResultTypeInd, false); + if (strcasecmp(mResultType, "NATIVE") == 0) { + di.kind = DomainInfo::Native; + } else if (strcasecmp(mResultType, "MASTER") == 0) { + di.kind = DomainInfo::Master; + check_indicator(notified_serial_ind, false); + di.notified_serial = notified_serial; + } else if (strcasecmp(mResultType, "SLAVE") == 0) { + di.kind = DomainInfo::Slave; + check_indicator(last_check_ind, true); + di.last_check = last_check; + di.masters = getDomainMasters(DNSName(mResultName), zone_id); + } else { + throw OracleException("Unknown zone type in Oracle backend"); + } + + di.kind = DomainInfo::Native; + + release_query(stmt, zoneInfoQueryKey); + return true; +} + +void OracleBackend::alsoNotifies(const DNSName& domain, set *addrs) +{ + sword rc; + OCIStmt *stmt; + + char hostaddr[512]; + sb2 hostaddr_ind; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, alsoNotifyQuerySQL, alsoNotifyQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":name", mQueryZone, sizeof(mQueryZone)); + + DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone)); + + define_output_str(stmt, 1, &hostaddr_ind, hostaddr, sizeof(hostaddr)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle alsoNotifies", oraerr); + } + + while (rc != OCI_NO_DATA) { + check_indicator(hostaddr_ind, false); + + addrs->insert(hostaddr); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "OracleBackend alsoNotifies fetch", oraerr + ); + } + } + + release_query(stmt, alsoNotifyQueryKey); +} + +void +OracleBackend::getUnfreshSlaveInfos (vector* domains) +{ + sword rc; + OCIStmt *stmt; + + struct timeval now; + gettimeofday(&now, NULL); + mQueryTimestamp = now.tv_sec; + + int last_check; + sb2 last_check_ind; + uint32_t serial; + sb2 serial_ind; + char master[512]; + sb2 master_ind; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, unfreshZonesQuerySQL, unfreshZonesQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":ts", &mQueryTimestamp); + define_output_int(stmt, 1, &mResultZoneIdInd, &mResultZoneId); + define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName)); + define_output_int(stmt, 3, &last_check_ind, &last_check); + define_output_uint32(stmt, 4, &serial_ind, &serial); + define_output_str(stmt, 5, &master_ind, master, sizeof(master)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle getUnfreshSlaveInfos", oraerr); + } + + while (rc != OCI_NO_DATA) { + check_indicator(mResultZoneIdInd, false); + check_indicator(mResultNameInd, false); + check_indicator(serial_ind, true); + check_indicator(last_check_ind, true); + int zoneId = mResultZoneId; + + if (mResultZoneId < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t"); + + DomainInfo di; + di.id = mResultZoneId; + di.zone = DNSName(mResultName); + di.last_check = last_check; + di.kind = DomainInfo::Slave; + di.backend = this; + if (serial_ind == 0) { + di.serial = serial; + } + + while (rc != OCI_NO_DATA && zoneId == mResultZoneId) { + check_indicator(master_ind, false); + di.masters.push_back(master); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "OracleBackend, fetching next unfresh slave master", oraerr + ); + } + + check_indicator(mResultZoneIdInd, false); + } + + domains->push_back(di); + } + + release_query(stmt, unfreshZonesQueryKey); +} + +void +OracleBackend::getUpdatedMasters (vector* domains) +{ + sword rc; + OCIStmt *stmt; + + uint32_t serial; + sb2 serial_ind; + uint32_t notified_serial; + sb2 notified_serial_ind; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, updatedMastersQuerySQL, updatedMastersQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + define_output_int(stmt, 1, &mResultZoneIdInd, &mResultZoneId); + define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName)); + define_output_uint32(stmt, 3, &serial_ind, &serial); + define_output_uint32(stmt, 4, ¬ified_serial_ind, ¬ified_serial); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle getUpdatedMasters", oraerr); + } + + while (rc != OCI_NO_DATA) { + check_indicator(mResultZoneIdInd, false); + check_indicator(mResultNameInd, false); + check_indicator(serial_ind, false); + check_indicator(notified_serial_ind, true); + + if (mResultZoneId < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t"); + + DomainInfo di; + di.id = mResultZoneId; + di.zone = DNSName(mResultName); + di.serial = serial; + di.notified_serial = notified_serial; + di.kind = DomainInfo::Master; + di.backend = this; + + domains->push_back(di); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "OracleBackend, fetching next updated master", oraerr + ); + } + } + + release_query(stmt, updatedMastersQueryKey); +} + +void +OracleBackend::setFresh (uint32_t zoneId) +{ + sword rc; + OCIStmt *stmt; + + mQueryZoneId = zoneId; + + struct timeval now; + gettimeofday(&now, NULL); + mQueryTimestamp = now.tv_sec; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setFresh BEGIN", oraerr); + } + + stmt = prepare_query(masterSvcCtx, zoneSetLastCheckQuerySQL, zoneSetLastCheckQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":zoneid", &mQueryZoneId); + bind_int(stmt, ":lastcheck", &mQueryTimestamp); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setFresh", oraerr); + } + + release_query(stmt, zoneSetLastCheckQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc) { + throw OracleException("Oracle setFresh COMMIT", oraerr); + } +} + +void +OracleBackend::setNotified (uint32_t zoneId, uint32_t serial) +{ + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setNotified BEGIN", oraerr); + } + + stmt = prepare_query(masterSvcCtx, zoneSetNotifiedSerialQuerySQL, zoneSetNotifiedSerialQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_uint32(stmt, ":serial", &serial); + bind_uint32(stmt, ":zoneid", &zoneId); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setNotified", oraerr); + } + + release_query(stmt, zoneSetNotifiedSerialQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc) { + throw OracleException("Oracle setNotified COMMIT", oraerr); + } +} + +bool +OracleBackend::list (const DNSName& domain, int zoneId, bool include_disabled) +{ + sword rc; + + // This is only for backends that cannot lookup by zoneId, + // we can discard + (void)domain; + + if (curStmtHandle != NULL) throw OracleException("Invalid state"); + curStmtHandle = prepare_query(pooledSvcCtx, listQuerySQL, listQueryKey); + curStmtKey = listQueryKey; + define_fwd_query(curStmtHandle); + bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_int(curStmtHandle, ":zoneid", &mQueryZoneId); + + mQueryZoneId = zoneId; + + rc = OCIStmtExecute(pooledSvcCtx, curStmtHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle List", oraerr); + } + + if (rc == OCI_SUCCESS || rc == OCI_SUCCESS_WITH_INFO) { + return true; + } + + if (rc == OCI_NO_DATA) { + release_query(curStmtHandle, curStmtKey); + curStmtHandle = NULL; + } + + return false; +} + +bool OracleBackend::get (DNSResourceRecord &rr) +{ + sword rc; + + if (curStmtHandle == NULL) { + return false; + } + + check_indicator(mResultNameInd, false); + check_indicator(mResultTTLInd, false); + check_indicator(mResultTypeInd, true); + check_indicator(mResultContentInd, true); + check_indicator(mResultZoneIdInd, false); + check_indicator(mResultLastChangeInd, false); + if (d_dnssecQueries) + check_indicator(mResultIsAuthInd, false); + + rr.qname = DNSName(mResultName); + rr.ttl = mResultTTL; + rr.qtype = mResultType; + rr.content = mResultContent; + rr.domain_id = mResultZoneId; + rr.last_modified = mResultLastChange; + if (d_dnssecQueries) + rr.auth = mResultIsAuth > 0; + else + rr.auth = 1; + + rc = OCIStmtFetch2(curStmtHandle, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("OracleBackend, fetching next row", oraerr); + } + + if (rc == OCI_NO_DATA) { + release_query(curStmtHandle, curStmtKey); + curStmtHandle = NULL; + } + + return true; +} + +bool +OracleBackend::startTransaction (const DNSName& domain, int zoneId) +{ + sword rc; + OCIStmt *stmt; + + (void)domain; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle startTransaction", oraerr); + } + + if (zoneId >= 0) { + if (openTransactionZoneID >= 0) { + throw OracleException("Attempt to start AXFR during AXFR"); + } + + mQueryZoneId = openTransactionZoneID = zoneId; + + stmt = prepare_query(masterSvcCtx, deleteZoneQuerySQL, deleteZoneQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":zoneid", &mQueryZoneId); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle startTransaction deleteZone", oraerr); + } + + release_query(stmt, deleteZoneQueryKey); + } + + return true; +} + +bool +OracleBackend::feedRecord (const DNSResourceRecord &rr, const DNSName ordername) +{ + sword rc; + OCIStmt *stmt; + + uint32_t ttl; + + stmt = prepare_query(masterSvcCtx, insertRecordQuerySQL, insertRecordQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":zoneid", &mQueryZoneId); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":type", mQueryType, sizeof(mQueryType)); + bind_uint32(stmt, ":ttl", &ttl); + bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent)); + + mQueryZoneId = rr.domain_id; + DNSName_to_cbuf(mQueryName, rr.qname, sizeof(mQueryName)); + ttl = rr.ttl; + string_to_cbuf(mQueryType, rr.qtype.getName(), sizeof(mQueryType)); + string_to_cbuf(mQueryContent, rr.content, sizeof(mQueryContent)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle feedRecord", oraerr); + } + + release_query(stmt, insertRecordQueryKey); + + return true; +} + +bool +OracleBackend::commitTransaction () +{ + sword rc; + OCIStmt *stmt; + + if (openTransactionZoneID >= 0) { + stmt = prepare_query(masterSvcCtx, finalizeAXFRQuerySQL, finalizeAXFRQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_int(stmt, ":zoneid", &openTransactionZoneID); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle commitTransaction finalizeAXFR", oraerr); + } + + release_query(stmt, finalizeAXFRQueryKey); + + openTransactionZoneID = -1; + } + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc) { + throw OracleException("Oracle commitTransaction", oraerr); + } + + return true; +} + +bool +OracleBackend::abortTransaction () +{ + sword err; + + err = OCITransRollback(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (err) { + throw OracleException("Oracle abortTransaction", oraerr); + } + + return true; +} + +bool +OracleBackend::superMasterBackend (const string &ip, const DNSName& domain, + const vector &nsset, + string *nameserver, string *account, + DNSBackend **backend) +{ + sword rc; + OCIStmt *stmt; + + bool result = false; + + (void)domain; + + string_to_cbuf(mQueryAddr, ip, sizeof(mQueryAddr)); + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, acceptSupernotificationQuerySQL, acceptSupernotificationQueryKey); + define_output_str(stmt, 1, &mResultNameInd, mResultName, sizeof(mResultName)); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":ns", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":ip", mQueryAddr, sizeof(mQueryAddr)); + + for (vector::const_iterator i=nsset.begin(); i != nsset.end(); ++i) { + string_to_cbuf(mQueryName, i->content, sizeof(mQueryName)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle superMasterBackend", oraerr); + } + + if (rc != OCI_NO_DATA) { + *account = mResultName; + *backend = this; + result = true; + break; + } + } + + release_query(stmt, acceptSupernotificationQueryKey); + + return result; +} + +bool +OracleBackend::createSlaveDomain(const string &ip, const DNSName& domain, + const string &nameserver, const string &account) +{ + sword rc; + OCIStmt *insertSlaveQueryHandle; + OCIStmt *insertMasterQueryHandle; + + DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone)); + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle createSlaveDomain BEGIN", oraerr); + } + + insertSlaveQueryHandle = prepare_query(masterSvcCtx, insertSlaveQuerySQL, insertSlaveQueryKey); + bind_str_failokay(insertSlaveQueryHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_int(insertSlaveQueryHandle, ":zoneid", &mQueryZoneId); + bind_str(insertSlaveQueryHandle, ":zone", mQueryZone, sizeof(mQueryZone)); + + insertMasterQueryHandle = prepare_query(masterSvcCtx, insertMasterQuerySQL, insertMasterQueryKey); + bind_str_failokay(insertMasterQueryHandle, ":nsname", myServerName, sizeof(myServerName)); + bind_int(insertMasterQueryHandle, ":zoneid", &mQueryZoneId); + bind_str(insertMasterQueryHandle, ":ip", mQueryAddr, sizeof(mQueryAddr)); + + rc = OCIStmtExecute(masterSvcCtx, insertSlaveQueryHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "Oracle createSlaveDomain insertSlave", oraerr); + } + + string_to_cbuf(mQueryAddr, ip, sizeof(mQueryAddr)); + + rc = OCIStmtExecute(masterSvcCtx, insertMasterQueryHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException( + "Oracle createSlaveDomain insertMaster", oraerr); + } + + release_query(insertSlaveQueryHandle, insertSlaveQueryKey); + release_query(insertMasterQueryHandle, insertMasterQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc) { + throw OracleException("Oracle createSlaveDomain COMMIT", oraerr); + } + + return true; +} + +bool +OracleBackend::getAllDomainMetadata (const DNSName& name, std::map >& meta) +{ + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, getAllZoneMetadataQuerySQL, getAllZoneMetadataQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + + define_output_str(stmt, 1, &mResultTypeInd, mResultType, sizeof(mResultType)); + define_output_str(stmt, 2, &mResultContentInd, mResultContent, sizeof(mResultContent)); + + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + while (rc != OCI_NO_DATA) { + if (rc == OCI_ERROR) { + throw OracleException("Oracle getAllDomainMetadata", oraerr); + } + check_indicator(mResultTypeInd, true); + check_indicator(mResultContentInd, true); + + string kind = mResultType; + string content = mResultContent; + if (!isDnssecDomainMetadata(content)) + meta[kind].push_back(content); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + } + + release_query(stmt, getAllZoneMetadataQueryKey); + return true; +} + +bool +OracleBackend::getDomainMetadata (const DNSName& name, const string& kind, + vector& meta) +{ + if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) + return -1; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, getZoneMetadataQuerySQL, getZoneMetadataQueryKey); + bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName)); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType)); + define_output_str(stmt, 1, &mResultContentInd, mResultContent, sizeof(mResultContent)); + + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + string_to_cbuf(mQueryType, kind, sizeof(mQueryType)); + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + while (rc != OCI_NO_DATA) { + if (rc == OCI_ERROR) { + throw OracleException("Oracle getDomainMetadata", oraerr); + } + + check_indicator(mResultContentInd, true); + + string content = mResultContent; + meta.push_back(content); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + } + + release_query(stmt, getZoneMetadataQueryKey); + return true; +} + +bool +OracleBackend::setDomainMetadata(const DNSName& name, const string& kind, + const vector& meta) +{ + if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) + return -1; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainMetadata BEGIN", oraerr); + } + + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + string_to_cbuf(mQueryType, kind, sizeof(mQueryType)); + + stmt = prepare_query(masterSvcCtx, delZoneMetadataQuerySQL, delZoneMetadataQueryKey); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainMetadata DELETE", oraerr); + } + + release_query(stmt, delZoneMetadataQueryKey); + + stmt = prepare_query(masterSvcCtx, setZoneMetadataQuerySQL, setZoneMetadataQueryKey); + + int i = 0; + + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType)); + bind_int(stmt, ":i", &i); + bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent)); + + for (vector::const_iterator it = meta.begin(); it != meta.end(); ++it) { + string_to_cbuf(mQueryContent, *it, sizeof(mQueryContent)); + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainMetadata INSERT", oraerr); + } + i++; + } + + release_query(stmt, setZoneMetadataQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainMetadata COMMIT", oraerr); + } + + return true; +} + +bool +OracleBackend::getTSIGKey (const DNSName& name, DNSName* algorithm, string* content) +{ + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, getTSIGKeyQuerySQL, getTSIGKeyQueryKey); + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + + define_output_str(stmt, 1, &mResultTypeInd, mResultType, sizeof(mResultType)); + define_output_str(stmt, 2, &mResultContentInd, mResultContent, sizeof(mResultContent)); + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + content->clear(); + while (rc != OCI_NO_DATA) { + + if (rc == OCI_ERROR) { + throw OracleException("Oracle getTSIGKey", oraerr); + } + + check_indicator(mResultTypeInd, false); + check_indicator(mResultContentInd, false); + + if(algorithm->empty() || *algorithm==DNSName(mResultType)) { + *algorithm = DNSName(mResultType); + *content = mResultContent; + } + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + } + + release_query(stmt, getTSIGKeyQueryKey); + return !content->empty(); +} + +bool +OracleBackend::delTSIGKey(const DNSName& name) +{ + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + stmt = prepare_query(masterSvcCtx, delTSIGKeyQuerySQL, delTSIGKeyQueryKey); + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle delTSIGKey", oraerr); + } + + release_query(stmt, setTSIGKeyQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + if (rc == OCI_ERROR) { + throw OracleException("Oracle delTSIGKey COMMIT", oraerr); + } + return true; +} + +bool +OracleBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setTSIGKey BEGIN", oraerr); + } + + stmt = prepare_query(masterSvcCtx, delTSIGKeyQuerySQL, delTSIGKeyQueryKey); + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setTSIGKey DELETE", oraerr); + } + + release_query(stmt, delTSIGKeyQueryKey); + + stmt = prepare_query(masterSvcCtx, setTSIGKeyQuerySQL, setTSIGKeyQueryKey); + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + DNSName_to_cbuf(mQueryType, algorithm, sizeof(mQueryType)); + string_to_cbuf(mQueryContent, content, sizeof(mQueryContent)); + + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_str(stmt, ":algorithm", mQueryType, sizeof(mQueryType)); + bind_str(stmt, ":secret", mQueryContent, sizeof(mQueryContent)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setTSIGKey INSERT", oraerr); + } + + release_query(stmt, setTSIGKeyQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setTSIGKey COMMIT", oraerr); + } + + return true; +} + +bool +OracleBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +{ + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, getTSIGKeysQuerySQL, getTSIGKeysQueryKey); + define_output_str(stmt, 1, &mResultNameInd, mResultName, sizeof(mResultName)); + define_output_str(stmt, 2, &mResultTypeInd, mResultType, sizeof(mResultType)); + define_output_str(stmt, 3, &mResultContentInd, mResultContent, sizeof(mResultContent)); + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + while (rc != OCI_NO_DATA) { + if (rc == OCI_ERROR) { + throw OracleException("Oracle getDomainMetadata", oraerr); + } + + check_indicator(mResultNameInd, true); + check_indicator(mResultTypeInd, true); + check_indicator(mResultContentInd, true); + + struct TSIGKey key; + + key.name = DNSName(mResultName); + key.algorithm = DNSName(mResultType); + key.key = mResultContent; + keys.push_back(key); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + } + + release_query(stmt, getTSIGKeyQueryKey); + return true; +} + +bool +OracleBackend::getDomainKeys (const DNSName& name, vector& keys) +{ + if(!d_dnssecQueries) + return -1; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + stmt = prepare_query(pooledSvcCtx, getZoneKeysQuerySQL, getZoneKeysQueryKey); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + + sb2 key_id_ind = 0; + unsigned int key_id = 0; + sb2 key_flags_ind = 0; + uint16_t key_flags = 0; + sb2 key_active_ind = 0; + int key_active = 0; + + define_output_uint(stmt, 1, &key_id_ind, &key_id); + define_output_uint16(stmt, 2, &key_flags_ind, &key_flags); + define_output_int(stmt, 3, &key_active_ind, &key_active); + define_output_str(stmt, 4, &mResultContentInd, mResultContent, sizeof(mResultContent)); + + rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + while (rc != OCI_NO_DATA) { + if (rc == OCI_ERROR) { + throw OracleException("Oracle getDomainKeys", oraerr); + } + + check_indicator(key_id_ind, false); + check_indicator(key_flags_ind, false); + check_indicator(key_active_ind, false); + check_indicator(mResultContentInd, false); + + KeyData kd; + kd.id = key_id; + kd.flags = key_flags; + kd.active = key_active; + kd.content = mResultContent; + keys.push_back(kd); + + rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); + } + + release_query(stmt, getZoneKeysQueryKey); + return true; +} + +bool +OracleBackend::removeDomainKey (const DNSName& name, unsigned int id) +{ + if(!d_dnssecQueries) + return -1; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle removeDomainKey BEGIN", oraerr); + } + + stmt = prepare_query(masterSvcCtx, delZoneKeyQuerySQL, delZoneKeyQueryKey); + bind_uint(stmt, ":keyid", &id); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle removeDomainKey DELETE", oraerr); + } + + release_query(stmt, delZoneKeyQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle removeDomainKey COMMIT", oraerr); + } + + return true; +} + +bool +OracleBackend::addDomainKey (const DNSName& name, const KeyData& key, int64_t& id) +{ + if(!d_dnssecQueries) + return false; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + int key_id = -1; + uint16_t key_flags = key.flags; + int key_active = key.active; + + openMasterConnection(); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle addDomainKey BEGIN", oraerr); + } + + DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName)); + string_to_cbuf(mQueryContent, key.content, sizeof(mQueryContent)); + + stmt = prepare_query(masterSvcCtx, addZoneKeyQuerySQL, addZoneKeyQueryKey); + + bind_int(stmt, ":keyid", &key_id); + bind_str(stmt, ":name", mQueryName, sizeof(mQueryName)); + bind_uint16(stmt, ":flags", &key_flags); + bind_int(stmt, ":active", &key_active); + bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent)); + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle addDomainKey INSERT", oraerr); + } + + release_query(stmt, addZoneKeyQueryKey); + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle addDomainKey COMMIT", oraerr); + } + + id = key_id; + return key_id >= 0; +} + +bool +OracleBackend::setDomainKeyState (const DNSName& name, unsigned int id, int active) +{ + if(!d_dnssecQueries) + return -1; + DomainInfo di; + if (getDomainInfo(name, di) == false) return false; + + sword rc; + OCIStmt *stmt; + + openMasterConnection(); + + stmt = prepare_query(masterSvcCtx, setZoneKeyStateQuerySQL, setZoneKeyStateQueryKey); + bind_uint(stmt, ":keyid", &id); + bind_int(stmt, ":active", &active); + + rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainKeyState BEGIN", oraerr); + } + + rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainKeyState UPDATE", oraerr); + } + + rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT); + + if (rc == OCI_ERROR) { + throw OracleException("Oracle setDomainKeyState COMMIT", oraerr); + } + + release_query(stmt, setZoneKeyStateQueryKey); + return true; +} + +bool +OracleBackend::activateDomainKey (const DNSName& name, unsigned int id) +{ + return setDomainKeyState(name, id, 1); +} + +bool +OracleBackend::deactivateDomainKey (const DNSName& name, unsigned int id) +{ + return setDomainKeyState(name, id, 0); +} + +void +OracleBackend::Cleanup () +{ + sword err; + + if (masterSvcCtx != NULL) { + err = OCITransRollback(masterSvcCtx, oraerr, OCI_DEFAULT); + // No error check, we don't care if ROLLBACK failed + err = OCISessionRelease(masterSvcCtx, oraerr, NULL, 0, OCI_DEFAULT); + if (err == OCI_ERROR) { + throw OracleException("Oracle cleanup, OCISessionRelease (master)", oraerr); + } + masterSvcCtx = NULL; + OCIHandleFree(masterAuthHandle, OCI_HTYPE_AUTHINFO); + masterAuthHandle = NULL; + } + + if (pooledSvcCtx != NULL) { + err = OCITransRollback(pooledSvcCtx, oraerr, OCI_DEFAULT); + // No error check, we don't care if ROLLBACK failed + err = OCISessionRelease(pooledSvcCtx, oraerr, NULL, 0, OCI_DEFAULT); + if (err == OCI_ERROR) { + throw OracleException("Oracle cleanup, OCISessionRelease (pooled)", oraerr); + } + pooledSvcCtx = NULL; + } + + if (oraerr != NULL) { + OCIHandleFree(oraerr, OCI_HTYPE_ERROR); + oraerr = NULL; + } +} + +OCIStmt* +OracleBackend::prepare_query (OCISvcCtx *orasvc, string& code, const char *key) +{ + sword err; + + OCIStmt *handle = NULL; + + err = OCIStmtPrepare2(orasvc, &handle, oraerr, (OraText*) code.c_str(), code.length(), (OraText*) key, strlen(key), OCI_NTV_SYNTAX, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Preparing Oracle statement", oraerr); + } + + return handle; +} + +void +OracleBackend::release_query (OCIStmt *stmt, const char *key) +{ + sword err; + + err = OCIStmtRelease(stmt, oraerr, (OraText*)key, strlen(key), OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Releasing Oracle statement", oraerr); + } +} + +void +OracleBackend::define_output_str (OCIStmt *s, ub4 pos, sb2 *ind, + char *buf, sb4 buflen) +{ + sword err; + OCIDefine *handle = NULL; + + err = OCIDefineByPos(s, &handle, oraerr, pos, buf, buflen, SQLT_STR, + ind, NULL, NULL, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Defining output for Oracle statement", oraerr); + } +} + +void +OracleBackend::define_output_int (OCIStmt *s, ub4 pos, sb2 *ind, int *buf) +{ + sword err; + OCIDefine *handle = NULL; + + err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(int), + SQLT_INT, ind, NULL, NULL, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Defining output for Oracle statement", oraerr); + } +} + +void +OracleBackend::define_output_uint (OCIStmt *s, ub4 pos, sb2 *ind, unsigned int *buf) +{ + sword err; + OCIDefine *handle = NULL; + + err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(unsigned int), + SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Defining output for Oracle statement", oraerr); + } +} + +void +OracleBackend::define_output_uint16 (OCIStmt *s, ub4 pos, sb2 *ind, + uint16_t *buf) +{ + sword err; + OCIDefine *handle = NULL; + + err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(uint16_t), + SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Defining output for Oracle statement", oraerr); + } +} + +void +OracleBackend::define_output_uint32 (OCIStmt *s, ub4 pos, sb2 *ind, + uint32_t *buf) +{ + sword err; + OCIDefine *handle = NULL; + + err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(uint32_t), + SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT); + + if (err == OCI_ERROR) { + throw OracleException("Defining output for Oracle statement", oraerr); + } +} + +void +OracleBackend::check_indicator (sb2 ind, bool null_okay) +{ + if ((!null_okay) && (ind == -1)) { + throw OracleException("Received NULL where a value was expected"); + } + + if ((ind < -1) || (ind > 0)) { + throw OracleException("Return value truncated"); + } +} + +void +OracleBackend::define_fwd_query (OCIStmt *s) +{ + const ub4 n = 100; + sword err = OCIAttrSet(s, OCI_HTYPE_STMT, (void*) &n, sizeof(ub4), + OCI_ATTR_PREFETCH_ROWS, oraerr); + + if (err == OCI_ERROR) { + throw OracleException("Activating row prefetching", oraerr); + } + + define_output_str(s, 1, &mResultNameInd, + mResultName, sizeof(mResultName)); + define_output_uint32(s, 2, &mResultTTLInd, &mResultTTL); + define_output_str(s, 3, &mResultTypeInd, + mResultType, sizeof(mResultType)); + define_output_str(s, 4, &mResultContentInd, + mResultContent, sizeof(mResultContent)); + define_output_int(s, 5, &mResultZoneIdInd, &mResultZoneId); + define_output_int(s, 6, &mResultLastChangeInd, &mResultLastChange); + if (d_dnssecQueries) + define_output_int(s, 7, &mResultIsAuthInd, &mResultIsAuth); +} + +void +OracleBackend::bind_str (OCIStmt *s, const char *name, char *buf, sb4 buflen) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, buflen, SQLT_STR, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_str (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_str_failokay (OCIStmt *s, const char *name, + char *buf, sb4 buflen) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, buflen, SQLT_STR, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + (void)err; +} + +void +OracleBackend::bind_str_ind (OCIStmt *s, const char *name, + char *buf, sb4 buflen, sb2 *ind) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, buflen, SQLT_STR, + ind, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_str_ind (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_int (OCIStmt *s, const char *name, int *buf) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, sizeof(int), SQLT_INT, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_int (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_uint (OCIStmt *s, const char *name, unsigned int *buf) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, sizeof(unsigned int), SQLT_UIN, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_uint (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_uint16 (OCIStmt *s, const char *name, uint16_t *buf) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, sizeof(uint16_t), SQLT_UIN, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_uint16 (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_uint16_ind (OCIStmt *s, const char *name, uint16_t *buf, + sb2 *ind) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, sizeof(uint16_t), SQLT_UIN, + ind, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_uint16_ind (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + +void +OracleBackend::bind_uint32 (OCIStmt *s, const char *name, uint32_t *buf) +{ + sword err; + OCIBind *handle = NULL; + + err = OCIBindByName(s, &handle, oraerr, + (OraText*) name, strlen(name), + buf, sizeof(uint32_t), SQLT_UIN, + NULL, NULL, NULL, 0, NULL, + OCI_DEFAULT); + + if (err == OCI_ERROR) { + string msg; + msg.append("Oracle bind_uint32 (\""); + msg.append(name); + msg.append("\")"); + throw OracleException(msg, oraerr); + } +} + + +class OracleFactory : public BackendFactory +{ +private: + pthread_mutex_t factoryLock; + OCIEnv *oraenv; + OCIError *oraerr; + OCISPool *mSessionPoolHandle; + text *mSessionPoolName; + ub4 mSessionPoolNameLen; + + void CreateSessionPool () + { + sword err; + + try { + // set some environment variables + setenv("ORACLE_HOME", arg()["oracle-home"].c_str(), 1); + setenv("ORACLE_SID", arg()["oracle-sid"].c_str(), 1); + setenv("NLS_LANG", arg()["oracle-nls-lang"].c_str(), 1); + + // Initialize and create the environment + err = OCIEnvCreate(&oraenv, OCI_THREADED, NULL, NULL, + NULL, NULL, 0, NULL); + if (err == OCI_ERROR) { + throw OracleException("OCIEnvCreate"); + } + // Allocate an error handle + err = OCIHandleAlloc(oraenv, (void**) &oraerr, + OCI_HTYPE_ERROR, 0, NULL); + if (err == OCI_ERROR) { + throw OracleException("OCIHandleAlloc"); + } + + const char *dbname = arg()["oracle-pool-database"].c_str(); + const char *dbuser = arg()["oracle-pool-username"].c_str(); + const char *dbpass = arg()["oracle-pool-password"].c_str(); + + ub4 sess_min = arg().asNum("oracle-session-min"); + ub4 sess_max = arg().asNum("oracle-session-max"); + ub4 sess_inc = arg().asNum("oracle-session-inc"); + ub4 get_mode = OCI_SPOOL_ATTRVAL_NOWAIT; + + // Create a session pool + err = OCIHandleAlloc(oraenv, (void**) &mSessionPoolHandle, + OCI_HTYPE_SPOOL, 0, NULL); + if (err == OCI_ERROR) { + throw OracleException("OCIHandleAlloc"); + } + err = OCISessionPoolCreate(oraenv, oraerr, + mSessionPoolHandle, + (OraText **) &mSessionPoolName, + &mSessionPoolNameLen, + (OraText *) dbname, strlen(dbname), + sess_min, sess_max, sess_inc, + (OraText *) dbuser, strlen(dbuser), + (OraText *) dbpass, strlen(dbpass), + OCI_SPC_STMTCACHE | OCI_SPC_HOMOGENEOUS); + if (err == OCI_ERROR) { + throw OracleException("Creating Oracle session pool", oraerr); + } + + // Set session pool NOWAIT + err = OCIAttrSet(mSessionPoolHandle, OCI_HTYPE_SPOOL, &get_mode, 0, OCI_ATTR_SPOOL_GETMODE, oraerr); + if (err == OCI_ERROR) { + throw OracleException("Setting session pool get mode", oraerr); + } + } catch (OracleException &theException) { + g_log << Logger::Critical << "OracleFactory: " + << theException.reason << endl; + Cleanup(); + throw theException; + } + } + + void Cleanup () + { + sword err; + + if (mSessionPoolHandle != NULL) { + try { + err = OCISessionPoolDestroy(mSessionPoolHandle, oraerr, + OCI_SPD_FORCE); + OCIHandleFree(mSessionPoolHandle, OCI_HTYPE_SPOOL); + mSessionPoolHandle = NULL; + if (err == OCI_ERROR) { + throw OracleException("OCISessionPoolDestroy", oraerr); + } + } catch (OracleException &theException) { + g_log << Logger::Error << "Failed to destroy Oracle session pool: " + << theException.reason << endl; + } + } + + if (oraerr != NULL) { + OCIHandleFree(oraerr, OCI_HTYPE_ERROR); + oraerr = NULL; + } + + if (oraenv != NULL) { + OCIHandleFree(oraenv, OCI_HTYPE_ENV); + oraenv = NULL; + } + } + +public: + +OracleFactory () : BackendFactory("oracle") { + pthread_mutex_init(&factoryLock, NULL); + oraenv = NULL; + oraerr = NULL; + mSessionPoolHandle = NULL; + mSessionPoolName = NULL; + mSessionPoolNameLen = 0; + } + + ~OracleFactory () { + Cleanup(); + pthread_mutex_destroy(&factoryLock); + } + + void declareArguments (const string & suffix = "") { + declare(suffix,"home", "Oracle home path", ""); + declare(suffix,"sid", "Oracle sid", "XE"); + declare(suffix,"nls-lang", "Oracle language", "AMERICAN_AMERICA.AL32UTF8"); + + declare(suffix, "pool-database", "Database to connect to for the session pool", "powerdns"); + declare(suffix, "pool-username", "Username to connect as for the session pool", "powerdns"); + declare(suffix, "pool-password", "Password to connect with for the session pool", ""); + declare(suffix, "session-min", "Number of sessions to open at startup", "4"); + declare(suffix, "session-inc", "Number of sessions to open when growing", "2"); + declare(suffix, "session-max", "Max number of sessions to have open", "20"); + declare(suffix, "master-database", "Database to connect to for write access", "powerdns"); + declare(suffix, "master-username", "Username to connect as for write access", "powerdns"); + declare(suffix, "master-password", "Password to connect with for write access", ""); + declare(suffix, "dnssec", "Assume DNSSEC Schema is in place", "no"); + declare(suffix, "nameserver-name", "", ""); + + declare(suffix, "basic-query", "", basicQueryDefaultSQL); + declare(suffix, "basic-query-auth", "", basicQueryDefaultAuthSQL); + declare(suffix, "basic-id-query", "", basicIdQueryDefaultSQL); + declare(suffix, "basic-id-query-auth", "", basicIdQueryDefaultAuthSQL); + declare(suffix, "any-query", "", anyQueryDefaultSQL); + declare(suffix, "any-query-auth", "", anyQueryDefaultAuthSQL); + declare(suffix, "any-id-query", "", anyIdQueryDefaultSQL); + declare(suffix, "any-id-query-auth", "", anyIdQueryDefaultAuthSQL); + declare(suffix, "list-query", "", listQueryDefaultSQL); + declare(suffix, "list-query-auth", "", listQueryDefaultAuthSQL); + declare(suffix, "zone-info-query", "", zoneInfoQueryDefaultSQL); + declare(suffix, "also-notify-query", "", alsoNotifyQueryDefaultSQL); + declare(suffix, "zone-masters-query", "", zoneMastersQueryDefaultSQL); + declare(suffix, "delete-zone-query", "", deleteZoneQueryDefaultSQL); + declare(suffix, "zone-set-last-check-query", "", zoneSetLastCheckQueryDefaultSQL); + declare(suffix, "zone-set-notified-serial-query", "", zoneSetNotifiedSerialQueryDefaultSQL); + declare(suffix, "insert-record-query", "", insertRecordQueryDefaultSQL); + declare(suffix, "finalize-axfr-query", "", finalizeAXFRQueryDefaultSQL); + declare(suffix, "unfresh-zones-query", "", unfreshZonesQueryDefaultSQL); + declare(suffix, "updated-masters-query", "", updatedMastersQueryDefaultSQL); + declare(suffix, "accept-supernotification-query", "", acceptSupernotificationQueryDefaultSQL); + declare(suffix, "insert-slave-query", "", insertSlaveQueryDefaultSQL); + declare(suffix, "insert-master-query", "", insertMasterQueryDefaultSQL); + declare(suffix, "prev-next-name-query", "", prevNextNameQueryDefaultSQL); + declare(suffix, "prev-next-hash-query", "", prevNextHashQueryDefaultSQL); + + declare(suffix, "get-all-zone-metadata-query", "", getAllZoneMetadataQueryDefaultSQL); + declare(suffix, "get-zone-metadata-query", "", getZoneMetadataQueryDefaultSQL); + declare(suffix, "del-zone-metadata-query", "", delZoneMetadataQueryDefaultSQL); + declare(suffix, "set-zone-metadata-query", "", setZoneMetadataQueryDefaultSQL); + + declare(suffix, "get-tsig-key-query", "", getTSIGKeyQueryDefaultSQL); + declare(suffix, "del-tsig-key-query", "", delTSIGKeyQueryDefaultSQL); + declare(suffix, "set-tsig-key-query", "", setTSIGKeyQueryDefaultSQL); + declare(suffix, "get-tsig-keys-query", "", getTSIGKeysQueryDefaultSQL); + + declare(suffix, "get-zone-keys-query", "", getZoneKeysQueryDefaultSQL); + declare(suffix, "del-zone-key-query", "", delZoneKeyQueryDefaultSQL); + declare(suffix, "add-zone-key-query", "", addZoneKeyQueryDefaultSQL); + declare(suffix, "set-zone-key-state-query", "", setZoneKeyStateQueryDefaultSQL); + } + + DNSBackend *make (const string & suffix = "") { + { + Lock l(&factoryLock); + if (oraenv == NULL) { + CreateSessionPool(); + } + } + return new OracleBackend(suffix, oraenv, + (char *) mSessionPoolName); + } + +}; + + +//! Magic class that is activated when the dynamic library is loaded +class OracleLoader +{ +public: + + OracleLoader() + { + BackendMakers().report(new OracleFactory); + g_log << Logger::Info << "[oraclebackend] This is the oracle backend version " VERSION +#ifndef REPRODUCIBLE + << " (" __DATE__ " " __TIME__ ")" +#endif + << " reporting" << endl; + } + +}; + +static OracleLoader loader; + +/* vi: set sw=2 et : */ diff --git a/modules/oraclebackend/oraclebackend.hh b/modules/oraclebackend/oraclebackend.hh new file mode 100644 index 0000000..c846897 --- /dev/null +++ b/modules/oraclebackend/oraclebackend.hh @@ -0,0 +1,219 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * originally authored by Maik Zumstrull + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_ORACLEBACKEND_HH +#define PDNS_ORACLEBACKEND_HH + +#include +#include +#include + +#include + +#include "pdns/namespaces.hh" + +class OracleException : public DBException +{ +public: + + OracleException (string r) : DBException(r) {} + + OracleException (string context, OCIError *theErrorHandle) + : DBException(context + ": ORA-UNKNOWN") + { + if (theErrorHandle != NULL) { + char msg[2048]; + sb4 errcode = 0; + + msg[0] = '\0'; + + OCIErrorGet((void *) theErrorHandle, 1, NULL, &errcode, (OraText*) msg, + sizeof(msg), OCI_HTYPE_ERROR); + + reason = context + ": " + msg; + } + } + +}; + +class OracleBackend : public DNSBackend +{ +public: + + OracleBackend(const string &suffix = "", OCIEnv *envh = + NULL, char *poolname = NULL); + virtual ~OracleBackend(); + + void lookup(const QType &qtype, const DNSName& qname, DNSPacket *p = 0, + int zoneId = -1) override; + + bool getBeforeAndAfterNames(uint32_t zoneId, const DNSName& zone, + const DNSName& name, + DNSName& before, DNSName& after) override; + bool getBeforeAndAfterNamesAbsolute(uint32_t zoneId, + const DNSName& name, + DNSName& unhashed, + DNSName& before, + DNSName& after) override; + bool get(DNSResourceRecord &rr) override; + vector getDomainMasters(const DNSName& domain, int zoneId) override; + bool getDomainInfo(const DNSName& domain, DomainInfo &di) override; + void alsoNotifies(const DNSName& domain, set *addrs) override; + void getUnfreshSlaveInfos(vector* domains) override; + void getUpdatedMasters(vector* domains) override; + void setFresh(uint32_t zoneId) override; + void setNotified(uint32_t zoneId, uint32_t serial) override; + bool list(const DNSName& domain, int zoneId, bool include_disabled=false) override; + bool startTransaction(const DNSName& domain, int zoneId) override; + bool feedRecord(const DNSResourceRecord &rr, const DNSName ordername) override; + bool commitTransaction() override; + bool abortTransaction() override; + bool superMasterBackend(const string &ip, const DNSName& domain, + const vector &nsset, + string *account, string *nameserver, + DNSBackend **backend) override; + bool createSlaveDomain(const string &ip, const DNSName& domain, + const string &nameserver, const string &account) override; + + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; + + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; + bool delTSIGKey(const DNSName& name) override; + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; + bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + + bool getDomainKeys(const DNSName& name, vector& keys) override; + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + +private: + + OCIEnv *oraenv; + OCIError *oraerr; + OCISvcCtx *pooledSvcCtx; + OCIAuthInfo *masterAuthHandle; + OCISvcCtx *masterSvcCtx; + + string basicQuerySQL; + string basicIdQuerySQL; + string anyQuerySQL; + string anyIdQuerySQL; + string listQuerySQL; + + string zoneInfoQuerySQL; + string alsoNotifyQuerySQL; + string zoneMastersQuerySQL; + string deleteZoneQuerySQL; + string zoneSetLastCheckQuerySQL; + + string insertRecordQuerySQL; + string finalizeAXFRQuerySQL; + + string unfreshZonesQuerySQL; + string updatedMastersQuerySQL; + string acceptSupernotificationQuerySQL; + string insertSlaveQuerySQL; + string insertMasterQuerySQL; + string zoneSetNotifiedSerialQuerySQL; + + string prevNextNameQuerySQL; + string prevNextHashQuerySQL; + + string getAllZoneMetadataQuerySQL; + string getZoneMetadataQuerySQL; + string delZoneMetadataQuerySQL; + string setZoneMetadataQuerySQL; + + string getTSIGKeyQuerySQL; + string delTSIGKeyQuerySQL; + string setTSIGKeyQuerySQL; + string getTSIGKeysQuerySQL; + + string getZoneKeysQuerySQL; + string delZoneKeyQuerySQL; + string addZoneKeyQuerySQL; + string setZoneKeyStateQuerySQL; + + OCIStmt *curStmtHandle; + const char *curStmtKey; + int openTransactionZoneID; + + char myServerName[512]; + + char mQueryName[512]; + char mQueryType[64]; + char mQueryContent[4001]; + char mQueryZone[512]; + char mQueryAddr[64]; + int mQueryZoneId; + int mQueryTimestamp; + + char mResultName[512]; + sb2 mResultNameInd; + uint32_t mResultTTL; + sb2 mResultTTLInd; + char mResultType[64]; + sb2 mResultTypeInd; + char mResultContent[4001]; + sb2 mResultContentInd; + int mResultZoneId; + sb2 mResultZoneIdInd; + int mResultLastChange; + sb2 mResultLastChangeInd; + int mResultIsAuth; + sb2 mResultIsAuthInd; + char mResultPrevName[512]; + sb2 mResultPrevNameInd; + char mResultNextName[512]; + sb2 mResultNextNameInd; + bool d_dnssecQueries; + + void Cleanup(); + + void openMasterConnection(); + bool setDomainKeyState(const DNSName& name, unsigned int id, int active); + + OCIStmt* prepare_query (OCISvcCtx* orasvc, string& code, const char *key); + void release_query (OCIStmt *stmt, const char *key); + void define_output_str (OCIStmt *s, ub4 pos, sb2 *ind, char *buf, sb4 buflen); + void define_output_int (OCIStmt *s, ub4 pos, sb2 *ind, int *buf); + void define_output_uint (OCIStmt *s, ub4 pos, sb2 *ind, unsigned int *buf); + void define_output_uint16 (OCIStmt *s, ub4 pos, sb2 *ind, uint16_t *buf); + void define_output_uint32 (OCIStmt *s, ub4 pos, sb2 *ind, uint32_t *buf); + void check_indicator (sb2 ind, bool null_okay); + void define_fwd_query (OCIStmt *s); + void bind_str (OCIStmt *s, const char *name, char *buf, sb4 buflen); + void bind_str_failokay (OCIStmt *s, const char *name, char *buf, sb4 buflen); + void bind_str_ind (OCIStmt *s, const char *name, char *buf, sb4 buflen, sb2 *ind); + void bind_int (OCIStmt *s, const char *name, int *buf); + void bind_uint (OCIStmt *s, const char *name, unsigned int *buf); + void bind_uint16 (OCIStmt *s, const char *name, uint16_t *buf); + void bind_uint16_ind (OCIStmt *s, const char *name, uint16_t *buf, sb2 *ind); + void bind_uint32 (OCIStmt *s, const char *name, uint32_t *buf); + +}; + +#endif /* PDNS_ORACLEBACKEND_HH */ diff --git a/modules/oraclebackend/schema.oracle.sql b/modules/oraclebackend/schema.oracle.sql new file mode 100644 index 0000000..3b4f520 --- /dev/null +++ b/modules/oraclebackend/schema.oracle.sql @@ -0,0 +1,484 @@ +-- THIS IS NOT PRODUCTION-QUALITY CODE +-- +-- This database schema is meant to serve as documentation-by-example for how +-- certain things might be done. It has also been used for early testing of the +-- backend. It should not be deployed as-is. + +CREATE SEQUENCE zones_id_seq; + +CREATE TABLE Zones ( + id INTEGER CONSTRAINT pkey_zones PRIMARY KEY, + name VARCHAR2(512) NOT NULL, + type VARCHAR2(32) NOT NULL, + last_check INTEGER, + refresh NUMBER(10,0), + serial NUMBER(10,0) DEFAULT 0 NOT NULL, + notified_serial NUMBER(10,0), + CONSTRAINT chk_zones_name CHECK (name = lower(name)), + CONSTRAINT unq_zones_name UNIQUE (name), + CONSTRAINT chk_zones_type CHECK ( + type IN ('NATIVE', 'MASTER', 'SLAVE') + AND (type = 'SLAVE' OR last_check IS NULL) + ), + CONSTRAINT chk_zones_serial CHECK (serial BETWEEN 0 AND 4294967295), + CONSTRAINT chk_zones_nserial CHECK (notified_serial BETWEEN 0 AND 4294967295), + CONSTRAINT chk_zones_refresh CHECK (refresh BETWEEN 0 AND 4294967295), + CONSTRAINT chk_zones_master CHECK (type = 'MASTER' OR notified_serial IS NULL) +); + +CREATE INDEX zones_type_ind ON Zones (type); + + +CREATE TABLE Zonemasters ( + zone_id INTEGER NOT NULL CONSTRAINT fkey_zonemasters_zones REFERENCES Zones ON DELETE CASCADE, + master VARCHAR2(512) NOT NULL, + CONSTRAINT unq_zonemasters_zone_master UNIQUE (zone_id, master) +); + +CREATE INDEX zonemasters_zone_id_ind ON Zonemasters (zone_id); + + +CREATE TABLE ZoneAlsoNotify ( + zone_id INTEGER NOT NULL CONSTRAINT fkey_zonealsonotify_zones REFERENCES Zones ON DELETE CASCADE, + hostaddr VARCHAR2(512) NOT NULL, + CONSTRAINT unq_zonealsonotify_zone_host UNIQUE (zone_id, hostaddr) +); + +CREATE INDEX zonealsonotify_zone_id_ind ON ZoneAlsoNotify (zone_id); + + +CREATE SEQUENCE supermasters_id_seq; + +CREATE TABLE Supermasters ( + id INTEGER CONSTRAINT pkey_supermasters PRIMARY KEY, + name VARCHAR2(64) NOT NULL, + ip VARCHAR2(64) NOT NULL, + nameserver VARCHAR2(512) NOT NULL +); + +CREATE INDEX supermasters_ip_ind ON Supermasters (ip); + + +CREATE TABLE ZoneMetadata ( + zone_id INTEGER NOT NULL CONSTRAINT fkey_zonemetadata_zones REFERENCES Zones, + meta_type VARCHAR2(64) NOT NULL, + meta_ind INTEGER NOT NULL, + meta_content VARCHAR2(4000), + CONSTRAINT pkey_zonemetadata PRIMARY KEY (zone_id, meta_type, meta_ind) +); + + +CREATE SEQUENCE zonednskeys_id_seq; + +CREATE TABLE ZoneDNSKeys ( + id INTEGER CONSTRAINT pkey_zonednskeys PRIMARY KEY, + zone_id INTEGER NOT NULL CONSTRAINT fkey_zonednskeys_zones REFERENCES Zones, + flags NUMBER(5,0) NOT NULL, + active NUMBER(1,0) NOT NULL, + keydata VARCHAR2(4000) NOT NULL, + CONSTRAINT chk_zonednskeys_flags CHECK (flags BETWEEN 0 AND 65535), + CONSTRAINT chk_zonednskeys_active CHECK (active IN (0, 1)) +); + +CREATE INDEX zonednskeys_zone_ind ON ZoneDNSKeys (zone_id); + + +CREATE TABLE TSIGKeys ( + name VARCHAR2(256), + algorithm VARCHAR2(64) NOT NULL, + secret VARCHAR2(2048) NOT NULL, + CONSTRAINT chk_tsigkeys_name CHECK (name = lower(name)), + CONSTRAINT chk_tsigkeys_algorithm CHECK (algorithm = lower(algorithm)), + CONSTRAINT unq_tsigkeys_nav UNIQUE (name, algorithm, secret) +); + + +CREATE TABLE AccessControlList ( + acl_type VARCHAR2(64) NOT NULL, + acl_key VARCHAR2(256) NOT NULL, + acl_val VARCHAR2(2048), + CONSTRAINT chk_acl_type CHECK (acl_type = 'allow-axfr'), + CONSTRAINT unq_acl_tkv UNIQUE (acl_type, acl_key, acl_val) +); + +CREATE INDEX acl_tk ON AccessControlList (acl_type, acl_key); + + +CREATE SEQUENCE records_id_seq; + +CREATE TABLE Records ( + id INTEGER CONSTRAINT pkey_records PRIMARY KEY, + zone_id INTEGER NOT NULL CONSTRAINT fkey_records_zones REFERENCES Zones, + fqdn VARCHAR2(512) NOT NULL, + revfqdn VARCHAR2(512) NOT NULL, + fqdnhash VARCHAR2(512), + ttl NUMBER(10,0) NOT NULL, + type VARCHAR2(32), + content VARCHAR2(2048), + auth NUMBER(1,0) DEFAULT 1 NOT NULL, + CONSTRAINT chk_records_fqdn CHECK (fqdn = lower(fqdn)), + CONSTRAINT chk_records_ttl CHECK (ttl BETWEEN 0 AND 4294967295), + CONSTRAINT chk_records_type CHECK (type = upper(type)), + CONSTRAINT unq_records_zntc UNIQUE (zone_id, fqdn, type, content), + CONSTRAINT chk_records_tc CHECK ( + content IS NOT NULL OR + type IN('NS', 'CNAME') OR + type IS NULL + ), + CONSTRAINT chk_records_auth CHECK (auth IN (0, 1)) +); + +CREATE INDEX records_zone_id_ind ON Records (zone_id); +CREATE INDEX records_revfqdn_ind ON Records (zone_id, revfqdn); +CREATE INDEX records_fqdnhash_ind ON Records (zone_id, fqdnhash); +CREATE INDEX records_last_change_ind ON Records (last_change); + +-- Only one SOA and NSEC3PARAM record per zone +CREATE UNIQUE INDEX records_zonesoa_unq_ind ON Records ( + CASE + WHEN type IN ('SOA', 'NSEC3PARAM') THEN zone_id + ELSE NULL + END, + CASE + WHEN type IN ('SOA', 'NSEC3PARAM') THEN type + ELSE NULL + END +); + + +CREATE FUNCTION label_reverse (dnsname IN VARCHAR2) RETURN VARCHAR2 AS + pattern VARCHAR2(32) := '[^.]+'; + match BINARY_INTEGER := 1; + label VARCHAR2(63); + out_dnsname VARCHAR2(512); +BEGIN + label := REGEXP_SUBSTR(dnsname, pattern, 1, match); + match := match + 1; + out_dnsname := label; + LOOP + label := REGEXP_SUBSTR(dnsname, pattern, 1, match); + EXIT WHEN label IS NULL; + out_dnsname := label || ' ' || out_dnsname; + match := match + 1; + END LOOP; + RETURN(out_dnsname); +END; +/ + +SHOW ERRORS + +CREATE FUNCTION dnsname_to_raw (in_dnsname IN VARCHAR2) RETURN RAW AS + dnsname VARCHAR2(512) := LOWER(in_dnsname); + rawname RAW(512); + + lpos BINARY_INTEGER := 1; + rpos BINARY_INTEGER; + label VARCHAR2(63); + + TYPE convarray IS VARRAY(64) OF RAW(1); + byteval convarray := convarray( + '00', '01', '02', '03', '04', '05', '06', '07', + '08', '09', '0A', '0B', '0C', '0D', '0E', '0F', + '10', '11', '12', '13', '14', '15', '16', '17', + '18', '19', '1A', '1B', '1C', '1D', '1E', '1F', + '20', '21', '22', '23', '24', '25', '26', '27', + '28', '29', '2A', '2B', '2C', '2D', '2E', '2F', + '30', '31', '32', '33', '34', '35', '36', '37', + '38', '39', '3A', '3B', '3C', '3D', '3E', '3F' + ); +BEGIN + IF dnsname IS NULL THEN + RETURN('00'); + END IF; + + WHILE lpos <= LENGTH(dnsname) LOOP + rpos := INSTR(dnsname, '.', lpos); + IF rpos = 0 THEN + rpos := LENGTH(dnsname) + 1; + END IF; + label := SUBSTR(dnsname, lpos, rpos - lpos); + rawname := UTL_RAW.CONCAT( + rawname, + byteval(LENGTH(label) + 1), + UTL_I18N.STRING_TO_RAW(label, 'US7ASCII') + ); + lpos := rpos + 1; + END LOOP; + + IF rpos = LENGTH(dnsname) THEN + rawname := UTL_RAW.CONCAT(rawname, '00'); + END IF; + + RETURN(rawname); +END; +/ + +SHOW ERRORS + +-- This is clearly terrible, though it appears to work. +-- For real deployment, you could upload the dnsjava +-- library into your database and use its facilities. +CREATE FUNCTION base32hex_encode ( + in_string RAW +) RETURN VARCHAR2 AS + off BINARY_INTEGER := 1; + out_string VARCHAR2(6554); + sub RAW(5); + num INTEGER; + TYPE convarray IS VARRAY(32) OF VARCHAR2(1); + digit convarray := convarray( + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v' + ); +BEGIN + + WHILE off + 4 <= UTL_RAW.LENGTH(in_string) LOOP + sub := UTL_RAW.SUBSTR(in_string, off, 2); + num := TO_NUMBER(sub, 'XXXX'); + out_string := out_string + || digit(FLOOR(num / 2048) + 1) + || digit(FLOOR(MOD(num / 64, 32)) + 1) + || digit(FLOOR(MOD(num / 2, 32)) + 1); + sub := UTL_RAW.SUBSTR(in_string, off + 1, 3); + num := TO_NUMBER(sub, 'XXXXXX'); + out_string := out_string + || digit(FLOOR(MOD(num / 4096, 32)) + 1) + || digit(FLOOR(MOD(num / 128, 32)) + 1) + || digit(FLOOR(MOD(num / 4, 32)) + 1); + sub := UTL_RAW.SUBSTR(in_string, off + 3, 2); + num := TO_NUMBER(sub, 'XXXX'); + out_string := out_string + || digit(FLOOR(MOD(num / 32, 32)) + 1) + || digit(FLOOR(MOD(num, 32)) + 1); + off := off + 5; + END LOOP; + + IF off <= UTL_RAW.LENGTH(in_string) THEN + sub := UTL_RAW.SUBSTR(in_string, off); + CASE UTL_RAW.LENGTH(sub) + WHEN 1 THEN + num := TO_NUMBER(sub, 'XX'); + out_string := out_string + || digit(FLOOR(num / 8) + 1) + || digit(FLOOR(MOD(num, 8)) * 4 + 1); + WHEN 2 THEN + num := TO_NUMBER(sub, 'XXXX'); + out_string := out_string + || digit(FLOOR(num / 2048) + 1) + || digit(FLOOR(MOD(num / 64, 32)) + 1) + || digit(FLOOR(MOD(num / 2, 32)) + 1) + || digit(FLOOR(MOD(num, 2)) * 16 + 1); + WHEN 3 THEN + num := TO_NUMBER(sub, 'XXXXXX'); + out_string := out_string + || digit(FLOOR(num / 524288) + 1) + || digit(FLOOR(MOD(num / 16384, 32)) + 1) + || digit(FLOOR(MOD(num / 512, 32)) + 1) + || digit(FLOOR(MOD(num / 16, 32)) + 1) + || digit(FLOOR(MOD(num, 16)) * 2 + 1); + WHEN 4 THEN + num := TO_NUMBER(sub, 'XXXXXXXX'); + out_string := out_string + || digit(FLOOR(num / 134217728) + 1) + || digit(FLOOR(MOD(num / 4194304, 32)) + 1) + || digit(FLOOR(MOD(num / 131072, 32)) + 1) + || digit(FLOOR(MOD(num / 4096, 32)) + 1) + || digit(FLOOR(MOD(num / 128, 32)) + 1) + || digit(FLOOR(MOD(num / 4, 32)) + 1) + || digit(FLOOR(MOD(num, 4)) * 8 + 1); + END CASE; + END IF; + + RETURN(out_string); +END; +/ + +SHOW ERRORS + +CREATE FUNCTION dnsname_to_hashname ( + in_dnsname IN VARCHAR2, + salt RAW, + itercnt BINARY_INTEGER +) RETURN VARCHAR2 AS + rawname RAW(512) := dnsname_to_raw(RTRIM(in_dnsname, '.') || '.'); + rawsalt RAW(32) := salt; + hashname RAW(64); + iter BINARY_INTEGER := 0; +BEGIN + hashname := UTL_RAW.CONCAT(rawname, rawsalt); + hashname := DBMS_CRYPTO.HASH(hashname, DBMS_CRYPTO.HASH_SH1); + WHILE iter < itercnt LOOP + hashname := UTL_RAW.CONCAT(hashname, rawsalt); + hashname := DBMS_CRYPTO.HASH(hashname, DBMS_CRYPTO.HASH_SH1); + iter := iter + 1; + END LOOP; + RETURN(base32hex_encode(hashname)); +END; +/ + +SHOW ERRORS + +CREATE PROCEDURE get_canonical_prev_next ( + in_zone_id INTEGER, + in_fqdn VARCHAR2, + out_prev OUT VARCHAR2, + out_next OUT VARCHAR2 +) AS +BEGIN + SELECT * INTO out_prev + FROM ( + SELECT fqdn + FROM Records + WHERE zone_id = in_zone_id + AND revfqdn <= label_reverse(LOWER(in_fqdn)) + AND auth = 1 + ORDER BY revfqdn DESC + ) WHERE ROWNUM = 1; + + BEGIN + SELECT * INTO out_next + FROM ( + SELECT fqdn + FROM Records + WHERE zone_id = in_zone_id + AND revfqdn > label_reverse(LOWER(in_fqdn)) + AND auth = 1 + ORDER BY revfqdn ASC + ) WHERE ROWNUM = 1; + EXCEPTION + WHEN NO_DATA_FOUND THEN + SELECT name INTO out_next + FROM Zones + WHERE id = in_zone_id; + END; +END; +/ + +SHOW ERRORS + +CREATE PROCEDURE get_hashed_prev_next ( + in_zone_id INTEGER, + in_fqdnhash VARCHAR2, + out_fqdn OUT VARCHAR2, + out_prev OUT VARCHAR2, + out_next OUT VARCHAR2 +) AS +BEGIN + BEGIN + SELECT * INTO out_prev, out_fqdn + FROM ( + SELECT fqdnhash, fqdn + FROM Records + WHERE zone_id = in_zone_id + AND fqdnhash <= in_fqdnhash + AND auth = 1 + ORDER BY fqdnhash DESC + ) WHERE ROWNUM = 1; + EXCEPTION + WHEN NO_DATA_FOUND THEN + SELECT * INTO out_prev, out_fqdn + FROM ( + SELECT fqdnhash, fqdn + FROM Records + WHERE zone_id = in_zone_id + AND auth = 1 + ORDER BY fqdnhash DESC + ) WHERE ROWNUM = 1; + END; + + BEGIN + SELECT * INTO out_next + FROM ( + SELECT fqdnhash + FROM Records + WHERE zone_id = in_zone_id + AND fqdnhash > in_fqdnhash + AND auth = 1 + ORDER BY fqdnhash ASC + ) WHERE ROWNUM = 1; + EXCEPTION + WHEN NO_DATA_FOUND THEN + SELECT * INTO out_next + FROM ( + SELECT fqdnhash + FROM Records + WHERE zone_id = in_zone_id + AND auth = 1 + ORDER BY fqdnhash ASC + ) WHERE ROWNUM = 1; + END; +END; +/ + +SHOW ERRORS + +CREATE TRIGGER records_fill_columns + BEFORE INSERT OR UPDATE ON Records + FOR EACH ROW +BEGIN + -- 'www.site.example' => 'example site www' for NSEC ordering + :NEW.revfqdn := label_reverse(LOWER(:NEW.fqdn)); + + -- Hash the FQDN for NSEC3 ordering + IF :NEW.type != 'RRSIG' THEN + DECLARE + nsec3param_string VARCHAR2(512); + nsec3param_pattern VARCHAR2(512) := '^(\d+) +(\d+) +(\d+) +([0-9A-Fa-f]+)'; + hashalgo BINARY_INTEGER; + itcount BINARY_INTEGER; + salt RAW(256); + BEGIN + SELECT meta_content INTO nsec3param_string + FROM ZoneMetadata + WHERE zone_id = :NEW.zone_id + AND meta_type = 'NSEC3PARAM'; + hashalgo := REGEXP_SUBSTR(nsec3param_string, nsec3param_pattern, 1, 1, '', 1); + IF hashalgo != 1 THEN + RAISE_APPLICATION_ERROR(-20000, 'NSEC3 hash is not SHA-1'); + END IF; + itcount := REGEXP_SUBSTR(nsec3param_string, nsec3param_pattern, 1, 1, '', 3); + salt := REGEXP_SUBSTR(nsec3param_string, nsec3param_pattern, 1, 1, '', 4); + :NEW.fqdnhash := dnsname_to_hashname(:NEW.fqdn, salt, itcount); + EXCEPTION + WHEN NO_DATA_FOUND THEN + NULL; + END; + END IF; +END; +/ + +SHOW ERRORS + +CREATE TRIGGER parse_zone_defining_records + AFTER INSERT OR UPDATE ON Records + FOR EACH ROW + WHEN (NEW.type IN ('SOA')) +BEGIN + CASE :NEW.type + WHEN 'SOA' THEN + DECLARE + pattern VARCHAR2(32) := '^[^ ]+ +[^ ]+ +(\d+) +(\d+)'; + serial_str VARCHAR2(32) := REGEXP_SUBSTR(:NEW.content, pattern, 1, 1, '', 1); + serial_num NUMBER(10,0) := TO_NUMBER(serial_str); + refresh_str VARCHAR2(32) := REGEXP_SUBSTR(:NEW.content, pattern, 1, 1, '', 2); + BEGIN + IF serial_num = 0 THEN + SELECT NVL(max(last_change), 0) INTO serial_num + FROM Records + WHERE zone_id = :NEW.zone_id; + END IF; + + UPDATE Zones + SET serial = serial_num, refresh = TO_NUMBER(refresh_str) + WHERE id = :NEW.zone_id; + END; + END CASE; +END; +/ + +SHOW ERRORS + +-- End of schema +-- vi: set sw=2 et : -- diff --git a/modules/pipebackend/Makefile.am b/modules/pipebackend/Makefile.am new file mode 100644 index 0000000..b91553d --- /dev/null +++ b/modules/pipebackend/Makefile.am @@ -0,0 +1,13 @@ +pkglib_LTLIBRARIES = libpipebackend.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + backend.pl + +libpipebackend_la_SOURCES = \ + coprocess.cc coprocess.hh \ + pipebackend.cc pipebackend.hh + +libpipebackend_la_LDFLAGS = -module -avoid-version + diff --git a/modules/pipebackend/Makefile.in b/modules/pipebackend/Makefile.in new file mode 100644 index 0000000..b1d99ea --- /dev/null +++ b/modules/pipebackend/Makefile.in @@ -0,0 +1,832 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/pipebackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +libpipebackend_la_LIBADD = +am_libpipebackend_la_OBJECTS = coprocess.lo pipebackend.lo +libpipebackend_la_OBJECTS = $(am_libpipebackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libpipebackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libpipebackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libpipebackend_la_SOURCES) +DIST_SOURCES = $(libpipebackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libpipebackend.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + backend.pl + +libpipebackend_la_SOURCES = \ + coprocess.cc coprocess.hh \ + pipebackend.cc pipebackend.hh + +libpipebackend_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/pipebackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/pipebackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libpipebackend.la: $(libpipebackend_la_OBJECTS) $(libpipebackend_la_DEPENDENCIES) $(EXTRA_libpipebackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libpipebackend_la_LINK) -rpath $(pkglibdir) $(libpipebackend_la_OBJECTS) $(libpipebackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coprocess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipebackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/pipebackend/OBJECTFILES b/modules/pipebackend/OBJECTFILES new file mode 100644 index 0000000..5b8a67d --- /dev/null +++ b/modules/pipebackend/OBJECTFILES @@ -0,0 +1 @@ +coprocess.lo pipebackend.lo diff --git a/modules/pipebackend/OBJECTLIBS b/modules/pipebackend/OBJECTLIBS new file mode 100644 index 0000000..e69de29 diff --git a/modules/pipebackend/backend.pl b/modules/pipebackend/backend.pl new file mode 100755 index 0000000..a766d35 --- /dev/null +++ b/modules/pipebackend/backend.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w +# sample PowerDNS Coprocess backend +# + +use strict; + + +$|=1; # no buffering + +my $line=<>; +chomp($line); + +unless($line eq "HELO\t1") { + print "FAIL\n"; + print STDERR "Received '$line'\n"; + <>; + exit; +} +print "OK Sample backend firing up\n"; # print our banner + +while(<>) +{ + print STDERR "$$ Received: $_"; + chomp(); + my @arr=split(/\t/); + if(@arr<6) { + print "LOG PowerDNS sent unparseable line\n"; + print "FAIL\n"; + next; + } + + # note! the qname is what PowerDNS asks the backend. It need not be what the internet asked PowerDNS! + my ($type,$qname,$qclass,$qtype,$id,$ip)=split(/\t/); + + if(($qtype eq "SOA" || $qtype eq "ANY") && $qname eq "example.com") { + print STDERR "$$ Sent SOA records\n"; + print "DATA $qname $qclass SOA 3600 -1 ns1.example.com ahu.example.com 2008080300 1800 3600 604800 3600\n"; + } + if(($qtype eq "NS" || $qtype eq "ANY") && $qname eq "example.com") { + print STDERR "$$ Sent NS records\n"; + print "DATA $qname $qclass NS 3600 -1 ns1.example.com\n"; + print "DATA $qname $qclass NS 3600 -1 ns2.example.com\n"; + } + if(($qtype eq "TXT" || $qtype eq "ANY") && $qname eq "example.com") { + print STDERR "$$ Sent NS records\n"; + print "DATA $qname $qclass TXT 3600 -1 \"hallo allemaal!\"\n"; + } + if(($qtype eq "A" || $qtype eq "ANY") && $qname eq "webserver.example.com") { + print STDERR "$$ Sent A records\n"; + print "DATA $qname $qclass A 3600 -1 1.2.3.4\n"; + print "DATA $qname $qclass A 3600 -1 1.2.3.5\n"; + print "DATA $qname $qclass A 3600 -1 1.2.3.6\n"; + } + elsif(($qtype eq "CNAME" || $qtype eq "ANY") && $qname eq "www.example.com") { + print STDERR "$$ Sent CNAME records\n"; + print "DATA $qname $qclass CNAME 3600 -1 webserver.example.com\n"; + } + + + print STDERR "$$ End of data\n"; + print "END\n"; +} + diff --git a/modules/pipebackend/coprocess.cc b/modules/pipebackend/coprocess.cc new file mode 100644 index 0000000..db0ed5c --- /dev/null +++ b/modules/pipebackend/coprocess.cc @@ -0,0 +1,257 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "coprocess.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include "pdns/utility.hh" +#include +#include "pdns/misc.hh" +#include "pdns/pdnsexception.hh" +#include +#include +#include +#include + +CoProcess::CoProcess(const string &command,int timeout, int infd, int outfd) +{ + vector v; + split(v, command, is_any_of(" ")); + + std::vectorargv(v.size()+1); + argv[v.size()]=0; + + for (size_t n = 0; n < v.size(); n++) + argv[n]=v[n].c_str(); + // we get away with not copying since nobody resizes v + launch(argv.data(), timeout, infd, outfd); +} + +void CoProcess::launch(const char **argv, int timeout, int infd, int outfd) +{ + d_timeout=timeout; + d_infd=infd; + d_outfd=outfd; + + signal(SIGPIPE, SIG_IGN); + + if(access(argv[0],X_OK)) // check before fork so we can throw + throw PDNSException("Command '"+string(argv[0])+"' cannot be executed: "+stringerror()); + + if(pipe(d_fd1)<0 || pipe(d_fd2)<0) + throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(errno))); + + if((d_pid=fork())<0) + throw PDNSException("Unable to fork for coprocess: "+stringerror()); + else if(d_pid>0) { // parent speaking + close(d_fd1[0]); + setCloseOnExec(d_fd1[1]); + close(d_fd2[1]); + setCloseOnExec(d_fd2[0]); + if(!(d_fp=fdopen(d_fd2[0],"r"))) + throw PDNSException("Unable to associate a file pointer with pipe: "+stringerror()); + if( d_timeout) + setbuf(d_fp,0); // no buffering please, confuses poll + } + else if(!d_pid) { // child + signal(SIGCHLD, SIG_DFL); // silence a warning from perl + close(d_fd1[1]); + close(d_fd2[0]); + + if(d_fd1[0]!= infd) { + dup2(d_fd1[0], infd); + close(d_fd1[0]); + } + + if(d_fd2[1]!= outfd) { + dup2(d_fd2[1], outfd); + close(d_fd2[1]); + } + + // stdin & stdout are now connected, fire up our coprocess! + + if(execv(argv[0], const_cast(argv))<0) // now what + exit(123); + + /* not a lot we can do here. We shouldn't return because that will leave a forked process around. + no way to log this either - only thing we can do is make sure that our parent catches this soonest! */ + } +} + +CoProcess::~CoProcess() +{ + int status; + if(!waitpid(d_pid, &status, WNOHANG)) { + kill(d_pid, 9); + waitpid(d_pid, &status, 0); + } + + close(d_fd1[1]); + fclose(d_fp); +} + +void CoProcess::checkStatus() +{ + int status; + int ret=waitpid(d_pid, &status, WNOHANG); + if(ret<0) + throw PDNSException("Unable to ascertain status of coprocess "+itoa(d_pid)+" from "+itoa(getpid())+": "+string(strerror(errno))); + else if(ret) { + if(WIFEXITED(status)) { + int exitStatus=WEXITSTATUS(status); + throw PDNSException("Coprocess exited with code "+itoa(exitStatus)); + } + if(WIFSIGNALED(status)) { + int sig=WTERMSIG(status); + string reason="CoProcess died on receiving signal "+itoa(sig); +#ifdef WCOREDUMP + if(WCOREDUMP(status)) + reason+=". Dumped core"; +#endif + + throw PDNSException(reason); + } + } +} + +void CoProcess::send(const string &snd) +{ + checkStatus(); + string line(snd); + line.append(1,'\n'); + + unsigned int sent=0; + int bytes; + + // writen routine - socket may not accept al data in one go + while(sent +#include +#include + +#include "pdns/namespaces.hh" + +class CoRemote +{ +public: + virtual ~CoRemote() {} + virtual void sendReceive(const string &send, string &receive) = 0; + virtual void receive(string &rcv) = 0; + virtual void send(const string &send) = 0; + +}; + +class CoProcess : public CoRemote +{ +public: + CoProcess(const string &command,int timeout=0, int infd=0, int outfd=1); + ~CoProcess(); + void sendReceive(const string &send, string &receive); + void receive(string &rcv); + void send(const string &send); +private: + void launch(const char **argv, int timeout=0, int infd=0, int outfd=1); + void checkStatus(); + int d_fd1[2], d_fd2[2]; + int d_pid; + int d_infd; + int d_outfd; + int d_timeout; + FILE *d_fp; +}; + +class UnixRemote : public CoRemote +{ +public: + UnixRemote(const string &path, int timeout=0); + ~UnixRemote(); + void sendReceive(const string &send, string &receive); + void receive(string &rcv); + void send(const string &send); +private: + int d_fd; + FILE *d_fp; +}; +bool isUnixSocket(const string& fname); +#endif diff --git a/modules/pipebackend/pipebackend.cc b/modules/pipebackend/pipebackend.cc new file mode 100644 index 0000000..33950ec --- /dev/null +++ b/modules/pipebackend/pipebackend.cc @@ -0,0 +1,390 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include "coprocess.hh" + +#include "pdns/namespaces.hh" + +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include +#include +#include +#include "pipebackend.hh" + +static const char *kBackendId = "[PIPEBackend]"; + +CoWrapper::CoWrapper(const string &command, int timeout, int abiVersion) +{ + d_cp=0; + d_command=command; + d_timeout=timeout; + d_abiVersion = abiVersion; + launch(); // let exceptions fall through - if initial launch fails, we want to die + // I think +} + +CoWrapper::~CoWrapper() +{ + if(d_cp) + delete d_cp; +} + + +void CoWrapper::launch() +{ + if(d_cp) + return; + + if(d_command.empty()) + throw ArgException("pipe-command is not specified"); + + if(isUnixSocket(d_command)) + d_cp = new UnixRemote(d_command, d_timeout); + else + d_cp = new CoProcess(d_command, d_timeout); + + d_cp->send("HELO\t"+std::to_string(d_abiVersion)); + string banner; + d_cp->receive(banner); + g_log<send(line); + return; + } + catch(PDNSException &ae) { + delete d_cp; + d_cp=0; + throw; + } +} +void CoWrapper::receive(string &line) +{ + launch(); + try { + d_cp->receive(line); + return; + } + catch(PDNSException &ae) { + g_log< (new CoWrapper(getArg("command"), getArgAsNum("timeout"), getArgAsNum("abi-version"))); + } + + catch(const ArgException &A) { + cleanup(); + throw; + } +} + +/* + * Cleans up the co-process wrapper + */ +void PipeBackend::cleanup() +{ + d_coproc.reset(0); + delete d_regex; + d_regexstr = string(); + d_abiVersion = 0; +} + +void PipeBackend::lookup(const QType& qtype,const DNSName& qname, DNSPacket *pkt_p, int zoneId) +{ + try { + launch(); + d_disavow=false; + if(d_regex && !d_regex->match(qname.toStringRootDot())) { + if(::arg().mustDo("query-logging")) + g_log<getLocal().toString(); + realRemote = pkt_p->getRealRemote(); + remoteIP = pkt_p->getRemote().toString(); + } + // abi-version = 1 + // type qname qclass qtype id remote-ip-address + query<<"Q\t"<= 2) + query<<"\t"<= 3) + query <<"\t"<send(query.str()); + } + } + catch(PDNSException &pe) { + g_log<= 4) + query<<"AXFR\t"<send(query.str()); + } + catch(PDNSException &ae) { + g_log<send(oss.str()); + } + catch(PDNSException &ae) { + g_log<receive(line); + if (line == "END") break; + oss << line << std::endl; + }; + + return oss.str(); +} + +//! For the dynamic loader +DNSBackend *PipeBackend::maker() +{ + try { + return new PipeBackend(); + } + catch(...) { + g_log<= 3) + extraFields = 2; + + try{ + launch(); + for(;;) { + d_coproc->receive(line); + vectorparts; + stringtok(parts,line,"\t"); + if(parts.empty()) { + g_log<= 3) { + r.scopeMask = std::stoi(parts[1]); + r.auth = (parts[2] == "1"); + } else { + r.scopeMask = 0; + r.auth = 1; + } + r.qname=DNSName(parts[1+extraFields]); + r.qtype=parts[3+extraFields]; + r.ttl=pdns_stou(parts[4+extraFields]); + r.domain_id=std::stoi(parts[5+extraFields]); + + if(r.qtype.getCode() != QType::MX && r.qtype.getCode() != QType::SRV) { + r.content.clear(); + for(unsigned int n= 6 + extraFields; n < parts.size(); ++n) { + if(n!=6+extraFields) + r.content.append(1,' '); + r.content.append(parts[n]); + } + } + else { + if(parts.size()< 8 + extraFields) { + g_log< +#include +#include + + +#include "pdns/namespaces.hh" +#include "pdns/misc.hh" + + +/** The CoWrapper class wraps around a coprocess and restarts it if needed. + It may also send out pings and expect banners */ +class CoWrapper +{ +public: + CoWrapper(const string &command, int timeout, int abiVersion); + ~CoWrapper(); + void send(const string &line); + void receive(string &line); +private: + CoRemote* d_cp; + string d_command; + void launch(); + int d_timeout; + int d_abiVersion; +}; + +class PipeBackend : public DNSBackend +{ +public: + PipeBackend(const string &suffix=""); + ~PipeBackend(); + void lookup(const QType&, const DNSName& qdomain, DNSPacket *p=0, int zoneId=-1) override; + bool list(const DNSName& target, int domain_id, bool include_disabled=false) override; + bool get(DNSResourceRecord &r) override; + string directBackendCmd(const string &query) override; + static DNSBackend *maker(); + +private: + void launch(); + void cleanup(); + unique_ptr d_coproc; + DNSName d_qname; + QType d_qtype; + Regex* d_regex; + string d_regexstr; + bool d_disavow; + int d_abiVersion; +}; + + +#endif + diff --git a/modules/randombackend/Makefile.am b/modules/randombackend/Makefile.am new file mode 100644 index 0000000..2da4bbd --- /dev/null +++ b/modules/randombackend/Makefile.am @@ -0,0 +1,6 @@ +pkglib_LTLIBRARIES = librandombackend.la + +EXTRA_DIST = OBJECTFILES OBJECTLIBS + +librandombackend_la_SOURCES = randombackend.cc +librandombackend_la_LDFLAGS = -module -avoid-version diff --git a/modules/randombackend/Makefile.in b/modules/randombackend/Makefile.in new file mode 100644 index 0000000..730b964 --- /dev/null +++ b/modules/randombackend/Makefile.in @@ -0,0 +1,806 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/randombackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +librandombackend_la_LIBADD = +am_librandombackend_la_OBJECTS = randombackend.lo +librandombackend_la_OBJECTS = $(am_librandombackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +librandombackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(librandombackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(librandombackend_la_SOURCES) +DIST_SOURCES = $(librandombackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = librandombackend.la +EXTRA_DIST = OBJECTFILES OBJECTLIBS +librandombackend_la_SOURCES = randombackend.cc +librandombackend_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/randombackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/randombackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +librandombackend.la: $(librandombackend_la_OBJECTS) $(librandombackend_la_DEPENDENCIES) $(EXTRA_librandombackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(librandombackend_la_LINK) -rpath $(pkglibdir) $(librandombackend_la_OBJECTS) $(librandombackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/randombackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/randombackend/OBJECTFILES b/modules/randombackend/OBJECTFILES new file mode 100644 index 0000000..012f607 --- /dev/null +++ b/modules/randombackend/OBJECTFILES @@ -0,0 +1 @@ +randombackend.lo diff --git a/modules/randombackend/OBJECTLIBS b/modules/randombackend/OBJECTLIBS new file mode 100644 index 0000000..e69de29 diff --git a/modules/randombackend/randombackend.cc b/modules/randombackend/randombackend.cc new file mode 100644 index 0000000..525beb8 --- /dev/null +++ b/modules/randombackend/randombackend.cc @@ -0,0 +1,131 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/dnsbackend.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/dns_random.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/version.hh" +#include + +/* FIRST PART */ +class RandomBackend : public DNSBackend +{ +public: + RandomBackend(const string &suffix="") + { + setArgPrefix("random"+suffix); + d_ourname=DNSName(getArg("hostname")); + d_ourdomain = d_ourname; + d_ourdomain.chopOff(); + } + + bool list(const DNSName &target, int id, bool include_disabled) override { + return false; // we don't support AXFR + } + + void lookup(const QType &type, const DNSName &qdomain, DNSPacket *p, int zoneId) override + { + if(qdomain == d_ourdomain){ + if(type.getCode() == QType::SOA || type.getCode() == QType::ANY) { + d_answer="ns1." + d_ourdomain.toString() + " hostmaster." + d_ourdomain.toString() + " 1234567890 86400 7200 604800 300"; + } else { + d_answer.clear();; + } + } else if (qdomain == d_ourname) { + if(type.getCode() == QType::A || type.getCode() == QType::ANY) { + ostringstream os; + os<= 1.0.1) + ffi-rzmq-core (1.0.3) + ffi (~> 1.9) + json (1.8.5) + sqlite3 (1.3.9) + webrick (1.4.2) + zeromqrb (0.1.3) + ffi-rzmq + +PLATFORMS + ruby + +DEPENDENCIES + json + sqlite3 + webrick + zeromqrb + +BUNDLED WITH + 1.10.2 diff --git a/modules/remotebackend/Makefile.am b/modules/remotebackend/Makefile.am new file mode 100644 index 0000000..e106047 --- /dev/null +++ b/modules/remotebackend/Makefile.am @@ -0,0 +1,210 @@ +AM_CPPFLAGS += \ + -I$(top_srcdir)/ext/json11 \ + $(YAHTTP_CFLAGS) \ + $(LIBCRYPTO_CFLAGS) \ + $(LIBZMQ_CFLAGS) + +AM_LDFLAGS = $(THREADFLAGS) + +JSON11_LIBS = $(top_builddir)/ext/json11/libjson11.la + +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + testrunner.sh \ + unittest_http.rb \ + unittest_json.rb \ + unittest_pipe.rb \ + unittest_zeromq.rb \ + unittest_post.rb \ + unittest.rb \ + Gemfile \ + Gemfile.lock + +EXTRA_PROGRAMS = \ + remotebackend_pipe.test \ + remotebackend_unix.test \ + remotebackend_http.test \ + remotebackend_post.test \ + remotebackend_json.test \ + remotebackend_zeromq.test + +EXTRA_LTLIBRARIES = libtestremotebackend.la + +clean-local: + rm -f $(EXTRA_PROGRAMS) + +pkglib_LTLIBRARIES = libremotebackend.la + +libremotebackend_la_SOURCES = \ + remotebackend.hh \ + remotebackend.cc \ + unixconnector.cc \ + httpconnector.cc \ + pipeconnector.cc \ + zmqconnector.cc + +libremotebackend_la_LDFLAGS = -module -avoid-version + +libremotebackend_la_LIBADD = $(YAHTTP_LIBS) $(JSON11_LIBS) + +if REMOTEBACKEND_ZEROMQ +libremotebackend_la_LIBADD += $(LIBZMQ_LIBS) +endif + +TESTS_ENVIRONMENT = \ + BOOST_TEST_LOG_LEVEL=message; \ + export BOOST_TEST_LOG_LEVEL; \ + REMOTEBACKEND_ZEROMQ=$(REMOTEBACKEND_ZEROMQ); \ + export REMOTEBACKEND_ZEROMQ; + +TEST_EXTENSIONS = .test + +TEST_LOG_COMPILER = $(abs_srcdir)/testrunner.sh + +RECHECK_LOGS = \ + $(TEST_LOGS) \ + remotebackend_http_server.log \ + remotebackend_post_server.log \ + remotebackend_json_server.log \ + remotebackend_zeromq_server.log + +## The http, post and json test are using the same TCP port. +## To prevent "Address already in use - bind(2) (Errno::EADDRINUSE)" +## errors when running `make check` in parallel, we need to specify +## an order +remotebackend_post.log: remotebackend_http.log + +remotebackend_json.log: remotebackend_http.log remotebackend_post.log + +if BACKEND_UNIT_TESTS +TESTS = \ + remotebackend_pipe.test \ + remotebackend_unix.test \ + remotebackend_http.test \ + remotebackend_post.test \ + remotebackend_json.test \ + remotebackend_zeromq.test + +endif + +BUILT_SOURCES = ../../pdns/dnslabeltext.cc + +../../pdns/dnslabeltext.cc: ../../pdns/dnslabeltext.rl + $(MAKE) -C ../../pdns dnslabeltext.cc + +libtestremotebackend_la_SOURCES = \ + ../../pdns/arguments.hh ../../pdns/arguments.cc \ + ../../pdns/auth-packetcache.cc ../../pdns/auth-packetcache.hh \ + ../../pdns/auth-querycache.cc ../../pdns/auth-querycache.hh \ + ../../pdns/base32.cc \ + ../../pdns/base64.cc \ + ../../pdns/dnsbackend.hh ../../pdns/dnsbackend.cc \ + ../../pdns/dnslabeltext.cc \ + ../../pdns/dnsname.cc ../../pdns/dnsname.hh \ + ../../pdns/dnspacket.cc \ + ../../pdns/dnsparser.cc \ + ../../pdns/dnsrecords.cc \ + ../../pdns/dnssecinfra.cc \ + ../../pdns/ednssubnet.cc \ + ../../pdns/ednsoptions.cc ../../pdns/ednsoptions.hh \ + ../../pdns/iputils.cc \ + ../../pdns/logger.cc \ + ../../pdns/misc.cc \ + ../../pdns/nsecrecords.cc \ + ../../pdns/packetcache.hh \ + ../../pdns/qtype.cc \ + ../../pdns/sillyrecords.cc \ + ../../pdns/statbag.cc \ + ../../pdns/ueberbackend.hh ../../pdns/ueberbackend.cc \ + ../../pdns/dns.hh ../../pdns/dns.cc \ + ../../pdns/dns_random_urandom.cc \ + ../../pdns/dnswriter.cc \ + ../../pdns/nameserver.cc \ + ../../pdns/rcpgenerator.cc \ + ../../pdns/unix_utility.cc \ + ../../pdns/gss_context.cc ../../pdns/gss_context.hh \ + ../../pdns/json.hh ../../pdns/json.cc \ + httpconnector.cc \ + pipeconnector.cc \ + unixconnector.cc \ + zmqconnector.cc \ + remotebackend.hh remotebackend.cc + +libtestremotebackend_la_CPPFLAGS = $(AM_CPPFLAGS) + +libtestremotebackend_la_LIBADD = \ + $(YAHTTP_LIBS) \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(LIBDL) $(JSON11_LIBS) + +libtestremotebackend_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) + +if REMOTEBACKEND_ZEROMQ +libtestremotebackend_la_LIBADD += $(LIBZMQ_LIBS) +endif + +if PKCS11 +libtestremotebackend_la_SOURCES += \ + ../../pdns/pkcs11signers.hh \ + ../../pdns/pkcs11signers.cc + +libtestremotebackend_la_LIBADD += \ + $(P11KIT1_LIBS) + +libtestremotebackend_la_CPPFLAGS += \ + $(P11KIT1_CFLAGS) +endif + +if GSS_TSIG +libtestremotebackend_la_LIBADD += \ + $(GSS_LIBS) +libtestremotebackend_la_CPPFLAGS+= \ + $(GSS_CFLAGS) +endif + +remotebackend_http_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-http.cc \ + test-remotebackend-keys.hh + +remotebackend_http_test_LDADD = libtestremotebackend.la + +remotebackend_json_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-json.cc \ + test-remotebackend-keys.hh + +remotebackend_json_test_LDADD = libtestremotebackend.la + +remotebackend_pipe_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-pipe.cc \ + test-remotebackend-keys.hh + +remotebackend_pipe_test_LDADD = libtestremotebackend.la + +remotebackend_post_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-post.cc \ + test-remotebackend-keys.hh + +remotebackend_post_test_LDADD = libtestremotebackend.la + +remotebackend_unix_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-unix.cc \ + test-remotebackend-keys.hh + +remotebackend_unix_test_LDADD = libtestremotebackend.la + +remotebackend_zeromq_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-zeromq.cc \ + test-remotebackend-keys.hh + +remotebackend_zeromq_test_LDADD = libtestremotebackend.la diff --git a/modules/remotebackend/Makefile.in b/modules/remotebackend/Makefile.in new file mode 100644 index 0000000..c30fccd --- /dev/null +++ b/modules/remotebackend/Makefile.in @@ -0,0 +1,1865 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +EXTRA_PROGRAMS = remotebackend_pipe.test$(EXEEXT) \ + remotebackend_unix.test$(EXEEXT) \ + remotebackend_http.test$(EXEEXT) \ + remotebackend_post.test$(EXEEXT) \ + remotebackend_json.test$(EXEEXT) \ + remotebackend_zeromq.test$(EXEEXT) +@REMOTEBACKEND_ZEROMQ_TRUE@am__append_1 = $(LIBZMQ_LIBS) +@BACKEND_UNIT_TESTS_TRUE@TESTS = remotebackend_pipe.test$(EXEEXT) \ +@BACKEND_UNIT_TESTS_TRUE@ remotebackend_unix.test$(EXEEXT) \ +@BACKEND_UNIT_TESTS_TRUE@ remotebackend_http.test$(EXEEXT) \ +@BACKEND_UNIT_TESTS_TRUE@ remotebackend_post.test$(EXEEXT) \ +@BACKEND_UNIT_TESTS_TRUE@ remotebackend_json.test$(EXEEXT) \ +@BACKEND_UNIT_TESTS_TRUE@ remotebackend_zeromq.test$(EXEEXT) +@REMOTEBACKEND_ZEROMQ_TRUE@am__append_2 = $(LIBZMQ_LIBS) +@PKCS11_TRUE@am__append_3 = \ +@PKCS11_TRUE@ ../../pdns/pkcs11signers.hh \ +@PKCS11_TRUE@ ../../pdns/pkcs11signers.cc + +@PKCS11_TRUE@am__append_4 = \ +@PKCS11_TRUE@ $(P11KIT1_LIBS) + +@PKCS11_TRUE@am__append_5 = \ +@PKCS11_TRUE@ $(P11KIT1_CFLAGS) + +@GSS_TSIG_TRUE@am__append_6 = \ +@GSS_TSIG_TRUE@ $(GSS_LIBS) + +@GSS_TSIG_TRUE@am__append_7 = \ +@GSS_TSIG_TRUE@ $(GSS_CFLAGS) + +subdir = modules/remotebackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +@REMOTEBACKEND_ZEROMQ_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +libremotebackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(JSON11_LIBS) $(am__DEPENDENCIES_2) +am_libremotebackend_la_OBJECTS = remotebackend.lo unixconnector.lo \ + httpconnector.lo pipeconnector.lo zmqconnector.lo +libremotebackend_la_OBJECTS = $(am_libremotebackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libremotebackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libremotebackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@PKCS11_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@GSS_TSIG_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +libtestremotebackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(JSON11_LIBS) \ + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +am__libtestremotebackend_la_SOURCES_DIST = ../../pdns/arguments.hh \ + ../../pdns/arguments.cc ../../pdns/auth-packetcache.cc \ + ../../pdns/auth-packetcache.hh ../../pdns/auth-querycache.cc \ + ../../pdns/auth-querycache.hh ../../pdns/base32.cc \ + ../../pdns/base64.cc ../../pdns/dnsbackend.hh \ + ../../pdns/dnsbackend.cc ../../pdns/dnslabeltext.cc \ + ../../pdns/dnsname.cc ../../pdns/dnsname.hh \ + ../../pdns/dnspacket.cc ../../pdns/dnsparser.cc \ + ../../pdns/dnsrecords.cc ../../pdns/dnssecinfra.cc \ + ../../pdns/ednssubnet.cc ../../pdns/ednsoptions.cc \ + ../../pdns/ednsoptions.hh ../../pdns/iputils.cc \ + ../../pdns/logger.cc ../../pdns/misc.cc \ + ../../pdns/nsecrecords.cc ../../pdns/packetcache.hh \ + ../../pdns/qtype.cc ../../pdns/sillyrecords.cc \ + ../../pdns/statbag.cc ../../pdns/ueberbackend.hh \ + ../../pdns/ueberbackend.cc ../../pdns/dns.hh ../../pdns/dns.cc \ + ../../pdns/dns_random_urandom.cc ../../pdns/dnswriter.cc \ + ../../pdns/nameserver.cc ../../pdns/rcpgenerator.cc \ + ../../pdns/unix_utility.cc ../../pdns/gss_context.cc \ + ../../pdns/gss_context.hh ../../pdns/json.hh \ + ../../pdns/json.cc httpconnector.cc pipeconnector.cc \ + unixconnector.cc zmqconnector.cc remotebackend.hh \ + remotebackend.cc ../../pdns/pkcs11signers.hh \ + ../../pdns/pkcs11signers.cc +am__dirstamp = $(am__leading_dot)dirstamp +@PKCS11_TRUE@am__objects_1 = ../../pdns/libtestremotebackend_la-pkcs11signers.lo +am_libtestremotebackend_la_OBJECTS = \ + ../../pdns/libtestremotebackend_la-arguments.lo \ + ../../pdns/libtestremotebackend_la-auth-packetcache.lo \ + ../../pdns/libtestremotebackend_la-auth-querycache.lo \ + ../../pdns/libtestremotebackend_la-base32.lo \ + ../../pdns/libtestremotebackend_la-base64.lo \ + ../../pdns/libtestremotebackend_la-dnsbackend.lo \ + ../../pdns/libtestremotebackend_la-dnslabeltext.lo \ + ../../pdns/libtestremotebackend_la-dnsname.lo \ + ../../pdns/libtestremotebackend_la-dnspacket.lo \ + ../../pdns/libtestremotebackend_la-dnsparser.lo \ + ../../pdns/libtestremotebackend_la-dnsrecords.lo \ + ../../pdns/libtestremotebackend_la-dnssecinfra.lo \ + ../../pdns/libtestremotebackend_la-ednssubnet.lo \ + ../../pdns/libtestremotebackend_la-ednsoptions.lo \ + ../../pdns/libtestremotebackend_la-iputils.lo \ + ../../pdns/libtestremotebackend_la-logger.lo \ + ../../pdns/libtestremotebackend_la-misc.lo \ + ../../pdns/libtestremotebackend_la-nsecrecords.lo \ + ../../pdns/libtestremotebackend_la-qtype.lo \ + ../../pdns/libtestremotebackend_la-sillyrecords.lo \ + ../../pdns/libtestremotebackend_la-statbag.lo \ + ../../pdns/libtestremotebackend_la-ueberbackend.lo \ + ../../pdns/libtestremotebackend_la-dns.lo \ + ../../pdns/libtestremotebackend_la-dns_random_urandom.lo \ + ../../pdns/libtestremotebackend_la-dnswriter.lo \ + ../../pdns/libtestremotebackend_la-nameserver.lo \ + ../../pdns/libtestremotebackend_la-rcpgenerator.lo \ + ../../pdns/libtestremotebackend_la-unix_utility.lo \ + ../../pdns/libtestremotebackend_la-gss_context.lo \ + ../../pdns/libtestremotebackend_la-json.lo \ + libtestremotebackend_la-httpconnector.lo \ + libtestremotebackend_la-pipeconnector.lo \ + libtestremotebackend_la-unixconnector.lo \ + libtestremotebackend_la-zmqconnector.lo \ + libtestremotebackend_la-remotebackend.lo $(am__objects_1) +libtestremotebackend_la_OBJECTS = \ + $(am_libtestremotebackend_la_OBJECTS) +libtestremotebackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libtestremotebackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_remotebackend_http_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-http.$(OBJEXT) +remotebackend_http_test_OBJECTS = \ + $(am_remotebackend_http_test_OBJECTS) +remotebackend_http_test_DEPENDENCIES = libtestremotebackend.la +am_remotebackend_json_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-json.$(OBJEXT) +remotebackend_json_test_OBJECTS = \ + $(am_remotebackend_json_test_OBJECTS) +remotebackend_json_test_DEPENDENCIES = libtestremotebackend.la +am_remotebackend_pipe_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-pipe.$(OBJEXT) +remotebackend_pipe_test_OBJECTS = \ + $(am_remotebackend_pipe_test_OBJECTS) +remotebackend_pipe_test_DEPENDENCIES = libtestremotebackend.la +am_remotebackend_post_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-post.$(OBJEXT) +remotebackend_post_test_OBJECTS = \ + $(am_remotebackend_post_test_OBJECTS) +remotebackend_post_test_DEPENDENCIES = libtestremotebackend.la +am_remotebackend_unix_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-unix.$(OBJEXT) +remotebackend_unix_test_OBJECTS = \ + $(am_remotebackend_unix_test_OBJECTS) +remotebackend_unix_test_DEPENDENCIES = libtestremotebackend.la +am_remotebackend_zeromq_test_OBJECTS = test-remotebackend.$(OBJEXT) \ + test-remotebackend-zeromq.$(OBJEXT) +remotebackend_zeromq_test_OBJECTS = \ + $(am_remotebackend_zeromq_test_OBJECTS) +remotebackend_zeromq_test_DEPENDENCIES = libtestremotebackend.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libremotebackend_la_SOURCES) \ + $(libtestremotebackend_la_SOURCES) \ + $(remotebackend_http_test_SOURCES) \ + $(remotebackend_json_test_SOURCES) \ + $(remotebackend_pipe_test_SOURCES) \ + $(remotebackend_post_test_SOURCES) \ + $(remotebackend_unix_test_SOURCES) \ + $(remotebackend_zeromq_test_SOURCES) +DIST_SOURCES = $(libremotebackend_la_SOURCES) \ + $(am__libtestremotebackend_la_SOURCES_DIST) \ + $(remotebackend_http_test_SOURCES) \ + $(remotebackend_json_test_SOURCES) \ + $(remotebackend_pipe_test_SOURCES) \ + $(remotebackend_post_test_SOURCES) \ + $(remotebackend_unix_test_SOURCES) \ + $(remotebackend_zeromq_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/ext/json11 \ + $(YAHTTP_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBZMQ_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_LDFLAGS = $(THREADFLAGS) +JSON11_LIBS = $(top_builddir)/ext/json11/libjson11.la +EXTRA_DIST = \ + OBJECTFILES \ + OBJECTLIBS \ + testrunner.sh \ + unittest_http.rb \ + unittest_json.rb \ + unittest_pipe.rb \ + unittest_zeromq.rb \ + unittest_post.rb \ + unittest.rb \ + Gemfile \ + Gemfile.lock + +EXTRA_LTLIBRARIES = libtestremotebackend.la +pkglib_LTLIBRARIES = libremotebackend.la +libremotebackend_la_SOURCES = \ + remotebackend.hh \ + remotebackend.cc \ + unixconnector.cc \ + httpconnector.cc \ + pipeconnector.cc \ + zmqconnector.cc + +libremotebackend_la_LDFLAGS = -module -avoid-version +libremotebackend_la_LIBADD = $(YAHTTP_LIBS) $(JSON11_LIBS) \ + $(am__append_1) +TESTS_ENVIRONMENT = \ + BOOST_TEST_LOG_LEVEL=message; \ + export BOOST_TEST_LOG_LEVEL; \ + REMOTEBACKEND_ZEROMQ=$(REMOTEBACKEND_ZEROMQ); \ + export REMOTEBACKEND_ZEROMQ; + +TEST_EXTENSIONS = .test +TEST_LOG_COMPILER = $(abs_srcdir)/testrunner.sh +RECHECK_LOGS = \ + $(TEST_LOGS) \ + remotebackend_http_server.log \ + remotebackend_post_server.log \ + remotebackend_json_server.log \ + remotebackend_zeromq_server.log + +BUILT_SOURCES = ../../pdns/dnslabeltext.cc +libtestremotebackend_la_SOURCES = ../../pdns/arguments.hh \ + ../../pdns/arguments.cc ../../pdns/auth-packetcache.cc \ + ../../pdns/auth-packetcache.hh ../../pdns/auth-querycache.cc \ + ../../pdns/auth-querycache.hh ../../pdns/base32.cc \ + ../../pdns/base64.cc ../../pdns/dnsbackend.hh \ + ../../pdns/dnsbackend.cc ../../pdns/dnslabeltext.cc \ + ../../pdns/dnsname.cc ../../pdns/dnsname.hh \ + ../../pdns/dnspacket.cc ../../pdns/dnsparser.cc \ + ../../pdns/dnsrecords.cc ../../pdns/dnssecinfra.cc \ + ../../pdns/ednssubnet.cc ../../pdns/ednsoptions.cc \ + ../../pdns/ednsoptions.hh ../../pdns/iputils.cc \ + ../../pdns/logger.cc ../../pdns/misc.cc \ + ../../pdns/nsecrecords.cc ../../pdns/packetcache.hh \ + ../../pdns/qtype.cc ../../pdns/sillyrecords.cc \ + ../../pdns/statbag.cc ../../pdns/ueberbackend.hh \ + ../../pdns/ueberbackend.cc ../../pdns/dns.hh ../../pdns/dns.cc \ + ../../pdns/dns_random_urandom.cc ../../pdns/dnswriter.cc \ + ../../pdns/nameserver.cc ../../pdns/rcpgenerator.cc \ + ../../pdns/unix_utility.cc ../../pdns/gss_context.cc \ + ../../pdns/gss_context.hh ../../pdns/json.hh \ + ../../pdns/json.cc httpconnector.cc pipeconnector.cc \ + unixconnector.cc zmqconnector.cc remotebackend.hh \ + remotebackend.cc $(am__append_3) +libtestremotebackend_la_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_5) \ + $(am__append_7) +libtestremotebackend_la_LIBADD = $(YAHTTP_LIBS) $(LIBCRYPTO_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) $(LIBDL) $(JSON11_LIBS) \ + $(am__append_2) $(am__append_4) $(am__append_6) +libtestremotebackend_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) + +remotebackend_http_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-http.cc \ + test-remotebackend-keys.hh + +remotebackend_http_test_LDADD = libtestremotebackend.la +remotebackend_json_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-json.cc \ + test-remotebackend-keys.hh + +remotebackend_json_test_LDADD = libtestremotebackend.la +remotebackend_pipe_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-pipe.cc \ + test-remotebackend-keys.hh + +remotebackend_pipe_test_LDADD = libtestremotebackend.la +remotebackend_post_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-post.cc \ + test-remotebackend-keys.hh + +remotebackend_post_test_LDADD = libtestremotebackend.la +remotebackend_unix_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-unix.cc \ + test-remotebackend-keys.hh + +remotebackend_unix_test_LDADD = libtestremotebackend.la +remotebackend_zeromq_test_SOURCES = \ + test-remotebackend.cc \ + test-remotebackend-zeromq.cc \ + test-remotebackend-keys.hh + +remotebackend_zeromq_test_LDADD = libtestremotebackend.la +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/remotebackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/remotebackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libremotebackend.la: $(libremotebackend_la_OBJECTS) $(libremotebackend_la_DEPENDENCIES) $(EXTRA_libremotebackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libremotebackend_la_LINK) -rpath $(pkglibdir) $(libremotebackend_la_OBJECTS) $(libremotebackend_la_LIBADD) $(LIBS) +../../pdns/$(am__dirstamp): + @$(MKDIR_P) ../../pdns + @: > ../../pdns/$(am__dirstamp) +../../pdns/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../../pdns/$(DEPDIR) + @: > ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-arguments.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-auth-packetcache.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-auth-querycache.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-base32.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-base64.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnsbackend.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnslabeltext.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnsname.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnspacket.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnsparser.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnsrecords.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnssecinfra.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-ednssubnet.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-ednsoptions.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-iputils.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-logger.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-misc.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-nsecrecords.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-qtype.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-sillyrecords.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-statbag.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-ueberbackend.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dns.lo: ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dns_random_urandom.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-dnswriter.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-nameserver.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-rcpgenerator.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-unix_utility.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-gss_context.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-json.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) +../../pdns/libtestremotebackend_la-pkcs11signers.lo: \ + ../../pdns/$(am__dirstamp) \ + ../../pdns/$(DEPDIR)/$(am__dirstamp) + +libtestremotebackend.la: $(libtestremotebackend_la_OBJECTS) $(libtestremotebackend_la_DEPENDENCIES) $(EXTRA_libtestremotebackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtestremotebackend_la_LINK) $(libtestremotebackend_la_OBJECTS) $(libtestremotebackend_la_LIBADD) $(LIBS) + +remotebackend_http.test$(EXEEXT): $(remotebackend_http_test_OBJECTS) $(remotebackend_http_test_DEPENDENCIES) $(EXTRA_remotebackend_http_test_DEPENDENCIES) + @rm -f remotebackend_http.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_http_test_OBJECTS) $(remotebackend_http_test_LDADD) $(LIBS) + +remotebackend_json.test$(EXEEXT): $(remotebackend_json_test_OBJECTS) $(remotebackend_json_test_DEPENDENCIES) $(EXTRA_remotebackend_json_test_DEPENDENCIES) + @rm -f remotebackend_json.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_json_test_OBJECTS) $(remotebackend_json_test_LDADD) $(LIBS) + +remotebackend_pipe.test$(EXEEXT): $(remotebackend_pipe_test_OBJECTS) $(remotebackend_pipe_test_DEPENDENCIES) $(EXTRA_remotebackend_pipe_test_DEPENDENCIES) + @rm -f remotebackend_pipe.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_pipe_test_OBJECTS) $(remotebackend_pipe_test_LDADD) $(LIBS) + +remotebackend_post.test$(EXEEXT): $(remotebackend_post_test_OBJECTS) $(remotebackend_post_test_DEPENDENCIES) $(EXTRA_remotebackend_post_test_DEPENDENCIES) + @rm -f remotebackend_post.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_post_test_OBJECTS) $(remotebackend_post_test_LDADD) $(LIBS) + +remotebackend_unix.test$(EXEEXT): $(remotebackend_unix_test_OBJECTS) $(remotebackend_unix_test_DEPENDENCIES) $(EXTRA_remotebackend_unix_test_DEPENDENCIES) + @rm -f remotebackend_unix.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_unix_test_OBJECTS) $(remotebackend_unix_test_LDADD) $(LIBS) + +remotebackend_zeromq.test$(EXEEXT): $(remotebackend_zeromq_test_OBJECTS) $(remotebackend_zeromq_test_DEPENDENCIES) $(EXTRA_remotebackend_zeromq_test_DEPENDENCIES) + @rm -f remotebackend_zeromq.test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(remotebackend_zeromq_test_OBJECTS) $(remotebackend_zeromq_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../../pdns/*.$(OBJEXT) + -rm -f ../../pdns/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-arguments.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-packetcache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-querycache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-base32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-base64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dns.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dns_random_urandom.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnslabeltext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsname.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnspacket.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsparser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsrecords.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnssecinfra.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-dnswriter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-ednsoptions.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-ednssubnet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-gss_context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-iputils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-json.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-logger.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-misc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-nameserver.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-nsecrecords.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-pkcs11signers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-qtype.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-rcpgenerator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-sillyrecords.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-statbag.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-ueberbackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../../pdns/$(DEPDIR)/libtestremotebackend_la-unix_utility.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/httpconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestremotebackend_la-httpconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestremotebackend_la-pipeconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestremotebackend_la-remotebackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestremotebackend_la-unixconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestremotebackend_la-zmqconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipeconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remotebackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-json.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-pipe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-post.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-unix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend-zeromq.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remotebackend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unixconnector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmqconnector.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +../../pdns/libtestremotebackend_la-arguments.lo: ../../pdns/arguments.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-arguments.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-arguments.Tpo -c -o ../../pdns/libtestremotebackend_la-arguments.lo `test -f '../../pdns/arguments.cc' || echo '$(srcdir)/'`../../pdns/arguments.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-arguments.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-arguments.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/arguments.cc' object='../../pdns/libtestremotebackend_la-arguments.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-arguments.lo `test -f '../../pdns/arguments.cc' || echo '$(srcdir)/'`../../pdns/arguments.cc + +../../pdns/libtestremotebackend_la-auth-packetcache.lo: ../../pdns/auth-packetcache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-auth-packetcache.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-packetcache.Tpo -c -o ../../pdns/libtestremotebackend_la-auth-packetcache.lo `test -f '../../pdns/auth-packetcache.cc' || echo '$(srcdir)/'`../../pdns/auth-packetcache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-packetcache.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-packetcache.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/auth-packetcache.cc' object='../../pdns/libtestremotebackend_la-auth-packetcache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-auth-packetcache.lo `test -f '../../pdns/auth-packetcache.cc' || echo '$(srcdir)/'`../../pdns/auth-packetcache.cc + +../../pdns/libtestremotebackend_la-auth-querycache.lo: ../../pdns/auth-querycache.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-auth-querycache.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-querycache.Tpo -c -o ../../pdns/libtestremotebackend_la-auth-querycache.lo `test -f '../../pdns/auth-querycache.cc' || echo '$(srcdir)/'`../../pdns/auth-querycache.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-querycache.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-auth-querycache.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/auth-querycache.cc' object='../../pdns/libtestremotebackend_la-auth-querycache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-auth-querycache.lo `test -f '../../pdns/auth-querycache.cc' || echo '$(srcdir)/'`../../pdns/auth-querycache.cc + +../../pdns/libtestremotebackend_la-base32.lo: ../../pdns/base32.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-base32.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-base32.Tpo -c -o ../../pdns/libtestremotebackend_la-base32.lo `test -f '../../pdns/base32.cc' || echo '$(srcdir)/'`../../pdns/base32.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-base32.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-base32.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/base32.cc' object='../../pdns/libtestremotebackend_la-base32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-base32.lo `test -f '../../pdns/base32.cc' || echo '$(srcdir)/'`../../pdns/base32.cc + +../../pdns/libtestremotebackend_la-base64.lo: ../../pdns/base64.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-base64.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-base64.Tpo -c -o ../../pdns/libtestremotebackend_la-base64.lo `test -f '../../pdns/base64.cc' || echo '$(srcdir)/'`../../pdns/base64.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-base64.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-base64.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/base64.cc' object='../../pdns/libtestremotebackend_la-base64.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-base64.lo `test -f '../../pdns/base64.cc' || echo '$(srcdir)/'`../../pdns/base64.cc + +../../pdns/libtestremotebackend_la-dnsbackend.lo: ../../pdns/dnsbackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnsbackend.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsbackend.Tpo -c -o ../../pdns/libtestremotebackend_la-dnsbackend.lo `test -f '../../pdns/dnsbackend.cc' || echo '$(srcdir)/'`../../pdns/dnsbackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsbackend.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsbackend.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnsbackend.cc' object='../../pdns/libtestremotebackend_la-dnsbackend.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnsbackend.lo `test -f '../../pdns/dnsbackend.cc' || echo '$(srcdir)/'`../../pdns/dnsbackend.cc + +../../pdns/libtestremotebackend_la-dnslabeltext.lo: ../../pdns/dnslabeltext.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnslabeltext.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnslabeltext.Tpo -c -o ../../pdns/libtestremotebackend_la-dnslabeltext.lo `test -f '../../pdns/dnslabeltext.cc' || echo '$(srcdir)/'`../../pdns/dnslabeltext.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnslabeltext.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnslabeltext.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnslabeltext.cc' object='../../pdns/libtestremotebackend_la-dnslabeltext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnslabeltext.lo `test -f '../../pdns/dnslabeltext.cc' || echo '$(srcdir)/'`../../pdns/dnslabeltext.cc + +../../pdns/libtestremotebackend_la-dnsname.lo: ../../pdns/dnsname.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnsname.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsname.Tpo -c -o ../../pdns/libtestremotebackend_la-dnsname.lo `test -f '../../pdns/dnsname.cc' || echo '$(srcdir)/'`../../pdns/dnsname.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsname.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsname.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnsname.cc' object='../../pdns/libtestremotebackend_la-dnsname.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnsname.lo `test -f '../../pdns/dnsname.cc' || echo '$(srcdir)/'`../../pdns/dnsname.cc + +../../pdns/libtestremotebackend_la-dnspacket.lo: ../../pdns/dnspacket.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnspacket.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnspacket.Tpo -c -o ../../pdns/libtestremotebackend_la-dnspacket.lo `test -f '../../pdns/dnspacket.cc' || echo '$(srcdir)/'`../../pdns/dnspacket.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnspacket.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnspacket.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnspacket.cc' object='../../pdns/libtestremotebackend_la-dnspacket.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnspacket.lo `test -f '../../pdns/dnspacket.cc' || echo '$(srcdir)/'`../../pdns/dnspacket.cc + +../../pdns/libtestremotebackend_la-dnsparser.lo: ../../pdns/dnsparser.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnsparser.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsparser.Tpo -c -o ../../pdns/libtestremotebackend_la-dnsparser.lo `test -f '../../pdns/dnsparser.cc' || echo '$(srcdir)/'`../../pdns/dnsparser.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsparser.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsparser.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnsparser.cc' object='../../pdns/libtestremotebackend_la-dnsparser.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnsparser.lo `test -f '../../pdns/dnsparser.cc' || echo '$(srcdir)/'`../../pdns/dnsparser.cc + +../../pdns/libtestremotebackend_la-dnsrecords.lo: ../../pdns/dnsrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnsrecords.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsrecords.Tpo -c -o ../../pdns/libtestremotebackend_la-dnsrecords.lo `test -f '../../pdns/dnsrecords.cc' || echo '$(srcdir)/'`../../pdns/dnsrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsrecords.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnsrecords.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnsrecords.cc' object='../../pdns/libtestremotebackend_la-dnsrecords.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnsrecords.lo `test -f '../../pdns/dnsrecords.cc' || echo '$(srcdir)/'`../../pdns/dnsrecords.cc + +../../pdns/libtestremotebackend_la-dnssecinfra.lo: ../../pdns/dnssecinfra.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnssecinfra.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnssecinfra.Tpo -c -o ../../pdns/libtestremotebackend_la-dnssecinfra.lo `test -f '../../pdns/dnssecinfra.cc' || echo '$(srcdir)/'`../../pdns/dnssecinfra.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnssecinfra.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnssecinfra.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnssecinfra.cc' object='../../pdns/libtestremotebackend_la-dnssecinfra.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnssecinfra.lo `test -f '../../pdns/dnssecinfra.cc' || echo '$(srcdir)/'`../../pdns/dnssecinfra.cc + +../../pdns/libtestremotebackend_la-ednssubnet.lo: ../../pdns/ednssubnet.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-ednssubnet.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednssubnet.Tpo -c -o ../../pdns/libtestremotebackend_la-ednssubnet.lo `test -f '../../pdns/ednssubnet.cc' || echo '$(srcdir)/'`../../pdns/ednssubnet.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednssubnet.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednssubnet.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/ednssubnet.cc' object='../../pdns/libtestremotebackend_la-ednssubnet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-ednssubnet.lo `test -f '../../pdns/ednssubnet.cc' || echo '$(srcdir)/'`../../pdns/ednssubnet.cc + +../../pdns/libtestremotebackend_la-ednsoptions.lo: ../../pdns/ednsoptions.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-ednsoptions.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednsoptions.Tpo -c -o ../../pdns/libtestremotebackend_la-ednsoptions.lo `test -f '../../pdns/ednsoptions.cc' || echo '$(srcdir)/'`../../pdns/ednsoptions.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednsoptions.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-ednsoptions.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/ednsoptions.cc' object='../../pdns/libtestremotebackend_la-ednsoptions.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-ednsoptions.lo `test -f '../../pdns/ednsoptions.cc' || echo '$(srcdir)/'`../../pdns/ednsoptions.cc + +../../pdns/libtestremotebackend_la-iputils.lo: ../../pdns/iputils.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-iputils.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-iputils.Tpo -c -o ../../pdns/libtestremotebackend_la-iputils.lo `test -f '../../pdns/iputils.cc' || echo '$(srcdir)/'`../../pdns/iputils.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-iputils.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-iputils.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/iputils.cc' object='../../pdns/libtestremotebackend_la-iputils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-iputils.lo `test -f '../../pdns/iputils.cc' || echo '$(srcdir)/'`../../pdns/iputils.cc + +../../pdns/libtestremotebackend_la-logger.lo: ../../pdns/logger.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-logger.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-logger.Tpo -c -o ../../pdns/libtestremotebackend_la-logger.lo `test -f '../../pdns/logger.cc' || echo '$(srcdir)/'`../../pdns/logger.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-logger.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-logger.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/logger.cc' object='../../pdns/libtestremotebackend_la-logger.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-logger.lo `test -f '../../pdns/logger.cc' || echo '$(srcdir)/'`../../pdns/logger.cc + +../../pdns/libtestremotebackend_la-misc.lo: ../../pdns/misc.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-misc.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-misc.Tpo -c -o ../../pdns/libtestremotebackend_la-misc.lo `test -f '../../pdns/misc.cc' || echo '$(srcdir)/'`../../pdns/misc.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-misc.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-misc.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/misc.cc' object='../../pdns/libtestremotebackend_la-misc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-misc.lo `test -f '../../pdns/misc.cc' || echo '$(srcdir)/'`../../pdns/misc.cc + +../../pdns/libtestremotebackend_la-nsecrecords.lo: ../../pdns/nsecrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-nsecrecords.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-nsecrecords.Tpo -c -o ../../pdns/libtestremotebackend_la-nsecrecords.lo `test -f '../../pdns/nsecrecords.cc' || echo '$(srcdir)/'`../../pdns/nsecrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-nsecrecords.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-nsecrecords.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/nsecrecords.cc' object='../../pdns/libtestremotebackend_la-nsecrecords.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-nsecrecords.lo `test -f '../../pdns/nsecrecords.cc' || echo '$(srcdir)/'`../../pdns/nsecrecords.cc + +../../pdns/libtestremotebackend_la-qtype.lo: ../../pdns/qtype.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-qtype.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-qtype.Tpo -c -o ../../pdns/libtestremotebackend_la-qtype.lo `test -f '../../pdns/qtype.cc' || echo '$(srcdir)/'`../../pdns/qtype.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-qtype.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-qtype.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/qtype.cc' object='../../pdns/libtestremotebackend_la-qtype.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-qtype.lo `test -f '../../pdns/qtype.cc' || echo '$(srcdir)/'`../../pdns/qtype.cc + +../../pdns/libtestremotebackend_la-sillyrecords.lo: ../../pdns/sillyrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-sillyrecords.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-sillyrecords.Tpo -c -o ../../pdns/libtestremotebackend_la-sillyrecords.lo `test -f '../../pdns/sillyrecords.cc' || echo '$(srcdir)/'`../../pdns/sillyrecords.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-sillyrecords.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-sillyrecords.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/sillyrecords.cc' object='../../pdns/libtestremotebackend_la-sillyrecords.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-sillyrecords.lo `test -f '../../pdns/sillyrecords.cc' || echo '$(srcdir)/'`../../pdns/sillyrecords.cc + +../../pdns/libtestremotebackend_la-statbag.lo: ../../pdns/statbag.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-statbag.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-statbag.Tpo -c -o ../../pdns/libtestremotebackend_la-statbag.lo `test -f '../../pdns/statbag.cc' || echo '$(srcdir)/'`../../pdns/statbag.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-statbag.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-statbag.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/statbag.cc' object='../../pdns/libtestremotebackend_la-statbag.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-statbag.lo `test -f '../../pdns/statbag.cc' || echo '$(srcdir)/'`../../pdns/statbag.cc + +../../pdns/libtestremotebackend_la-ueberbackend.lo: ../../pdns/ueberbackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-ueberbackend.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-ueberbackend.Tpo -c -o ../../pdns/libtestremotebackend_la-ueberbackend.lo `test -f '../../pdns/ueberbackend.cc' || echo '$(srcdir)/'`../../pdns/ueberbackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-ueberbackend.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-ueberbackend.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/ueberbackend.cc' object='../../pdns/libtestremotebackend_la-ueberbackend.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-ueberbackend.lo `test -f '../../pdns/ueberbackend.cc' || echo '$(srcdir)/'`../../pdns/ueberbackend.cc + +../../pdns/libtestremotebackend_la-dns.lo: ../../pdns/dns.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dns.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns.Tpo -c -o ../../pdns/libtestremotebackend_la-dns.lo `test -f '../../pdns/dns.cc' || echo '$(srcdir)/'`../../pdns/dns.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dns.cc' object='../../pdns/libtestremotebackend_la-dns.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dns.lo `test -f '../../pdns/dns.cc' || echo '$(srcdir)/'`../../pdns/dns.cc + +../../pdns/libtestremotebackend_la-dns_random_urandom.lo: ../../pdns/dns_random_urandom.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dns_random_urandom.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns_random_urandom.Tpo -c -o ../../pdns/libtestremotebackend_la-dns_random_urandom.lo `test -f '../../pdns/dns_random_urandom.cc' || echo '$(srcdir)/'`../../pdns/dns_random_urandom.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns_random_urandom.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dns_random_urandom.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dns_random_urandom.cc' object='../../pdns/libtestremotebackend_la-dns_random_urandom.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dns_random_urandom.lo `test -f '../../pdns/dns_random_urandom.cc' || echo '$(srcdir)/'`../../pdns/dns_random_urandom.cc + +../../pdns/libtestremotebackend_la-dnswriter.lo: ../../pdns/dnswriter.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-dnswriter.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnswriter.Tpo -c -o ../../pdns/libtestremotebackend_la-dnswriter.lo `test -f '../../pdns/dnswriter.cc' || echo '$(srcdir)/'`../../pdns/dnswriter.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnswriter.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-dnswriter.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/dnswriter.cc' object='../../pdns/libtestremotebackend_la-dnswriter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-dnswriter.lo `test -f '../../pdns/dnswriter.cc' || echo '$(srcdir)/'`../../pdns/dnswriter.cc + +../../pdns/libtestremotebackend_la-nameserver.lo: ../../pdns/nameserver.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-nameserver.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-nameserver.Tpo -c -o ../../pdns/libtestremotebackend_la-nameserver.lo `test -f '../../pdns/nameserver.cc' || echo '$(srcdir)/'`../../pdns/nameserver.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-nameserver.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-nameserver.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/nameserver.cc' object='../../pdns/libtestremotebackend_la-nameserver.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-nameserver.lo `test -f '../../pdns/nameserver.cc' || echo '$(srcdir)/'`../../pdns/nameserver.cc + +../../pdns/libtestremotebackend_la-rcpgenerator.lo: ../../pdns/rcpgenerator.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-rcpgenerator.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-rcpgenerator.Tpo -c -o ../../pdns/libtestremotebackend_la-rcpgenerator.lo `test -f '../../pdns/rcpgenerator.cc' || echo '$(srcdir)/'`../../pdns/rcpgenerator.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-rcpgenerator.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-rcpgenerator.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/rcpgenerator.cc' object='../../pdns/libtestremotebackend_la-rcpgenerator.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-rcpgenerator.lo `test -f '../../pdns/rcpgenerator.cc' || echo '$(srcdir)/'`../../pdns/rcpgenerator.cc + +../../pdns/libtestremotebackend_la-unix_utility.lo: ../../pdns/unix_utility.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-unix_utility.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-unix_utility.Tpo -c -o ../../pdns/libtestremotebackend_la-unix_utility.lo `test -f '../../pdns/unix_utility.cc' || echo '$(srcdir)/'`../../pdns/unix_utility.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-unix_utility.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-unix_utility.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/unix_utility.cc' object='../../pdns/libtestremotebackend_la-unix_utility.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-unix_utility.lo `test -f '../../pdns/unix_utility.cc' || echo '$(srcdir)/'`../../pdns/unix_utility.cc + +../../pdns/libtestremotebackend_la-gss_context.lo: ../../pdns/gss_context.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-gss_context.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-gss_context.Tpo -c -o ../../pdns/libtestremotebackend_la-gss_context.lo `test -f '../../pdns/gss_context.cc' || echo '$(srcdir)/'`../../pdns/gss_context.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-gss_context.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-gss_context.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/gss_context.cc' object='../../pdns/libtestremotebackend_la-gss_context.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-gss_context.lo `test -f '../../pdns/gss_context.cc' || echo '$(srcdir)/'`../../pdns/gss_context.cc + +../../pdns/libtestremotebackend_la-json.lo: ../../pdns/json.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-json.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-json.Tpo -c -o ../../pdns/libtestremotebackend_la-json.lo `test -f '../../pdns/json.cc' || echo '$(srcdir)/'`../../pdns/json.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-json.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-json.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/json.cc' object='../../pdns/libtestremotebackend_la-json.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-json.lo `test -f '../../pdns/json.cc' || echo '$(srcdir)/'`../../pdns/json.cc + +libtestremotebackend_la-httpconnector.lo: httpconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libtestremotebackend_la-httpconnector.lo -MD -MP -MF $(DEPDIR)/libtestremotebackend_la-httpconnector.Tpo -c -o libtestremotebackend_la-httpconnector.lo `test -f 'httpconnector.cc' || echo '$(srcdir)/'`httpconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestremotebackend_la-httpconnector.Tpo $(DEPDIR)/libtestremotebackend_la-httpconnector.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='httpconnector.cc' object='libtestremotebackend_la-httpconnector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libtestremotebackend_la-httpconnector.lo `test -f 'httpconnector.cc' || echo '$(srcdir)/'`httpconnector.cc + +libtestremotebackend_la-pipeconnector.lo: pipeconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libtestremotebackend_la-pipeconnector.lo -MD -MP -MF $(DEPDIR)/libtestremotebackend_la-pipeconnector.Tpo -c -o libtestremotebackend_la-pipeconnector.lo `test -f 'pipeconnector.cc' || echo '$(srcdir)/'`pipeconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestremotebackend_la-pipeconnector.Tpo $(DEPDIR)/libtestremotebackend_la-pipeconnector.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pipeconnector.cc' object='libtestremotebackend_la-pipeconnector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libtestremotebackend_la-pipeconnector.lo `test -f 'pipeconnector.cc' || echo '$(srcdir)/'`pipeconnector.cc + +libtestremotebackend_la-unixconnector.lo: unixconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libtestremotebackend_la-unixconnector.lo -MD -MP -MF $(DEPDIR)/libtestremotebackend_la-unixconnector.Tpo -c -o libtestremotebackend_la-unixconnector.lo `test -f 'unixconnector.cc' || echo '$(srcdir)/'`unixconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestremotebackend_la-unixconnector.Tpo $(DEPDIR)/libtestremotebackend_la-unixconnector.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='unixconnector.cc' object='libtestremotebackend_la-unixconnector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libtestremotebackend_la-unixconnector.lo `test -f 'unixconnector.cc' || echo '$(srcdir)/'`unixconnector.cc + +libtestremotebackend_la-zmqconnector.lo: zmqconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libtestremotebackend_la-zmqconnector.lo -MD -MP -MF $(DEPDIR)/libtestremotebackend_la-zmqconnector.Tpo -c -o libtestremotebackend_la-zmqconnector.lo `test -f 'zmqconnector.cc' || echo '$(srcdir)/'`zmqconnector.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestremotebackend_la-zmqconnector.Tpo $(DEPDIR)/libtestremotebackend_la-zmqconnector.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='zmqconnector.cc' object='libtestremotebackend_la-zmqconnector.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libtestremotebackend_la-zmqconnector.lo `test -f 'zmqconnector.cc' || echo '$(srcdir)/'`zmqconnector.cc + +libtestremotebackend_la-remotebackend.lo: remotebackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libtestremotebackend_la-remotebackend.lo -MD -MP -MF $(DEPDIR)/libtestremotebackend_la-remotebackend.Tpo -c -o libtestremotebackend_la-remotebackend.lo `test -f 'remotebackend.cc' || echo '$(srcdir)/'`remotebackend.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestremotebackend_la-remotebackend.Tpo $(DEPDIR)/libtestremotebackend_la-remotebackend.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='remotebackend.cc' object='libtestremotebackend_la-remotebackend.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libtestremotebackend_la-remotebackend.lo `test -f 'remotebackend.cc' || echo '$(srcdir)/'`remotebackend.cc + +../../pdns/libtestremotebackend_la-pkcs11signers.lo: ../../pdns/pkcs11signers.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../../pdns/libtestremotebackend_la-pkcs11signers.lo -MD -MP -MF ../../pdns/$(DEPDIR)/libtestremotebackend_la-pkcs11signers.Tpo -c -o ../../pdns/libtestremotebackend_la-pkcs11signers.lo `test -f '../../pdns/pkcs11signers.cc' || echo '$(srcdir)/'`../../pdns/pkcs11signers.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../../pdns/$(DEPDIR)/libtestremotebackend_la-pkcs11signers.Tpo ../../pdns/$(DEPDIR)/libtestremotebackend_la-pkcs11signers.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='../../pdns/pkcs11signers.cc' object='../../pdns/libtestremotebackend_la-pkcs11signers.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestremotebackend_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../../pdns/libtestremotebackend_la-pkcs11signers.lo `test -f '../../pdns/pkcs11signers.cc' || echo '$(srcdir)/'`../../pdns/pkcs11signers.cc + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf ../../pdns/.libs ../../pdns/_libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../../pdns/$(DEPDIR)/$(am__dirstamp) + -rm -f ../../pdns/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local \ + clean-pkglibLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ../../pdns/$(DEPDIR) ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ../../pdns/$(DEPDIR) ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-local \ + clean-pkglibLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am 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-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +clean-local: + rm -f $(EXTRA_PROGRAMS) + +remotebackend_post.log: remotebackend_http.log + +remotebackend_json.log: remotebackend_http.log remotebackend_post.log + +../../pdns/dnslabeltext.cc: ../../pdns/dnslabeltext.rl + $(MAKE) -C ../../pdns dnslabeltext.cc + +# 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. +.NOEXPORT: diff --git a/modules/remotebackend/OBJECTFILES b/modules/remotebackend/OBJECTFILES new file mode 100644 index 0000000..fa80d54 --- /dev/null +++ b/modules/remotebackend/OBJECTFILES @@ -0,0 +1 @@ +remotebackend.lo unixconnector.lo httpconnector.lo pipeconnector.lo zmqconnector.lo diff --git a/modules/remotebackend/OBJECTLIBS b/modules/remotebackend/OBJECTLIBS new file mode 100644 index 0000000..e162d0d --- /dev/null +++ b/modules/remotebackend/OBJECTLIBS @@ -0,0 +1 @@ +$(LIBZMQ_LIBS) diff --git a/modules/remotebackend/httpconnector.cc b/modules/remotebackend/httpconnector.cc new file mode 100644 index 0000000..bf74849 --- /dev/null +++ b/modules/remotebackend/httpconnector.cc @@ -0,0 +1,429 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "remotebackend.hh" +#include +#include +#include + +#include +#include "pdns/lock.hh" + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +HTTPConnector::HTTPConnector(std::map options): d_socket(nullptr) { + + if (options.find("url") == options.end()) { + throw PDNSException("Cannot find 'url' option in the remote backend HTTP connector's parameters"); + } + + this->d_url = options.find("url")->second; + + try { + YaHTTP::URL url(d_url); + d_host = url.host; + d_port = url.port; + } + catch(const std::exception& e) { + throw PDNSException("Error parsing the 'url' option provided to the remote backend HTTP connector: " + std::string(e.what())); + } + + if (options.find("url-suffix") != options.end()) { + this->d_url_suffix = options.find("url-suffix")->second; + } else { + this->d_url_suffix = ""; + } + this->timeout = 2; + this->d_post = false; + this->d_post_json = false; + + if (options.find("timeout") != options.end()) { + this->timeout = std::stoi(options.find("timeout")->second)/1000; + } + if (options.find("post") != options.end()) { + std::string val = options.find("post")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post = true; + } + } + if (options.find("post_json") != options.end()) { + std::string val = options.find("post_json")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post_json = true; + } + } +} + +HTTPConnector::~HTTPConnector() { } + +void HTTPConnector::addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss) { + std::string sparam; + if (parameters[element] != Json()) + ss << "/" << YaHTTP::Utility::encodeURL(asString(parameters[element]), false); +} + +std::string HTTPConnector::buildMemberListArgs(std::string prefix, const Json& args) { + std::stringstream stream; + + for(const auto& pair: args.object_items()) { + if (pair.second.is_bool()) { + stream << (pair.second.bool_value()?"1":"0"); + } else if (pair.second.is_null()) { + stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]="; + } else { + stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]=" << YaHTTP::Utility::encodeURL(this->asString(pair.second), false); + } + stream << "&"; + } + + return stream.str().substr(0, stream.str().size()-1); // snip the trailing & +} + +// builds our request (near-restful) +void HTTPConnector::restful_requestbuilder(const std::string &method, const Json& parameters, YaHTTP::Request& req) +{ + std::stringstream ss; + std::string sparam; + std::string verb; + + // special names are qname, name, zonename, kind, others go to headers + + ss << d_url; + + ss << "/" << method; + + // add the url components, if found, in following order. + // id must be first due to the fact that the qname/name can be empty + + addUrlComponent(parameters, "id", ss); + addUrlComponent(parameters, "domain_id", ss); + addUrlComponent(parameters, "zonename", ss); + addUrlComponent(parameters, "qname", ss); + addUrlComponent(parameters, "name", ss); + addUrlComponent(parameters, "kind", ss); + addUrlComponent(parameters, "qtype", ss); + + // set the correct type of request based on method + if (method == "activateDomainKey" || method == "deactivateDomainKey") { + // create an empty post + req.preparePost(); + verb = "POST"; + } else if (method == "setTSIGKey") { + req.POST()["algorithm"] = parameters["algorithm"].string_value(); + req.POST()["content"] = parameters["content"].string_value(); + req.preparePost(); + verb = "PATCH"; + } else if (method == "deleteTSIGKey") { + verb = "DELETE"; + } else if (method == "addDomainKey") { + const Json& param = parameters["key"]; + req.POST()["flags"] = asString(param["flags"]); + req.POST()["active"] = (param["active"].bool_value() ? "1" : "0"); + req.POST()["content"] = param["content"].string_value(); + req.preparePost(); + verb = "PUT"; + } else if (method == "superMasterBackend") { + std::stringstream ss2; + addUrlComponent(parameters, "ip", ss); + addUrlComponent(parameters, "domain", ss); + // then we need to serialize rrset payload into POST + for(size_t index = 0; index < parameters["nsset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("nsset[" + std::to_string(index) + "]", parameters["nsset"][index]) << "&"; + } + req.body = ss2.str().substr(0, ss2.str().size()-1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "POST"; + } else if (method == "createSlaveDomain") { + addUrlComponent(parameters, "ip", ss); + addUrlComponent(parameters, "domain", ss); + if (parameters["account"].is_null() == false && parameters["account"].is_string()) { + req.POST()["account"] = parameters["account"].string_value(); + } + req.preparePost(); + verb = "PUT"; + } else if (method == "replaceRRSet") { + std::stringstream ss2; + for(size_t index = 0; index < parameters["rrset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("rrset[" + std::to_string(index) + "]", parameters["rrset"][index]); + } + req.body = ss2.str(); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } else if (method == "feedRecord") { + addUrlComponent(parameters, "trxid", ss); + req.body = buildMemberListArgs("rr", parameters["rr"]); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } else if (method == "feedEnts") { + std::stringstream ss2; + addUrlComponent(parameters, "trxid", ss); + for(const auto& param: parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; + } + for(const auto& param: parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; + } + req.body = ss2.str().substr(0, ss2.str().size()-1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } else if (method == "feedEnts3") { + std::stringstream ss2; + addUrlComponent(parameters, "domain", ss); + addUrlComponent(parameters, "trxid", ss); + ss2 << "times=" << parameters["times"].int_value() << "&salt=" << YaHTTP::Utility::encodeURL(parameters["salt"].string_value(), false) << "&narrow=" << (parameters["narrow"].bool_value() ? 1 : 0) << "&"; + for(const auto& param: parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; + } + for(const auto& param: parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; + } + req.body = ss2.str().substr(0, ss2.str().size()-1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } else if (method == "startTransaction") { + addUrlComponent(parameters, "domain", ss); + addUrlComponent(parameters, "trxid", ss); + req.preparePost(); + verb = "POST"; + } else if (method == "commitTransaction" || method == "abortTransaction") { + addUrlComponent(parameters, "trxid", ss); + req.preparePost(); + verb = "POST"; + } else if (method == "setDomainMetadata") { + // copy all metadata values into post + std::stringstream ss2; + // this one has values too + if (parameters["value"].is_array()) { + for(const auto& val: parameters["value"].array_items()) { + ss2 << "value[]=" << YaHTTP::Utility::encodeURL(val.string_value(), false) << "&"; + } + } + req.body = ss2.str().substr(0, ss2.str().size()-1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } else if (method == "removeDomainKey") { + // this one is delete + verb = "DELETE"; + } else if (method == "setNotified") { + req.POST()["serial"] = std::to_string(parameters["serial"].number_value()); + req.preparePost(); + verb = "PATCH"; + } else if (method == "directBackendCmd") { + req.POST()["query"] = parameters["query"].string_value(); + req.preparePost(); + verb = "POST"; + } else if (method == "searchRecords" || method == "searchComments") { + req.GET()["pattern"] = parameters["pattern"].string_value(); + req.GET()["maxResults"] = std::to_string(parameters["maxResults"].int_value()); + verb = "GET"; + } else if (method == "getAllDomains") { + req.GET()["includeDisabled"] = (parameters["include_disabled"].bool_value()?"true":"false"); + verb = "GET"; + } else { + // perform normal get + verb = "GET"; + } + + // put everything else into headers + for(const auto& pair: parameters.object_items()) { + std::string member = pair.first; + // whitelist header parameters + if ((member == "trxid" || + member == "local" || + member == "remote" || + member == "real-remote" || + member == "zone-id")) { + std::string hdr = "x-remotebackend-" + member; + req.headers[hdr] = asString(pair.second); + } + }; + + // finally add suffix and store url + ss << d_url_suffix; + + req.setup(verb, ss.str()); + req.headers["accept"] = "application/json"; +} + +void HTTPConnector::post_requestbuilder(const Json& input, YaHTTP::Request& req) { + if (this->d_post_json) { + std::string out = input.dump(); + req.setup("POST", d_url); + // simple case, POST JSON into url. nothing fancy. + req.headers["Content-Type"] = "text/javascript; charset=utf-8"; + req.headers["Content-Length"] = std::to_string(out.size()); + req.headers["accept"] = "application/json"; + req.body = out; + } else { + std::stringstream url,content; + // call url/method.suffix + url << d_url << "/" << input["method"].string_value() << d_url_suffix; + req.setup("POST", url.str()); + // then build content + req.POST()["parameters"] = input["parameters"].dump(); + req.preparePost(); + req.headers["accept"] = "application/json"; + } +} + +int HTTPConnector::send_message(const Json& input) { + int rv,ec,fd; + + std::vector members; + std::string method; + std::ostringstream out; + + // perform request + YaHTTP::Request req; + + if (d_post) + post_requestbuilder(input, req); + else + restful_requestbuilder(input["method"].string_value(), input["parameters"], req); + + rv = -1; + req.headers["connection"] = "Keep-Alive"; // see if we can streamline requests (not needed, strictly speaking) + + out << req; + + // try sending with current socket, if it fails retry with new socket + if (this->d_socket != nullptr) { + fd = this->d_socket->getHandle(); + // there should be no data waiting + if (waitForRWData(fd, true, 0, 1000) < 1) { + try { + d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); + rv = 1; + } catch (NetworkError& ne) { + g_log<d_socket.reset(); + + // connect using tcp + struct addrinfo *gAddr, *gAddrPtr, hints; + std::string sPort = std::to_string(d_port); + memset(&hints,0,sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if ((ec = getaddrinfo(d_host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) { + // try to connect to each address. + gAddrPtr = gAddr; + + while(gAddrPtr) { + try { + d_socket = std::unique_ptr(new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol)); + d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen); + d_socket->connect(d_addr); + d_socket->setNonBlocking(); + d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); + rv = 1; + } catch (NetworkError& ne) { + g_log< -1) break; + d_socket.reset(); + gAddrPtr = gAddrPtr->ai_next; + } + freeaddrinfo(gAddr); + } else { + g_log<readWithTimeout(buffer, sizeof(buffer), timeout); + if (rd==0) + throw NetworkError("EOF while reading"); + if (rd<0) + throw NetworkError(std::string(strerror(rd))); + arl.feed(std::string(buffer, rd)); + } + // timeout occured. + if (arl.ready() == false) + throw NetworkError("timeout"); + } catch (NetworkError &ne) { + g_log<= 400) { + // bad. + return -1; + } + + int rv = -1; + std::string err; + output = Json::parse(resp.body, err); + if (output != nullptr) return resp.body.size(); + g_log< optionsMap): d_pid(-1) { + if (optionsMap.count("command") == 0) { + g_log<command = optionsMap.find("command")->second; + this->options = optionsMap; + d_timeout=2000; + + if (optionsMap.find("timeout") != optionsMap.end()) { + d_timeout = std::stoi(optionsMap.find("timeout")->second); + } + + d_fd1[0] = d_fd1[1] = -1; + d_fd2[0] = d_fd2[1] = -1; +} + +PipeConnector::~PipeConnector(){ + int status; + // just in case... + if (d_pid == -1) return; + + if(!waitpid(d_pid, &status, WNOHANG)) { + kill(d_pid, 9); + waitpid(d_pid, &status, 0); + } + + if (d_fd1[1]) { + close(d_fd1[1]); + } +} + +void PipeConnector::launch() { + // no relaunch + if (d_pid > 0 && checkStatus()) return; + + std::vector v; + split(v, command, is_any_of(" ")); + + std::vectorargv(v.size()+1); + argv[v.size()]=0; + + for (size_t n = 0; n < v.size(); n++) + argv[n]=v[n].c_str(); + + signal(SIGPIPE, SIG_IGN); + + if(access(argv[0],X_OK)) // check before fork so we can throw + throw PDNSException("Command '"+string(argv[0])+"' cannot be executed: "+stringerror()); + + if(pipe(d_fd1)<0 || pipe(d_fd2)<0) + throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(errno))); + + if((d_pid=fork())<0) + throw PDNSException("Unable to fork for coprocess: "+stringerror()); + else if(d_pid>0) { // parent speaking + close(d_fd1[0]); + setCloseOnExec(d_fd1[1]); + close(d_fd2[1]); + setCloseOnExec(d_fd2[0]); + if(!(d_fp=std::unique_ptr(fdopen(d_fd2[0],"r"), fclose))) + throw PDNSException("Unable to associate a file pointer with pipe: "+stringerror()); + if (d_timeout) + setbuf(d_fp.get(),0); // no buffering please, confuses poll + } + else if(!d_pid) { // child + signal(SIGCHLD, SIG_DFL); // silence a warning from perl + close(d_fd1[1]); + close(d_fd2[0]); + + if(d_fd1[0]!= 0) { + dup2(d_fd1[0], 0); + close(d_fd1[0]); + } + + if(d_fd2[1]!= 1) { + dup2(d_fd2[1], 1); + close(d_fd2[1]); + } + + // stdin & stdout are now connected, fire up our coprocess! + + if(execv(argv[0], const_cast(argv.data()))<0) // now what + exit(123); + + /* not a lot we can do here. We shouldn't return because that will leave a forked process around. + no way to log this either - only thing we can do is make sure that our parent catches this soonest! */ + } + + Json::array parameters; + Json msg = Json(Json::object{ + { "method", "initialize" }, + { "parameters", Json(options) }, + }); + + this->send(msg); + msg = nullptr; + if (this->recv(msg)==false) { + g_log<0; +} + +/** + * Helper for handling receiving of data. + * Basically what happens here is that we check + * that the receiving happened ok, and extract + * result. Logging is performed here, too. + */ +bool Connector::recv(Json& value) { + if (recv_message(value)>0) { + bool rv = true; + // check for error + if (value["result"] == Json()) + return false; + if (value["result"].is_bool() && boolFromJson(value, "result", false) == false) + rv = false; + for(const auto& message: value["log"].array_items()) + g_log<d_connstr = getArg("connection-string"); + this->d_dnssec = mustDo("dnssec"); + this->d_index = -1; + this->d_trxid = 0; + + build(); +} + +RemoteBackend::~RemoteBackend() { } + +bool RemoteBackend::send(Json& value) { + try { + return connector->send(value); + } catch (PDNSException &ex) { + g_log<connector.reset(); + build(); + return false; +} + +bool RemoteBackend::recv(Json& value) { + try { + return connector->recv(value); + } catch (PDNSException &ex) { + g_log<connector.reset(); + build(); + return false; +} + + +/** + * Builds connector based on options + * Currently supports unix,pipe and http + */ +int RemoteBackend::build() { + std::vector parts; + std::string type; + std::string opts; + std::map options; + + // connstr is of format "type:options" + size_t pos; + pos = d_connstr.find_first_of(":"); + if (pos == std::string::npos) + throw PDNSException("Invalid connection string: malformed"); + + type = d_connstr.substr(0, pos); + opts = d_connstr.substr(pos+1); + + // tokenize the string on comma + stringtok(parts, opts, ","); + + // find out some options and parse them while we're at it + for(const auto& opt: parts) { + std::string key,val; + // make sure there is something else than air in the option... + if (opt.find_first_not_of(" ") == std::string::npos) continue; + + // split it on '='. if not found, we treat it as "yes" + pos = opt.find_first_of("="); + + if (pos == std::string::npos) { + key = opt; + val = "yes"; + } else { + key = opt.substr(0,pos); + val = opt.substr(pos+1); + } + options[key] = val; + } + + // connectors know what they are doing + if (type == "unix") { + this->connector = std::unique_ptr(new UnixsocketConnector(options)); + } else if (type == "http") { + this->connector = std::unique_ptr(new HTTPConnector(options)); + } else if (type == "zeromq") { +#ifdef REMOTEBACKEND_ZEROMQ + this->connector = std::unique_ptr(new ZeroMQConnector(options)); +#else + throw PDNSException("Invalid connection string: zeromq connector support not enabled. Recompile with --enable-remotebackend-zeromq"); +#endif + } else if (type == "pipe") { + this->connector = std::unique_ptr(new PipeConnector(options)); + } else { + throw PDNSException("Invalid connection string: unknown connector"); + } + + return -1; +} + +/** + * The functions here are just remote json stubs that send and receive the method call + * data is mainly left alone, some defaults are assumed. + */ +void RemoteBackend::lookup(const QType &qtype, const DNSName& qdomain, DNSPacket *pkt_p, int zoneId) { + if (d_index != -1) + throw PDNSException("Attempt to lookup while one running"); + + string localIP="0.0.0.0"; + string remoteIP="0.0.0.0"; + string realRemote="0.0.0.0/0"; + + if (pkt_p) { + localIP=pkt_p->getLocal().toString(); + realRemote = pkt_p->getRealRemote().toString(); + remoteIP = pkt_p->getRemote().toString(); + } + + Json query = Json::object{ + { "method", "lookup" }, + { "parameters", Json::object{ + { "qtype", qtype.getName() }, + { "qname", qdomain.toString() }, + { "remote", remoteIP }, + { "local", localIP }, + { "real-remote", realRemote }, + { "zone-id", zoneId } + }} + }; + + if (this->send(query) == false || this->recv(d_result) == false) { + return; + } + + // OK. we have result parameters in result. do not process empty result. + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) + return; + + d_index = 0; +} + +bool RemoteBackend::list(const DNSName& target, int domain_id, bool include_disabled) { + if (d_index != -1) + throw PDNSException("Attempt to lookup while one running"); + + Json query = Json::object{ + { "method", "list" }, + { "parameters", Json::object{ + { "zonename", target.toString() }, + { "domain_id", domain_id }, + { "include_disabled", include_disabled } + }} + }; + + if (this->send(query) == false || this->recv(d_result) == false) + return false; + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) + return false; + + d_index = 0; + return true; +} + +bool RemoteBackend::get(DNSResourceRecord &rr) { + if (d_index == -1) return false; + + rr.qtype = stringFromJson(d_result["result"][d_index], "qtype"); + rr.qname = DNSName(stringFromJson(d_result["result"][d_index], "qname")); + rr.qclass = QClass::IN; + rr.content = stringFromJson(d_result["result"][d_index], "content"); + rr.ttl = d_result["result"][d_index]["ttl"].int_value(); + rr.domain_id = intFromJson(d_result["result"][d_index], "domain_id", -1); + if (d_dnssec) + rr.auth = intFromJson(d_result["result"][d_index], "auth", 1); + else + rr.auth = 1; + rr.scopeMask = d_result["result"][d_index]["scopeMask"].int_value(); + d_index++; + + // id index is out of bounds, we know the results end here. + if (d_index == static_cast(d_result["result"].array_items().size())) { + d_result = Json(); + d_index = -1; + } + return true; +} + +bool RemoteBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "getBeforeAndAfterNamesAbsolute" }, + { "parameters", Json::object { + { "id", Json(static_cast(id)) }, + { "qname", qname.toString() } + }} + }; + Json answer; + + if (this->send(query) == false || this->recv(answer) == false) + return false; + + unhashed = DNSName(stringFromJson(answer["result"], "unhashed")); + before.clear(); + after.clear(); + if (answer["result"]["before"] != Json()) + before = DNSName(stringFromJson(answer["result"], "before")); + if (answer["result"]["after"] != Json()) + after = DNSName(stringFromJson(answer["result"], "after")); + + return true; +} + +bool RemoteBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { + Json query = Json::object{ + { "method", "getAllDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; + + if (this->send(query) == false) + return false; + + meta.clear(); + + Json answer; + // not mandatory to implement + if (this->recv(answer) == false) + return true; + + for(const auto& pair: answer["result"].object_items()) { + if (pair.second.is_array()) { + for(const auto& val: pair.second.array_items()) + meta[pair.first].push_back(asString(val)); + } else { + meta[pair.first].push_back(asString(pair.second)); + } + } + + return true; +} + +bool RemoteBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { + Json query = Json::object{ + { "method", "getDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "kind", kind } + }} + }; + + if (this->send(query) == false) + return false; + + meta.clear(); + + Json answer; + // not mandatory to implement + if (this->recv(answer) == false) + return true; + + if (answer["result"].is_array()) { + for(const auto& row: answer["result"].array_items()) + meta.push_back(row.string_value()); + } else if (answer["result"].is_string()) { + meta.push_back(answer["result"].string_value()); + } + + return true; +} + +bool RemoteBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) { + Json query = Json::object{ + { "method", "setDomainMetadata" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "kind", kind }, + { "value", meta } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return boolFromJson(answer, "result", false); +} + + +bool RemoteBackend::getDomainKeys(const DNSName& name, std::vector& keys) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "getDomainKeys" }, + { "parameters", Json::object{ + { "name", name.toString() } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + keys.clear(); + + for(const auto& jsonKey: answer["result"].array_items()) { + DNSBackend::KeyData key; + key.id = intFromJson(jsonKey, "id"); + key.flags = intFromJson(jsonKey, "flags"); + key.active = asBool(jsonKey["active"]); + key.content = stringFromJson(jsonKey, "content"); + keys.push_back(key); + } + + return true; +} + +bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "removeDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "addDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "key", Json::object { + { "flags", static_cast(key.flags) }, + { "active", key.active }, + { "content", key.content } + }} + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + id = answer["result"].int_value(); + return id >= 0; +} + +bool RemoteBackend::activateDomainKey(const DNSName& name, unsigned int id) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "activateDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::deactivateDomainKey(const DNSName& name, unsigned int id) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "deactivateDomainKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "id", static_cast(id) } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::doesDNSSEC() { + return d_dnssec; +} + +bool RemoteBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "getTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + (*algorithm) = DNSName(stringFromJson(answer["result"], "algorithm")); + (*content) = stringFromJson(answer["result"], "content"); + + return true; +} + +bool RemoteBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const std::string& content) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + + Json query = Json::object{ + { "method", "setTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() }, + { "algorithm", algorithm.toString() }, + { "content", content } + }} + }; + + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::deleteTSIGKey(const DNSName& name) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + Json query = Json::object{ + { "method", "deleteTSIGKey" }, + { "parameters", Json::object { + { "name", name.toString() } + }} + }; + + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::getTSIGKeys(std::vector& keys) { + // no point doing dnssec if it's not supported + if (d_dnssec == false) return false; + Json query = Json::object{ + { "method", "getTSIGKeys" }, + { "parameters", Json::object { + }} + }; + + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + for(const auto& jsonKey: answer["result"].array_items()) { + struct TSIGKey key; + key.name = DNSName(stringFromJson(jsonKey, "name")); + key.algorithm = DNSName(stringFromJson(jsonKey, "algorithm")); + key.key = stringFromJson(jsonKey, "content"); + keys.push_back(key); + } + + return true; +} + +void RemoteBackend::parseDomainInfo(const Json &obj, DomainInfo &di) +{ + di.id = intFromJson(obj, "id", -1); + di.zone = DNSName(stringFromJson(obj, "zone")); + for(const auto& master: obj["masters"].array_items()) + di.masters.push_back(ComboAddress(master.string_value(), 53)); + + di.notified_serial = static_cast(doubleFromJson(obj, "notified_serial", -1)); + di.serial = static_cast(obj["serial"].number_value()); + di.last_check = static_cast(obj["last_check"].number_value()); + + string kind = ""; + if (obj["kind"].is_string()) { + kind = stringFromJson(obj, "kind"); + } + if (kind == "master") { + di.kind = DomainInfo::Master; + } else if (kind == "slave") { + di.kind = DomainInfo::Slave; + } else { + di.kind = DomainInfo::Native; + } + di.backend = this; +} + +bool RemoteBackend::getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial) { + if (domain.empty()) return false; + Json query = Json::object{ + { "method", "getDomainInfo" }, + { "parameters", Json::object { + { "name", domain.toString() } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + this->parseDomainInfo(answer["result"], di); + return true; +} + +void RemoteBackend::setNotified(uint32_t id, uint32_t serial) { + Json query = Json::object{ + { "method", "setNotified" }, + { "parameters", Json::object { + { "id", static_cast(id) }, + { "serial", static_cast(serial) } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) { + g_log<&nsset, string* nameserver, string *account, DNSBackend **ddb) +{ + Json::array rrset; + + for(const auto& ns: nsset) { + rrset.push_back(Json::object{ + { "qtype", ns.qtype.getName() }, + { "qname", ns.qname.toString() }, + { "qclass", QClass::IN }, + { "content", ns.content }, + { "ttl", static_cast(ns.ttl) }, + { "auth", ns.auth } + }); + } + + Json query = Json::object{ + { "method", "superMasterBackend" }, + { "parameters", Json::object { + { "ip", ip }, + { "domain", domain.toString() }, + { "nsset", rrset } + }} + }; + + *ddb = 0; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + // we are the backend + *ddb = this; + + // we allow simple true as well... + if (answer["result"].is_object()) { + *account = stringFromJson(answer["result"], "account"); + *nameserver = stringFromJson(answer["result"], "nameserver"); + } + + return true; +} + +bool RemoteBackend::createSlaveDomain(const string &ip, const DNSName& domain, const string& nameserver, const string &account) { + Json query = Json::object{ + { "method", "createSlaveDomain" }, + { "parameters", Json::object { + { "ip", ip }, + { "domain", domain.toString() }, + { "nameserver", nameserver }, + { "account", account }, + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qtype, const vector& rrset) { + Json::array json_rrset; + for(const auto& rr: rrset) { + json_rrset.push_back(Json::object{ + { "qtype", rr.qtype.getName() }, + { "qname", rr.qname.toString() }, + { "qclass", QClass::IN }, + { "content", rr.content }, + { "ttl", static_cast(rr.ttl) }, + { "auth", rr.auth } + }); + } + + Json query = Json::object{ + { "method", "replaceRRSet" }, + { "parameters", Json::object { + { "domain_id", static_cast(domain_id) }, + { "qname", qname.toString() }, + { "qtype", qtype.getName() }, + { "trxid", static_cast(d_trxid) }, + { "rrset", json_rrset } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3) { + Json query = Json::object{ + { "method", "feedRecord" }, + { "parameters", Json::object{ + { "rr", Json::object{ + { "qtype", rr.qtype.getName() }, + { "qname", rr.qname.toString() }, + { "qclass", QClass::IN }, + { "content", rr.content }, + { "ttl", static_cast(rr.ttl) }, + { "auth", rr.auth }, + { "ordername", (ordername.empty()?Json():ordername.toString()) } + }}, + { "trxid", static_cast(d_trxid) }, + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; // XXX FIXME this API should not return 'true' I think -ahu +} + +bool RemoteBackend::feedEnts(int domain_id, map& nonterm) { + Json::array nts; + + for(const auto& t: nonterm) + nts.push_back(Json::object{ + { "nonterm", t.first.toString() }, + { "auth", t.second } + }); + + Json query = Json::object{ + { "method", "feedEnts" }, + { "parameters", Json::object{ + { "domain_id", domain_id }, + { "trxid", static_cast(d_trxid) }, + { "nonterm", nts } + }}, + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) { + Json::array nts; + + for(const auto& t: nonterm) + nts.push_back(Json::object{ + { "nonterm", t.first.toString() }, + { "auth", t.second } + }); + + Json query = Json::object{ + { "method", "feedEnts3" }, + { "parameters", Json::object{ + { "domain_id", domain_id }, + { "domain", domain.toString() }, + { "times", ns3prc.d_iterations }, + { "salt", ns3prc.d_salt }, + { "narrow", narrow }, + { "trxid", static_cast(d_trxid) }, + { "nonterm", nts } + }}, + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::startTransaction(const DNSName& domain, int domain_id) { + this->d_trxid = time((time_t*)NULL); + + Json query = Json::object{ + { "method", "startTransaction" }, + { "parameters", Json::object{ + { "domain", domain.toString() }, + { "domain_id", domain_id }, + { "trxid", static_cast(d_trxid) } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) { + d_trxid = -1; + return false; + } + return true; + +} +bool RemoteBackend::commitTransaction() { + if (d_trxid == -1) return false; + + Json query = Json::object{ + { "method", "commitTransaction" }, + { "parameters", Json::object{ + { "trxid", static_cast(d_trxid) } + }} + }; + + d_trxid = -1; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::abortTransaction() { + if (d_trxid == -1) return false; + + Json query = Json::object{ + { "method", "abortTransaction" }, + { "parameters", Json::object{ + { "trxid", static_cast(d_trxid) } + }} + }; + + d_trxid = -1; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; +} + +string RemoteBackend::directBackendCmd(const string& querystr) { + Json query = Json::object{ + { "method", "directBackendCmd" }, + { "parameters", Json::object{ + { "query", querystr } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return "backend command failed"; + + return asString(answer["result"]); +} + +bool RemoteBackend::searchRecords(const string &pattern, int maxResults, vector& result) +{ + Json query = Json::object{ + { "method", "searchRecords" }, + { "parameters", Json::object{ + { "pattern", pattern }, + { "maxResults", maxResults } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + if (answer["result"].is_array() == false) + return false; + + for(const auto& row: answer["result"].array_items()) { + DNSResourceRecord rr; + rr.qtype = stringFromJson(row, "qtype"); + rr.qname = DNSName(stringFromJson(row, "qname")); + rr.qclass = QClass::IN; + rr.content = stringFromJson(row, "content"); + rr.ttl = row["ttl"].int_value(); + rr.domain_id = intFromJson(row, "domain_id", -1); + if (d_dnssec) + rr.auth = intFromJson(row, "auth", 1); + else + rr.auth = 1; + rr.scopeMask = row["scopeMask"].int_value(); + result.push_back(rr); + } + + return true; +} + +bool RemoteBackend::searchComments(const string &pattern, int maxResults, vector& result) +{ + // FIXME: Implement Comment API + return false; +} + +void RemoteBackend::getAllDomains(vector *domains, bool include_disabled) +{ + Json query = Json::object{ + { "method", "getAllDomains" }, + { "parameters", Json::object{ + { "include_disabled", include_disabled } + }} + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return; + + if (answer["result"].is_array() == false) + return; + + for(const auto& row: answer["result"].array_items()) { + DomainInfo di; + this->parseDomainInfo(row, di); + domains->push_back(di); + } +} + +void RemoteBackend::getUpdatedMasters(vector* domains) +{ + Json query = Json::object{ + { "method", "getUpdatedMasters" }, + { "parameters", Json::object{ } }, + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return; + + if (answer["result"].is_array() == false) + return; + + for(const auto& row: answer["result"].array_items()) { + DomainInfo di; + this->parseDomainInfo(row, di); + domains->push_back(di); + } +} + +DNSBackend *RemoteBackend::maker() +{ + try { + return new RemoteBackend(); + } + catch(...) { + g_log< +#include + +#include +#include "pdns/arguments.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/logger.hh" +#include "pdns/namespaces.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/sstuff.hh" +#include "pdns/json.hh" +#include "pdns/lock.hh" +#include "yahttp/yahttp.hpp" + +#ifdef REMOTEBACKEND_ZEROMQ +#include + +// If the available ZeroMQ library version is < 2.x, create macros for the zmq_msg_send/recv functions +#ifndef HAVE_ZMQ_MSG_SEND +#define zmq_msg_send(msg, socket, flags) zmq_send(socket, msg, flags) +#define zmq_msg_recv(msg, socket, flags) zmq_recv(socket, msg, flags) +#endif +#endif + +using json11::Json; + +class Connector { + public: + virtual ~Connector() {}; + bool send(Json &value); + bool recv(Json &value); + virtual int send_message(const Json &input) = 0; + virtual int recv_message(Json &output) = 0; + protected: + string asString(const Json& value) { + if (value.is_number()) return std::to_string(value.int_value()); + if (value.is_bool()) return (value.bool_value()?"1":"0"); + if (value.is_string()) return value.string_value(); + throw JsonException("Json value not convertible to String"); + }; +}; + +// fwd declarations +class UnixsocketConnector: public Connector { + public: + UnixsocketConnector(std::map options); + virtual ~UnixsocketConnector(); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); + private: + ssize_t read(std::string &data); + ssize_t write(const std::string &data); + void reconnect(); + std::map options; + int fd; + std::string path; + bool connected; + int timeout; +}; + +class HTTPConnector: public Connector { + public: + + HTTPConnector(std::map options); + ~HTTPConnector(); + + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); + private: + std::string d_url; + std::string d_url_suffix; + std::string d_data; + int timeout; + bool d_post; + bool d_post_json; + void restful_requestbuilder(const std::string &method, const Json ¶meters, YaHTTP::Request& req); + void post_requestbuilder(const Json &input, YaHTTP::Request& req); + void addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss); + std::string buildMemberListArgs(std::string prefix, const Json& args); + std::unique_ptr d_socket; + ComboAddress d_addr; + std::string d_host; + uint16_t d_port; +}; + +#ifdef REMOTEBACKEND_ZEROMQ +class ZeroMQConnector: public Connector { + public: + ZeroMQConnector(std::map options); + virtual ~ZeroMQConnector(); + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); + private: + void connect(); + std::string d_endpoint; + int d_timeout; + int d_timespent; + std::map d_options; + std::unique_ptr d_ctx; + std::unique_ptr d_sock; +}; +#endif + +class PipeConnector: public Connector { + public: + + PipeConnector(std::map options); + ~PipeConnector(); + + virtual int send_message(const Json &input); + virtual int recv_message(Json &output); + + private: + + void launch(); + bool checkStatus(); + + std::string command; + std::map options; + + int d_fd1[2], d_fd2[2]; + int d_pid; + int d_timeout; + std::unique_ptr d_fp{nullptr, fclose}; +}; + +class RemoteBackend : public DNSBackend +{ + public: + RemoteBackend(const std::string &suffix=""); + ~RemoteBackend(); + + void lookup(const QType &qtype, const DNSName& qdomain, DNSPacket *pkt_p=0, int zoneId=-1) override; + bool get(DNSResourceRecord &rr) override; + bool list(const DNSName& target, int domain_id, bool include_disabled=false) override; + + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool getDomainKeys(const DNSName& name, std::vector& keys) override; + bool getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) override; + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; + bool setDomainMetadata(const DNSName& name, const string& kind, const std::vector >& meta) override; + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial=true ) override; + void setNotified(uint32_t id, uint32_t serial) override; + bool doesDNSSEC() override; + bool superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string *nameserver, string *account, DNSBackend **ddb) override; + bool createSlaveDomain(const string &ip, const DNSName& domain, const string& nameserver, const string &account) override; + bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; + bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + bool feedEnts(int domain_id, map& nonterm) override; + bool feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; + bool startTransaction(const DNSName& domain, int domain_id) override; + bool commitTransaction() override; + bool abortTransaction() override; + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; + bool deleteTSIGKey(const DNSName& name) override; + bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + string directBackendCmd(const string& querystr) override; + bool searchRecords(const string &pattern, int maxResults, vector& result) override; + bool searchComments(const string &pattern, int maxResults, vector& result) override; + void getAllDomains(vector *domains, bool include_disabled=false) override; + void getUpdatedMasters(vector* domains) override; + + static DNSBackend *maker(); + + private: + int build(); + std::unique_ptr connector; + bool d_dnssec; + Json d_result; + int d_index; + int64_t d_trxid; + std::string d_connstr; + + bool send(Json &value); + bool recv(Json &value); + + string asString(const Json& value) { + if (value.is_number()) return std::to_string(value.int_value()); + if (value.is_bool()) return (value.bool_value()?"1":"0"); + if (value.is_string()) return value.string_value(); + throw JsonException("Json value not convertible to String"); + }; + + bool asBool(const Json& value) { + if (value.is_bool()) return value.bool_value(); + try { + string val = asString(value); + if (val == "0") return false; + if (val == "1") return true; + } catch (const JsonException&) {}; + throw JsonException("Json value not convertible to boolean"); + }; + + void parseDomainInfo(const json11::Json &obj, DomainInfo &di); +}; +#endif diff --git a/modules/remotebackend/test-remotebackend-http.cc b/modules/remotebackend/test-remotebackend-http.cc new file mode 100644 index 0000000..e92d4bb --- /dev/null +++ b/modules/remotebackend/test-remotebackend-http.cc @@ -0,0 +1,83 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#include +#include + +#include + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); diff --git a/modules/remotebackend/test-remotebackend-json.cc b/modules/remotebackend/test-remotebackend-json.cc new file mode 100644 index 0000000..fb56ee1 --- /dev/null +++ b/modules/remotebackend/test-remotebackend-json.cc @@ -0,0 +1,82 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#include +#include + +#include + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns/endpoint.json,post=1,post_json=1"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); diff --git a/modules/remotebackend/test-remotebackend-keys.hh b/modules/remotebackend/test-remotebackend-keys.hh new file mode 100644 index 0000000..5543574 --- /dev/null +++ b/modules/remotebackend/test-remotebackend-keys.hh @@ -0,0 +1,24 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +DNSBackend::KeyData k1 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: qpe9fxlN4dBT38cLPWtqljZhcJjbqRprj9XsYmf2/uFu4kA5sHYrlQY7H9lpzGJPRfOAfxShBpKs1AVaVInfJQ==\nPublicExponent: AQAB\nPrivateExponent: Ad3YogzXvVDLsWuAfioY571QlolbdTbzVlhLEMLD6dSRx+xcZgw6c27ak2HAH00iSKTvqK3AyeaK8Eqy/oJ5QQ==\nPrime1: wo8LZrdU2y0xLGCeLhwziQDDtTMi18NEIwlx8tUPnhs=\nPrime2: 4HcuFqgo7NOiXFvN+V2PT+QaIt2+oi6D2m8/qtTDS78=\nExponent1: GUdCoPbi9JM7l1t6Ud1iKMPLqchaF5SMTs0UXAuous8=\nExponent2: nzgKqimX9f1corTAEw0pddrwKyEtcu8ZuhzFhZCsAxM=\nCoefficient: YGNxbulf5GTNiIu0oNKmAF0khNtx9layjOPEI0R4/RY="), 1, 257, true }; + +DNSBackend::KeyData k2 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: tY2TAMgL/whZdSbn2aci4wcMqohO24KQAaq5RlTRwQ33M8FYdW5fZ3DMdMsSLQUkjGnKJPKEdN3Qd4Z5b18f+w==\nPublicExponent: AQAB\nPrivateExponent: BB6xibPNPrBV0PUp3CQq0OdFpk9v9EZ2NiBFrA7osG5mGIZICqgOx/zlHiHKmX4OLmL28oU7jPKgogeuONXJQQ==\nPrime1: yjxe/iHQ4IBWpvCmuGqhxApWF+DY9LADIP7bM3Ejf3M=\nPrime2: 5dGWTyYEQRBVK74q1a64iXgaNuYm1pbClvvZ6ccCq1k=\nExponent1: TwM5RebmWeAqerzJFoIqw5IaQugJO8hM4KZR9A4/BTs=\nExponent2: bpV2HSmu3Fvuj7jWxbFoDIXlH0uJnrI2eg4/4hSnvSk=\nCoefficient: e2uDDWN2zXwYa2P6VQBWQ4mR1ZZjFEtO/+YqOJZun1Y="), 2, 256, true }; diff --git a/modules/remotebackend/test-remotebackend-pipe.cc b/modules/remotebackend/test-remotebackend-pipe.cc new file mode 100644 index 0000000..8d4ca4e --- /dev/null +++ b/modules/remotebackend/test-remotebackend-pipe.cc @@ -0,0 +1,87 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/dnsrecords.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="pipe:command=unittest_pipe.rb"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); + diff --git a/modules/remotebackend/test-remotebackend-post.cc b/modules/remotebackend/test-remotebackend-post.cc new file mode 100644 index 0000000..785fb64 --- /dev/null +++ b/modules/remotebackend/test-remotebackend-post.cc @@ -0,0 +1,82 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#include +#include + +#include + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns,post=1"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); diff --git a/modules/remotebackend/test-remotebackend-unix.cc b/modules/remotebackend/test-remotebackend-unix.cc new file mode 100644 index 0000000..bf3f9da --- /dev/null +++ b/modules/remotebackend/test-remotebackend-unix.cc @@ -0,0 +1,87 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/dnsrecords.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="unix:path=/tmp/remotebackend.sock"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); + diff --git a/modules/remotebackend/test-remotebackend-zeromq.cc b/modules/remotebackend/test-remotebackend-zeromq.cc new file mode 100644 index 0000000..9a08fc8 --- /dev/null +++ b/modules/remotebackend/test-remotebackend-zeromq.cc @@ -0,0 +1,99 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE unit + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/dnsrecords.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" +#include "pdns/auth-packetcache.hh" +#include "pdns/auth-querycache.hh" + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +}; + +class RemoteLoader +{ + public: + RemoteLoader(); +}; + +DNSBackend *be; + +#ifdef REMOTEBACKEND_ZEROMQ +#include + +struct RemotebackendSetup { + RemotebackendSetup() { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir")="./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string")="zeromq:endpoint=ipc:///tmp/remotebackend.0"; + ::arg().set("remote-dnssec")="yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); + } catch (PDNSException &ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); + }; + } + ~RemotebackendSetup() { } +}; + +BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); + +#else + +#include + +int main(void) { + std::cout << "No HTTP support in remotebackend - skipping test" << std::endl; + return 0; +} + +#endif diff --git a/modules/remotebackend/test-remotebackend.cc b/modules/remotebackend/test-remotebackend.cc new file mode 100644 index 0000000..acabae2 --- /dev/null +++ b/modules/remotebackend/test-remotebackend.cc @@ -0,0 +1,343 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include "pdns/namespaces.hh" +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/json.hh" +#include "pdns/statbag.hh" + +#include "test-remotebackend-keys.hh" + +extern DNSBackend *be; + +BOOST_AUTO_TEST_SUITE(test_remotebackend_so) + +BOOST_AUTO_TEST_CASE(test_method_lookup) { + BOOST_TEST_MESSAGE("Testing lookup method"); + DNSResourceRecord rr; + be->lookup(QType(QType::SOA), DNSName("unit.test.")); + // then try to get() + BOOST_CHECK(be->get(rr)); // and this should be TRUE. + // then we check rr contains what we expect + BOOST_CHECK_EQUAL(rr.qname.toString(), "unit.test."); + BOOST_CHECK_MESSAGE(rr.qtype == QType::SOA, "returned qtype was not SOA"); + BOOST_CHECK_EQUAL(rr.content, "ns.unit.test. hostmaster.unit.test. 1 2 3 4 5"); + BOOST_CHECK_EQUAL(rr.ttl, 300); +} + +BOOST_AUTO_TEST_CASE(test_method_lookup_empty) { + BOOST_TEST_MESSAGE("Testing lookup method with empty result"); + DNSResourceRecord rr; + be->lookup(QType(QType::SOA), DNSName("empty.unit.test.")); + // then try to get() + BOOST_CHECK(!be->get(rr)); // and this should be FALSE +} + +BOOST_AUTO_TEST_CASE(test_method_list) { + int record_count = 0; + DNSResourceRecord rr; + + BOOST_TEST_MESSAGE("Testing list method"); + be->list(DNSName("unit.test."), -1); + while(be->get(rr)) record_count++; + + BOOST_CHECK_EQUAL(record_count, 5); // number of records our test domain has +} + +BOOST_AUTO_TEST_CASE(test_method_doesDNSSEC) { + BOOST_TEST_MESSAGE("Testing doesDNSSEC method"); + BOOST_CHECK(be->doesDNSSEC()); // should be true +} + +BOOST_AUTO_TEST_CASE(test_method_setDomainMetadata) { + std::vector meta; + meta.push_back("VALUE"); + BOOST_TEST_MESSAGE("Testing setDomainMetadata method"); + BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."),"TEST", meta)); +} + +BOOST_AUTO_TEST_CASE(test_method_getDomainMetadata) { + std::vector meta; + BOOST_TEST_MESSAGE("Testing getDomainMetadata method"); + be->getDomainMetadata(DNSName("unit.test."),"TEST", meta); + BOOST_CHECK_EQUAL(meta.size(), 1); + // in case we got more than one value, which would be unexpected + // but not fatal + if (meta.size() > 0) + BOOST_CHECK_EQUAL(meta[0], "VALUE"); +} + +BOOST_AUTO_TEST_CASE(test_method_getAllDomainMetadata) { + std::map > meta; + BOOST_TEST_MESSAGE("Testing getAllDomainMetadata method"); + be->getAllDomainMetadata(DNSName("unit.test."), meta); + BOOST_CHECK_EQUAL(meta.size(), 1); + // in case we got more than one value, which would be unexpected + // but not fatal + if (meta.size() > 0) + BOOST_CHECK_EQUAL(meta["TEST"][0], "VALUE"); +} + +BOOST_AUTO_TEST_CASE(test_method_addDomainKey) { + BOOST_TEST_MESSAGE("Testing addDomainKey method"); + int64_t id; + be->addDomainKey(DNSName("unit.test."),k1,id); + BOOST_CHECK_EQUAL(id, 1); + be->addDomainKey(DNSName("unit.test."),k2,id); + BOOST_CHECK_EQUAL(id, 2); +} + +BOOST_AUTO_TEST_CASE(test_method_getDomainKeys) { + std::vector keys; + BOOST_TEST_MESSAGE("Testing getDomainKeys method"); + // we expect to get two keys + be->getDomainKeys(DNSName("unit.test."),keys); + BOOST_CHECK_EQUAL(keys.size(), 2); + // in case we got more than 2 keys, which would be unexpected + // but not fatal + if (keys.size() > 1) { + // check that we have two keys + for(DNSBackend::KeyData &kd : keys) { + BOOST_CHECK(kd.id > 0); + BOOST_CHECK(kd.flags == 256 || kd.flags == 257); + BOOST_CHECK(kd.active == true); + BOOST_CHECK(kd.content.size() > 500); + } + } +} + +BOOST_AUTO_TEST_CASE(test_method_deactivateDomainKey) { + BOOST_TEST_MESSAGE("Testing deactivateDomainKey method"); + BOOST_CHECK(be->deactivateDomainKey(DNSName("unit.test."),1)); +} + +BOOST_AUTO_TEST_CASE(test_method_activateDomainKey) { + BOOST_TEST_MESSAGE("Testing activateDomainKey method"); + BOOST_CHECK(be->activateDomainKey(DNSName("unit.test."),1)); +} + +BOOST_AUTO_TEST_CASE(test_method_removeDomainKey) { + BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."),2)); + BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."),1)); +} + +BOOST_AUTO_TEST_CASE(test_method_getBeforeAndAfterNamesAbsolute) { + DNSName unhashed, before, after; + BOOST_TEST_MESSAGE("Testing getBeforeAndAfterNamesAbsolute method"); + + be->getBeforeAndAfterNamesAbsolute(-1, DNSName("middle.unit.test."), unhashed, before, after); + BOOST_CHECK_EQUAL(unhashed.toString(), "middle."); + BOOST_CHECK_EQUAL(before.toString(), "begin."); + BOOST_CHECK_EQUAL(after.toString(), "stop."); +} + +BOOST_AUTO_TEST_CASE(test_method_setTSIGKey) { + std::string algorithm, content; + BOOST_TEST_MESSAGE("Testing setTSIGKey method"); + BOOST_CHECK_MESSAGE(be->setTSIGKey(DNSName("unit.test."),DNSName("hmac-md5."),"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="), "did not return true"); +} + +BOOST_AUTO_TEST_CASE(test_method_getTSIGKey) { + DNSName algorithm; + std::string content; + BOOST_TEST_MESSAGE("Testing getTSIGKey method"); + be->getTSIGKey(DNSName("unit.test."),&algorithm,&content); + BOOST_CHECK_EQUAL(algorithm.toString(), "hmac-md5."); + BOOST_CHECK_EQUAL(content, "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="); +} + +BOOST_AUTO_TEST_CASE(test_method_deleteTSIGKey) { + std::string algorithm, content; + BOOST_TEST_MESSAGE("Testing deleteTSIGKey method"); + BOOST_CHECK_MESSAGE(be->deleteTSIGKey(DNSName("unit.test.")), "did not return true"); +} + +BOOST_AUTO_TEST_CASE(test_method_getTSIGKeys) { + std::vector keys; + BOOST_TEST_MESSAGE("Testing getTSIGKeys method"); + be->getTSIGKeys(keys); + BOOST_CHECK(keys.size() > 0); + if (keys.size() > 0) { + BOOST_CHECK_EQUAL(keys[0].name.toString(), "test."); + BOOST_CHECK_EQUAL(keys[0].algorithm.toString(), "NULL."); + BOOST_CHECK_EQUAL(keys[0].key, "NULL"); + } +} + +BOOST_AUTO_TEST_CASE(test_method_setNotified) { + BOOST_TEST_MESSAGE("Testing setNotified method"); + be->setNotified(1, 2); + BOOST_CHECK(true); // we check this on next step +} + +BOOST_AUTO_TEST_CASE(test_method_getDomainInfo) { + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getDomainInfo method"); + be->getDomainInfo(DNSName("unit.test."), di); + BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); + BOOST_CHECK_EQUAL(di.backend, be); +} + +BOOST_AUTO_TEST_CASE(test_method_getAllDomains) { + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getAllDomains method"); + vector result; + + be->getAllDomains(&result, true); + + di = result[0]; + BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); + BOOST_CHECK_EQUAL(di.backend, be); +} + +BOOST_AUTO_TEST_CASE(test_method_superMasterBackend) { + DNSResourceRecord rr; + std::vector nsset; + DNSBackend *dbd; + BOOST_TEST_MESSAGE("Testing superMasterBackend method"); + + rr.qname = DNSName("example.com."); + rr.qtype = QType::NS; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns1.example.com."; + nsset.push_back(rr); + rr.qname = DNSName("example.com."); + rr.qtype = QType::NS; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns2.example.com."; + nsset.push_back(rr); + + BOOST_CHECK(be->superMasterBackend("10.0.0.1", DNSName("example.com."), nsset, NULL, NULL, &dbd)); + + // let's see what we got + BOOST_CHECK_EQUAL(dbd, be); +} + +BOOST_AUTO_TEST_CASE(test_method_createSlaveDomain) { + BOOST_TEST_MESSAGE("Testing createSlaveDomain method"); + BOOST_CHECK(be->createSlaveDomain("10.0.0.1", DNSName("pirate.unit.test."), "", "")); +} + +BOOST_AUTO_TEST_CASE(test_method_feedRecord) { + DNSResourceRecord rr; + BOOST_TEST_MESSAGE("Testing feedRecord method"); + be->startTransaction(DNSName("example.com."),2); + rr.qname = DNSName("example.com."); + rr.qtype = QType::SOA; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns1.example.com. hostmaster.example.com. 2013013441 7200 3600 1209600 300"; + BOOST_CHECK(be->feedRecord(rr, DNSName())); + rr.qname = DNSName("replace.example.com."); + rr.qtype = QType::A; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "127.0.0.1"; + BOOST_CHECK(be->feedRecord(rr, DNSName())); + be->commitTransaction(); +} + +BOOST_AUTO_TEST_CASE(test_method_replaceRRSet) { + be->startTransaction(DNSName("example.com."),2); + DNSResourceRecord rr; + std::vector rrset; + BOOST_TEST_MESSAGE("Testing replaceRRSet method"); + rr.qname = DNSName("replace.example.com."); + rr.qtype = QType::A; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "1.1.1.1"; + rrset.push_back(rr); + BOOST_CHECK(be->replaceRRSet(2, DNSName("replace.example.com."), QType(QType::A), rrset)); + be->commitTransaction(); +} + +BOOST_AUTO_TEST_CASE(test_method_feedEnts) { + BOOST_TEST_MESSAGE("Testing feedEnts method"); + be->startTransaction(DNSName("example.com."),2); + map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); + BOOST_CHECK(be->feedEnts(2, nonterm)); + be->commitTransaction(); +} + +BOOST_AUTO_TEST_CASE(test_method_feedEnts3) { + BOOST_TEST_MESSAGE("Testing feedEnts3 method"); + be->startTransaction(DNSName("example.com"),2); + NSEC3PARAMRecordContent ns3prc; + ns3prc.d_iterations=1; + ns3prc.d_salt="\u00aa\u00bb\u00cc\u00dd"; + map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); + BOOST_CHECK(be->feedEnts3(2, DNSName("example.com."), nonterm, ns3prc, 0)); + be->commitTransaction(); +} + +BOOST_AUTO_TEST_CASE(test_method_abortTransaction) { + BOOST_TEST_MESSAGE("Testing abortTransaction method"); + be->startTransaction(DNSName("example.com."),2); + BOOST_CHECK(be->abortTransaction()); +} + +BOOST_AUTO_TEST_CASE(test_method_directBackendCmd) { + BOOST_TEST_MESSAGE("Testing directBackendCmd method"); + BOOST_CHECK_EQUAL(be->directBackendCmd("PING 1234"), "PING 1234"); +} + +BOOST_AUTO_TEST_CASE(test_method_getUpdatedMasters) { + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getUpdatedMasters method"); + vector result; + + be->getUpdatedMasters(&result); + + BOOST_CHECK(result.size() > 0); + + di = result[0]; + BOOST_CHECK_EQUAL(di.zone.toString(), "master.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Master); + BOOST_CHECK_EQUAL(di.backend, be); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/modules/remotebackend/testrunner.sh b/modules/remotebackend/testrunner.sh new file mode 100755 index 0000000..86b85b2 --- /dev/null +++ b/modules/remotebackend/testrunner.sh @@ -0,0 +1,257 @@ +#!/usr/bin/env bash +new_api=0 +mode=$1 + +# keep the original arguments for new test harness api +orig="$*" + +# we could be ran with new API +while [ "$1" != "" ] +do + if [ "$1" == "--" ]; then + new_api=1 + mode=$2 + break + fi + shift +done + +webrick_pid="" +socat_pid="" +zeromq_pid="" +socat=$(which socat) + +function start_web() { + local service_logfile="${mode%\.test}_server.log" + + ./unittest_${1}.rb >> ${service_logfile} 2>&1 & + webrick_pid=$! + + local timeout=0 + while [ ${timeout} -lt 20 ]; do + local res=$(curl http://localhost:62434/ping 2>/dev/null) + if [ "x$res" == "xpong" ]; then + # server is up and running + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${webrick_pid} 2>/dev/null; then + # if something is wrong with curl (i.e. curl isn't installed, localhost is firewalled ...) + # the status check will fail -- cleanup required! + echo >&2 "WARNING: Timeout (${timeout}s) reached: \"${1}\" test service process is running but status check failed" + kill -KILL ${webrick_pid} 2>/dev/null + fi + + echo >&2 "ERROR: A timeout (${timeout}s) was reached while waiting for \"${1}\" test service to start!" + echo >&2 " See \"modules/remotebackend/${service_logfile}\" for more details." + exit 69 +} + +function stop_web() { + if [ -z "${webrick_pid}" ]; then + # should never happen - why was stop_web() called? + echo >&2 "ERROR: Unable to stop \"${1}\" test service: Did we ever start the service?" + exit 99 + fi + + if ! kill -0 ${webrick_pid} 2>/dev/null; then + # should never happen - did the test crashed the service? + echo >&2 "ERROR: Unable to stop \"${1}\" test service: service (${webrick_pid}) not running" + exit 69 + fi + + kill -TERM ${webrick_pid} + local timeout=0 + while [ ${timeout} -lt 5 ]; do + if ! kill -0 ${webrick_pid} 2>/dev/null; then + # service was stopped + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${webrick_pid} 2>/dev/null; then + echo >&2 "WARNING: Timeout (${timeout}s) reached - killing \"${1}\" test service ..." + kill -KILL ${webrick_pid} 2>/dev/null + return $? + fi +} + +function start_zeromq() { + if [ x"$REMOTEBACKEND_ZEROMQ" != "xyes" ]; then + echo "INFO: Skipping \"ZeroMQ\" test because PowerDNS was built without \"--enable-remotebackend-zeromq\"!" + exit 77 + fi + + local service_logfile="${mode%\.test}_server.log" + + ./unittest_zeromq.rb >> ${service_logfile} 2>&1 & + zeromq_pid=$! + + local timeout=0 + while [ ${timeout} -lt 5 ]; do + if [ -S "/tmp/remotebackend.0" ]; then + # service is up and running + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${zeromq_pid} 2>/dev/null; then + # not sure when this can happen but we should cleanup any process we started + echo >&2 "WARNING: Timeout (${timeout}s) reached: \"ZeroMQ\" test service process is running but status check failed" + kill -KILL ${zeromq_pid} 2>/dev/null + fi + + echo >&2 "ERROR: A timeout (${timeout}s) was reached while waiting for \"ZeroMQ\" test service to start!" + echo >&2 " See \"modules/remotebackend/${service_logfile}\" for more details." + exit 69 +} + +function stop_zeromq() { + if [ -z "${zeromq_pid}" ]; then + # should never happen - why was stop_zeromq() called? + echo >&2 "ERROR: Unable to stop \"ZeroMQ\" test service: Did we ever start the service?" + exit 99 + fi + + if ! kill -0 ${zeromq_pid} 2>/dev/null; then + # should never happen - did the test crashed the service? + echo >&2 "ERROR: Unable to stop \"ZeroMQ\" test service: service (${zeromq_pid}) not running" + exit 69 + fi + + kill -TERM ${zeromq_pid} + local timeout=0 + while [ ${timeout} -lt 5 ]; do + if ! kill -0 ${zeromq_pid} 2>/dev/null; then + # service was stopped + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${zeromq_pid} 2>/dev/null; then + echo >&2 "WARNING: Timeout (${timeout}s) reached - killing \"ZeroMQ\" test service ..." + kill -KILL ${zeromq_pid} 2>/dev/null + return $? + fi +} + +function start_unix() { + if [ -z "$socat" -o ! -x "$socat" ]; then + echo "INFO: Skipping \"UNIX socket\" test because \"socat\" executable wasn't found!" + exit 77 + fi + + $socat unix-listen:/tmp/remotebackend.sock exec:./unittest_pipe.rb & + socat_pid=$! + + local timeout=0 + while [ ${timeout} -lt 5 ]; do + if [ -S "/tmp/remotebackend.sock" ]; then + # service is up and running + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${socat_pid} 2>/dev/null; then + # not sure when this can happen but we should cleanup any process we started + echo >&2 "WARNING: Timeout (${timeout}s) reached: \"UNIX socket\" test service process is running but status check failed" + kill -KILL ${socat_pid} 2>/dev/null + fi + + echo >&2 "ERROR: A timeout (${timeout}s) was reached while waiting for \"UNIX socket\" test service to start!" + exit 69 +} + +function stop_unix() { + if [ -z "${socat_pid}" ]; then + # should never happen - why was stop_unix() called? + echo >&2 "ERROR: Unable to stop \"UNIX socket\" test service: Did we ever start the service?" + exit 99 + fi + + if ! kill -0 ${socat_pid} 2>/dev/null; then + # might very well happen, since socat will stop after getting EOF + return 0 + fi + + kill -TERM ${socat_pid} + local timeout=0 + while [ ${timeout} -lt 5 ]; do + if ! kill -0 ${socat_pid} 2>/dev/null; then + # service was stopped + return 0 + fi + + sleep 1 + let timeout=timeout+1 + done + + if kill -0 ${socat_pid} 2>/dev/null; then + echo >&2 "WARNING: Timeout (${timeout}s) reached - killing \"UNIX socket\" test service ..." + kill -KILL ${socat_pid} 2>/dev/null + return $? + fi +} + +function run_test() { + if [ $new_api -eq 0 ]; then + ./$mode + else + $orig + fi +} + +mode=`basename "$mode"` + +case "$mode" in + remotebackend_pipe.test) + run_test + ;; + remotebackend_unix.test) + start_unix + run_test + stop_unix + ;; + remotebackend_http.test) + start_web "http" + run_test + stop_web "http" + ;; + remotebackend_post.test) + start_web "post" + run_test + stop_web "post" + ;; + remotebackend_json.test) + start_web "json" + run_test + stop_web "json" + ;; + remotebackend_zeromq.test) + start_zeromq + run_test + stop_zeromq + ;; + *) + echo "Usage: $0 remotebackend_(pipe|unix|http|post|json|zeromq).test" + exit 1 + ;; +esac + +exit $? diff --git a/modules/remotebackend/unittest.rb b/modules/remotebackend/unittest.rb new file mode 100644 index 0000000..7fb40ec --- /dev/null +++ b/modules/remotebackend/unittest.rb @@ -0,0 +1,271 @@ +require 'rubygems' +require 'bundler/setup' +require 'json' + +# define a simple $domain + +$ttl = 300 +$notified_serial = 1 + +$domain = { + "unit.test." => { + "SOA" => ["ns.unit.test. hostmaster.unit.test. 1 2 3 4 5"], + "NS" => ["ns1.unit.test.", "ns2.unit.test."], + }, + "ns1.unit.test." => { + "A" => ["10.0.0.1"] + }, + "ns2.unit.test." => { + "A" => ["10.0.0.2"] + }, + "empty.unit.test." => {} +} + +$meta = {} + +$keys = {} + +$tsigkeys = { "test." => {:name => "test.", :algorithm => "NULL.", :content => "NULL"} } + +$masters = { :name => "ns1.unit.test.", :ip => "10.0.0.1" } + +class Handler + def initialize + end + + def rr(qname, qtype, content, ttl, auth = 1, domain_id = -1) + {:qname => qname, :qtype => qtype, :content => content, :ttl => ttl.to_i, :auth => auth.to_i, :domain_id => domain_id.to_i} + end + + def do_initialize(*args) + return true, "Test bench initialized" + end + + def do_lookup(args) + ret = [] + if $domain.has_key?(args["qname"]) + if $domain[args["qname"]].has_key?(args["qtype"]) + $domain[args["qname"]][args["qtype"]].each do |rd| + ret << rr(args["qname"], args["qtype"], rd, $ttl) + end + elsif args["qtype"] == 'ANY' + $domain[args["qname"]].each do |qt,qr| + qr.each do |rd| + ret << rr(args["qname"], qt, rd, $ttl) + end + end + end + end + [false] unless ret.size>0 and args["qname"] != "empty.unit.test" + [ret] + end + + def do_list(args) + ret = [] + if args["zonename"] == "unit.test." + $domain.each do |qname,rdata| + rdata.each do |rtype,rc| + rc.each do |rd| + ret << rr(qname,rtype,rd,$ttl) + end + end + end + end + [false] unless ret.size>0 + [ret] + end + + def do_getalldomainmetadata(args) + return [ $meta[args["name"]] ] if $meta.has_key?(args["name"]) + return [false] + end + + def do_getdomainmetadata(args) + return [ $meta[args["name"]][args["kind"]] ] if $meta.has_key?(args["name"]) and $meta[args["name"]].has_key?(args["kind"]) + return [false] + end + + def do_setdomainmetadata(args) + $meta[args["name"].to_s] = {} unless $meta.has_key? args["name"] + $meta[args["name"].to_s][args["kind"].to_s] = args["value"].to_a + [true] + end + + def do_adddomainkey(args) + $keys[args["name"]] = [] unless $keys.has_key? args["name"] + id=$keys[args["name"]].size + 1 + args["key"]["id"] = id + $keys[args["name"]] << args["key"] + [id] + end + + def do_getdomainkeys(args) + if $keys.has_key? args["name"] + return [ $keys[args["name"]] ] + end + [false] + end + + def do_activatedomainkey(args) + args["id"] = args["id"].to_i + if $keys.has_key? args["name"] + if $keys[args["name"]][args["id"]-1] + $keys[args["name"]][args["id"]-1]["active"] = true + return [true] + end + end + [false] + end + + def do_deactivatedomainkey(args) + args["id"] = args["id"].to_i + if $keys.has_key? args["name"] + if $keys[args["name"]][args["id"]-1] + $keys[args["name"]][args["id"]-1]["active"] = false + return [true] + end + end + [false] + end + + def do_removedomainkey(args) + args["id"] = args["id"].to_i + if $keys.has_key? args["name"] + if $keys[args["name"]][args["id"]-1] + $keys[args["name"]].delete_at args["id"]-1 + return [true] + end + end + [false] + end + + def do_getbeforeandafternamesabsolute(args) + return [ { :unhashed => "middle.", :before => "begin.", :after => "stop." } ] if args["qname"] == 'middle.unit.test.' + [false] + end + + def do_gettsigkey(args) + if $tsigkeys.has_key? args["name"] + return [{:algorithm => $tsigkeys[args["name"]][:algorithm], :content => $tsigkeys[args["name"]][:content] }] + end + [false] + end + + def do_setnotified(args) + if args["id"].to_i == 1 + $notified_serial = args["serial"].to_i + return [true] + end + [false] + end + + def do_getdomaininfo(args) + if args["name"] == "unit.test." + return [{ + :id => 1, + :zone => "unit.test.", + :masters => ["10.0.0.1"], + :notified_serial => $notified_serial, + :serial => $notified_serial, + :last_check => Time.now.to_i, + :kind => 'native' + }] + end + if args["name"] == "master.test." + return [{ + :id => 2, + :zone => "master.test.", + :masters => ["10.0.0.1"], + :notified_serial => $notified_serial, + :serial => $notified_serial, + :last_check => Time.now.to_i, + :kind => 'master' + }] + end + [false] + end + + def do_ismaster(args) + $masters[:name] == args["name"] && $masters[:ip] == args["ip"] + end + + def do_supermasterbackend(args) + $domain[args["domain"]] = { + "NS" => args["nsset"] + } + [true] + end + + def do_createslavedomain(args) + $domain[args["domain"]] = { + } + [true] + end + + def do_feedrecord(args) + args.delete "trxid" + rr = args["rr"] + name = rr["qname"] + qtype = rr["qtype"] + $domain[name] = {} unless $domain.has_key? name + $domain[name][qtype] = [] unless $domain[name].has_key? qtype + $domain[name][qtype] << rr["content"] + [true] + end + + def do_replacerrset(args) + $domain[args["qname"]].delete args["qtype"] if $domain.has_key?(args["qname"]) and $domain[args["qname"]].has_key?(args["qtype"]) + args["rrset"] = args["rrset"].values if args["rrset"].is_a?(Hash) + args["rrset"].each do |rr| + self.do_feedrecord({"trxid" => args["trxid"], "rr" => rr}) + end + [true] + end + + def do_feedents(args) + [true] + end + + def do_feedents3(args) + [true] + end + + def do_settsigkey(args) + $tsigkeys[args["name"]] = { :name => args["name"], :algorithm => args["algorithm"], :content => args["content"] } + [true] + end + + def do_deletetsigkey(args) + $tsigkeys.delete args["name"] if $tsigkeys.has_key? args["name"] + [true] + end + + def do_gettsigkeys(*args) + return [$tsigkeys.values] + end + + def do_starttransaction(args) + [true] + end + + def do_committransaction(args) + [true] + end + + def do_aborttransaction(args) + [true] + end + + def do_directbackendcmd(args) + [args["query"]] + end + + def do_getalldomains(args) + [do_getdomaininfo({'name'=>'unit.test.'})] + end + + def do_getupdatedmasters() + [do_getdomaininfo({'name'=>'master.test.'})] + end +end + diff --git a/modules/remotebackend/unittest_http.rb b/modules/remotebackend/unittest_http.rb new file mode 100755 index 0000000..21beaa3 --- /dev/null +++ b/modules/remotebackend/unittest_http.rb @@ -0,0 +1,200 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'bundler/setup' +require 'json' +require 'thread' +require 'webrick' +require './unittest' + +class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet + def initialize(server, dnsbackend) + @dnsbackend = dnsbackend + @semaphore = Mutex.new + @f = File.open("/tmp/remotebackend.txt.#{$$}","ab") + @f.set_encoding 'UTF-8' + end + + def parse_arrays(params) + newparams = {} + params.each do |key,val| + if key=~/^(.*)\[(.*)\]\[(.*)\]/ + newparams[$1] = {} unless newparams.has_key? $1 + newparams[$1][$2] = {} unless newparams[$1].has_key? $2 + newparams[$1][$2][$3] = val + params.delete key + elsif key=~/^(.*)\[(.*)\]/ + if $2 == "" + newparams[$1] = [] unless newparams.has_key? $1 + newparams[$1] << val + else + newparams[$1] = {} unless newparams.has_key? $1 + newparams[$1][$2] = val + end + params.delete key + end + end + params.merge newparams + end + + def parse_url(url) + url = url.split('/') + method = url.shift.downcase + + # do some determining based on method names + args = case method + when "lookup" + { + "qname" => url.shift, + "qtype" => url.shift + } + when "list" + { + "id" => url.shift, + "zonename" => url.shift + } + when "getbeforeandafternamesabsolute", "getbeforeandafternames" + { + "id" => url.shift.to_i, + "qname" => url.shift + } + when "getdomainmetadata", "setdomainmetadata", "getdomainkeys" + { + "name" => url.shift, + "kind" => url.shift + } + when "removedomainkey", "activatedomainkey", "deactivatedomainkey" + { + "id" => url.shift.to_i, + "name" => url.shift + } + when "adddomainkey", "gettsigkey", "getdomaininfo", "settsigkey", "deletetsigkey", "getalldomainmetadata" + { + "name" => url.shift + } + when "setnotified", "feedents" + { + "id" => url.shift.to_i + } + when "ismaster" + { + "name" => url.shift, + "ip" => url.shift + } + when "supermasterbackend", "createslavedomain" + { + "ip" => url.shift, + "domain" => url.shift + } + when "feedents3" + { + "id" => url.shift.to_i, + "domain" => url.shift + } + when "starttransaction" + { + "id" => url.shift.to_i, + "domain" => url.shift, + "trxid" => url.shift.to_i + } + when "committransaction", "aborttransaction" + { + "trxid" => url.shift.to_i + } + when "replacerrset" + { + "id" => url.shift.to_i, + "qname" => url.shift, + "qtype" => url.shift + } + else + {} + end + + [method, args] + end + + def do_GET(req,res) + req.continue + + tmp = req.path[/dns\/(.*)/,1] + return 400, "Bad request" if (tmp.nil?) + + method, args = parse_url(tmp) + + method = "do_#{method}" + + # get more arguments + req.each do |k,v| + attr = k[/X-RemoteBackend-(.*)/,1] + if attr + args[attr] = v + end + end + + args = args.merge req.query + + if method == "do_adddomainkey" + args["key"] = { + "flags" => args.delete("flags").to_i, + "active" => args.delete("active").to_i, + "content" => args.delete("content") + } + end + + args = parse_arrays args + begin + @f.puts "#{Time.now.to_f} [http]: #{({:method=>method,:parameters=>args}).to_json}" + rescue Encoding::UndefinedConversionError + # this fails with encoding error for feedEnts3 + end + + @semaphore.synchronize do + if @dnsbackend.respond_to?(method.to_sym) + result, log = @dnsbackend.send(method.to_sym, args) + body = {:result => result, :log => log} + res.status = 200 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = body.to_json + else + res.status = 404 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = ({:result => false, :log => ["Method not found"]}).to_json + end + + @f.puts "#{Time.now.to_f} [http]: #{res.body}" + end + end + + def do_DELETE(req,res) + do_GET(req,res) + end + + def do_POST(req,res) + do_GET(req,res) + end + + def do_PATCH(req,res) + do_GET(req,res) + end + + def do_PUT(req,res) + do_GET(req,res) + end +end + +server = WEBrick::HTTPServer.new( + :Port=>62434, + :BindAddress=>"localhost", +# Logger: WEBrick::Log.new("remotebackend-server.log"), + :AccessLog=>[ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] +) + +be = Handler.new +server.mount "/dns", DNSBackendHandler, be +server.mount_proc("/ping"){ |req,resp| resp.body = "pong" } + +trap('INT') { server.stop } +trap('TERM') { server.stop } + +server.start diff --git a/modules/remotebackend/unittest_json.rb b/modules/remotebackend/unittest_json.rb new file mode 100755 index 0000000..2c713b7 --- /dev/null +++ b/modules/remotebackend/unittest_json.rb @@ -0,0 +1,61 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'bundler/setup' +require 'json' +require 'thread' +require 'webrick' +require './unittest' + +class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet + def initialize(server, dnsbackend) + @dnsbackend = dnsbackend + @semaphore = Mutex.new + @f = File.open("/tmp/remotebackend.txt.#{$$}","a") + @f.sync + end + + def do_POST(req,res) + req.continue + + return 400, "Bad request" unless req.path == "/dns/endpoint.json" + + tmp = JSON::parse(req.body) + method = tmp["method"].downcase + method = "do_#{method}" + args = tmp["parameters"] + + @f.puts "#{Time.now.to_f} [http/json]: #{({:method=>method,:parameters=>args}).to_json}" + + @semaphore.synchronize do + if @dnsbackend.respond_to?(method.to_sym) + result, log = @dnsbackend.send(method.to_sym, args) + body = {:result => result, :log => log} + res.status = 200 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = body.to_json + else + res.status = 404 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = ({:result => false, :log => ["Method not found"]}).to_json + end + @f.puts "#{Time.now.to_f} [http/json]: #{res.body}" + end + end +end + +server = WEBrick::HTTPServer.new( + :Port=>62434, + :BindAddress=>"localhost", +# Logger: WEBrick::Log.new("remotebackend-server.log"), + :AccessLog=>[ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] +) + +be = Handler.new +server.mount "/dns", DNSBackendHandler, be +server.mount_proc("/ping"){ |req,resp| resp.body = "pong" } + +trap('INT') { server.stop } +trap('TERM') { server.stop } + +server.start diff --git a/modules/remotebackend/unittest_pipe.rb b/modules/remotebackend/unittest_pipe.rb new file mode 100755 index 0000000..4c6a155 --- /dev/null +++ b/modules/remotebackend/unittest_pipe.rb @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'bundler/setup' +require 'json' +require './unittest' + +h = Handler.new() +f = File.open "/tmp/remotebackend.txt.#{$$}","a" +f.sync + +STDOUT.sync = true +begin + STDIN.each_line do |line| + f.puts "#{Time.now.to_f}: [pipe] #{line}" + # expect json + input = {} + line = line.strip + next if line.empty? + begin + input = JSON.parse(line) + method = "do_#{input["method"].downcase}" + args = input["parameters"] || [] + + if h.respond_to?(method.to_sym) == false + res = false + elsif args.size > 0 + res, log = h.send(method,args) + else + res, log = h.send(method) + end + puts ({:result => res, :log => log}).to_json + f.puts "#{Time.now.to_f} [pipe]: #{({:result => res, :log => log}).to_json}" + rescue JSON::ParserError + puts ({:result => false, :log => "Cannot parse input #{line}"}).to_json + f.puts "#{Time.now.to_f} [pipe]: #{({:result => false, :log => "Cannot parse input #{line}"}).to_json}" + next + end + end +rescue SystemExit, Interrupt +end diff --git a/modules/remotebackend/unittest_post.rb b/modules/remotebackend/unittest_post.rb new file mode 100755 index 0000000..db82974 --- /dev/null +++ b/modules/remotebackend/unittest_post.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'bundler/setup' +require 'json' +require 'thread' +require 'webrick' +require './unittest' + +class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet + def initialize(server, dnsbackend) + @dnsbackend = dnsbackend + @semaphore = Mutex.new + @f = File.open("/tmp/remotebackend.txt.#{$$}","a") + @f.sync + end + + def do_POST(req,res) + req.continue + + tmp = req.path[/dns\/(.*)/,1] + return 400, "Bad request" if (tmp.nil?) + + url = tmp.split('/') + method = url.shift.downcase + method = "do_#{method}" + args = JSON::parse(req.query["parameters"]) + + @f.puts "#{Time.now.to_f} [http/post]: #{({:method=>method,:parameters=>args}).to_json}" + + @semaphore.synchronize do + if @dnsbackend.respond_to?(method.to_sym) + result, log = @dnsbackend.send(method.to_sym, args) + body = {:result => result, :log => log} + res.status = 200 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = body.to_json + else + res.status = 404 + res["Content-Type"] = "application/javascript; charset=utf-8" + res.body = ({:result => false, :log => ["Method not found"]}).to_json + end + @f.puts "#{Time.now.to_f} [http/post]: #{res.body}" + end + end +end + +server = WEBrick::HTTPServer.new( + :Port=>62434, + :BindAddress=>"localhost", +# Logger: WEBrick::Log.new("remotebackend-server.log"), + :AccessLog=>[ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] +) + +be = Handler.new +server.mount "/dns", DNSBackendHandler, be +server.mount_proc("/ping"){ |req,resp| resp.body = "pong" } + +trap('INT') { server.stop } +trap('TERM') { server.stop } + +server.start diff --git a/modules/remotebackend/unittest_zeromq.rb b/modules/remotebackend/unittest_zeromq.rb new file mode 100755 index 0000000..7f1b82a --- /dev/null +++ b/modules/remotebackend/unittest_zeromq.rb @@ -0,0 +1,57 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'bundler/setup' +require 'json' +require 'zero_mq' +require './unittest' + +h = Handler.new() +f = File.open "/tmp/remotebackend.txt.#{$$}","a" +f.sync = true + +runcond=true + +trap('INT') { runcond = false } +trap('TERM') { runcond = false } + +begin + context = ZeroMQ::Context.new + socket = context.socket ZMQ::REP + socket.bind("ipc:///tmp/remotebackend.0") + + print "[#{Time.now.to_s}] ZeroMQ unit test responder running\n" + + while(runcond) do + line = "" + rc = socket.recv_string line + # expect json + input = {} + line = line.strip + + f.puts "#{Time.now.to_f}: [zmq] #{line}" + next if line.empty? + begin + input = JSON.parse(line) + method = "do_#{input["method"].downcase}" + args = input["parameters"] || [] + + if h.respond_to?(method.to_sym) == false + res = false + elsif args.size > 0 + res, log = h.send(method,args) + else + res, log = h.send(method) + end + socket.send_string ({:result => res, :log => log}).to_json + "\n" , 0 + f.puts "#{Time.now.to_f} [zmq]: #{({:result => res, :log => log}).to_json}" + rescue JSON::ParserError + socket.send_string ({:result => false, :log => "Cannot parse input #{line}"}).to_json + "\n"; + f.puts "#{Time.now.to_f} [zmq]: #{({:result => false, :log => "Cannot parse input #{line}"}).to_json}" + next + end + end +rescue SystemExit, Interrupt, Errno::EINTR +end + +print "[#{Time.now.to_s}] ZeroMQ unit test responder ended\n" diff --git a/modules/remotebackend/unixconnector.cc b/modules/remotebackend/unixconnector.cc new file mode 100644 index 0000000..766e8a3 --- /dev/null +++ b/modules/remotebackend/unixconnector.cc @@ -0,0 +1,186 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include "remotebackend.hh" +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +UnixsocketConnector::UnixsocketConnector(std::map optionsMap) { + if (optionsMap.count("path") == 0) { + g_log<timeout = 2000; + if (optionsMap.find("timeout") != optionsMap.end()) { + this->timeout = std::stoi(optionsMap.find("timeout")->second); + } + this->path = optionsMap.find("path")->second; + this->options = optionsMap; + this->connected = false; + this->fd = -1; +} + +UnixsocketConnector::~UnixsocketConnector() { + if (this->connected) { + try { + g_log<write(data); + if (rv == -1) + return -1; + return rv; +} + +int UnixsocketConnector::recv_message(Json& output) { + int rv; + std::string s_output,err; + + struct timeval t0,t; + + gettimeofday(&t0, NULL); + memcpy(&t,&t0,sizeof(t0)); + s_output = ""; + + while((t.tv_sec - t0.tv_sec)*1000 + (t.tv_usec - t0.tv_usec)/1000 < this->timeout) { + int avail = waitForData(this->fd, 0, this->timeout * 500); // use half the timeout as poll timeout + if (avail < 0) // poll error + return -1; + if (avail == 0) { // timeout + gettimeofday(&t, NULL); + continue; + } + + rv = this->read(s_output); + if (rv == -1) + return -1; + + if (rv>0) { + // see if it can be parsed + output = Json::parse(s_output, err); + if (output != nullptr) return s_output.size(); + } + gettimeofday(&t, NULL); + } + + close(fd); + connected = false; // we need to reconnect + return -1; +} + +ssize_t UnixsocketConnector::read(std::string &data) { + ssize_t nread; + char buf[1500] = {0}; + + reconnect(); + if (!connected) return -1; + nread = ::read(this->fd, buf, sizeof buf); + + // just try again later... + if (nread==-1 && errno == EAGAIN) return 0; + + if (nread==-1 || nread==0) { + connected = false; + close(fd); + return -1; + } + + data.append(buf, nread); + return nread; +} + +ssize_t UnixsocketConnector::write(const std::string &data) { + size_t pos = 0; + + reconnect(); + if (!connected) return -1; + + while(pos < data.size()) { + ssize_t written = ::write(fd, &data.at(pos), data.size() - pos); + if (written < 1) { + connected = false; + close(fd); + return -1; + } else { + pos = pos + static_cast(written); + } + } + return pos; +} + +void UnixsocketConnector::reconnect() { + struct sockaddr_un sock; + int rv; + + if (connected) return; // no point reconnecting if connected... + connected = true; + + g_log<(&sock), sizeof sock); + + if (rv != 0 && errno != EISCONN && errno != 0) { + g_log<send(msg); + msg = nullptr; + if (this->recv(msg) == false) { + g_log<connected = false; + } +} diff --git a/modules/remotebackend/zmqconnector.cc b/modules/remotebackend/zmqconnector.cc new file mode 100644 index 0000000..1c5ae09 --- /dev/null +++ b/modules/remotebackend/zmqconnector.cc @@ -0,0 +1,146 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "remotebackend.hh" +#ifdef REMOTEBACKEND_ZEROMQ + +ZeroMQConnector::ZeroMQConnector(std::map options): d_ctx(std::unique_ptr(zmq_init(2), zmq_close)), d_sock(std::unique_ptr(zmq_socket(d_ctx.get(), ZMQ_REQ), zmq_close)) { + int opt=0; + + // lookup timeout, target and stuff + if (options.count("endpoint") == 0) { + g_log<d_endpoint = options.find("endpoint")->second; + this->d_options = options; + this->d_timeout=2000; + + if (options.find("timeout") != options.end()) { + this->d_timeout = std::stoi(options.find("timeout")->second); + } + + zmq_setsockopt(d_sock.get(), ZMQ_LINGER, &opt, sizeof(opt)); + + if(zmq_connect(this->d_sock.get(), this->d_endpoint.c_str()) < 0) + { + g_log<send(msg); + msg = nullptr; + if (this->recv(msg)==false) { + g_log<(zmq_msg_data(&message)), line.size()); + ((char *)zmq_msg_data(&message))[line.size()] = '\0'; + + try { + zmq_pollitem_t item; + item.socket = d_sock.get(); + item.events = ZMQ_POLLOUT; + // poll until it's sent or timeout is spent. try to leave + // leave few cycles for read. just in case. + for(d_timespent = 0; d_timespent < d_timeout-5; d_timespent++) { + if (zmq_poll(&item, 1, 1)>0) { + if(zmq_msg_send(&message, this->d_sock.get(), 0) == -1) { + // message was not sent + g_log<d_endpoint << ": " << zmq_strerror(errno)<d_endpoint << ": " << ex.what()<0) { + // we have an event + if ((item.revents & ZMQ_POLLIN) == ZMQ_POLLIN) { + string data; + size_t msg_size; + zmq_msg_init(&message); + // read something + if(zmq_msg_recv(&message, this->d_sock.get(), ZMQ_NOBLOCK)>0) { + string err; + msg_size = zmq_msg_size(&message); + data.assign(reinterpret_cast(zmq_msg_data(&message)), msg_size); + zmq_msg_close(&message); + output = Json::parse(data, err); + if (output != nullptr) + rv = msg_size; + else + g_log<d_endpoint << ": " << err << endl; + break; + } else if (errno == EAGAIN) { continue; // try again } + } else { + break; + } + } + } + } + } catch (std::exception &ex) { + g_log<d_endpoint << ": " << ex.what()<&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = modules/tinydnsbackend +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libtinydnsbackend_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libtinydnsbackend_la_OBJECTS = cdb.lo tinydnsbackend.lo +libtinydnsbackend_la_OBJECTS = $(am_libtinydnsbackend_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libtinydnsbackend_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libtinydnsbackend_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtinydnsbackend_la_SOURCES) +DIST_SOURCES = $(libtinydnsbackend_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ $(CDB_CFLAGS) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pkglib_LTLIBRARIES = libtinydnsbackend.la +EXTRA_DIST = OBJECTFILES OBJECTLIBS +libtinydnsbackend_la_SOURCES = \ + cdb.cc cdb.hh \ + tinydnsbackend.cc tinydnsbackend.hh + +libtinydnsbackend_la_LDFLAGS = -module -avoid-version +libtinydnsbackend_la_LIBADD = $(CDB_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign modules/tinydnsbackend/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign modules/tinydnsbackend/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libtinydnsbackend.la: $(libtinydnsbackend_la_OBJECTS) $(libtinydnsbackend_la_DEPENDENCIES) $(EXTRA_libtinydnsbackend_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libtinydnsbackend_la_LINK) -rpath $(pkglibdir) $(libtinydnsbackend_la_OBJECTS) $(libtinydnsbackend_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinydnsbackend.Plo@am__quote@ + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am 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-man install-pdf install-pdf-am \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# 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. +.NOEXPORT: diff --git a/modules/tinydnsbackend/OBJECTFILES b/modules/tinydnsbackend/OBJECTFILES new file mode 100644 index 0000000..41c0623 --- /dev/null +++ b/modules/tinydnsbackend/OBJECTFILES @@ -0,0 +1 @@ +tinydnsbackend.lo cdb.lo \ No newline at end of file diff --git a/modules/tinydnsbackend/OBJECTLIBS b/modules/tinydnsbackend/OBJECTLIBS new file mode 100644 index 0000000..ec1a88d --- /dev/null +++ b/modules/tinydnsbackend/OBJECTLIBS @@ -0,0 +1 @@ +$(CDB_LIBS) diff --git a/modules/tinydnsbackend/cdb.cc b/modules/tinydnsbackend/cdb.cc new file mode 100644 index 0000000..d836d34 --- /dev/null +++ b/modules/tinydnsbackend/cdb.cc @@ -0,0 +1,154 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "cdb.hh" +#include +#include "pdns/misc.hh" +#include "pdns/iputils.hh" +#include + + +CDB::CDB(const string &cdbfile) +{ + d_fd = open(cdbfile.c_str(), O_RDONLY); + if (d_fd < 0) + { + g_log< 0); +} + +bool CDB::readNext(pair &value) { + while (moveToNext()) { + unsigned int pos; + unsigned int len; + + pos = cdb_keypos(&d_cdb); + len = cdb_keylen(&d_cdb); + + char *key = (char *)malloc(len); + cdb_read(&d_cdb, key, len, pos); + + if (d_searchType == SearchSuffix) { + char *p = strstr(key, d_key); + if (p == NULL) { + free(key); + continue; + } + } + string skey(key, len); + free(key); + + pos = cdb_datapos(&d_cdb); + len = cdb_datalen(&d_cdb); + char *val = (char *)malloc(len); + cdb_read(&d_cdb, val, len, pos); + string sval(val, len); + free(val); + + value = make_pair(skey, sval); + return true; + } + // We're done searching, so we can clean up d_key + if (d_searchType != SearchAll) { + free(d_key); + } + return false; +} + +vector CDB::findall(string &key) +{ + vector ret; + struct cdb_find cdbf; + + cdb_findinit(&cdbf, &d_cdb, key.c_str(), key.size()); + int x=0; + while(cdb_findnext(&cdbf) > 0) { + x++; + unsigned int vpos = cdb_datapos(&d_cdb); + unsigned int vlen = cdb_datalen(&d_cdb); + char *val = (char *)malloc(vlen); + cdb_read(&d_cdb, val, vlen, vpos); + string sval(val, vlen); + ret.push_back(sval); + free(val); + } + return ret; +} diff --git a/modules/tinydnsbackend/cdb.hh b/modules/tinydnsbackend/cdb.hh new file mode 100644 index 0000000..7d5115c --- /dev/null +++ b/modules/tinydnsbackend/cdb.hh @@ -0,0 +1,55 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef CDB_HH +#define CDB_HH + +#include "pdns/logger.hh" +#include +#include +#include +#include + +// This class is responsible for the reading of a CDB file. +// The constructor opens the CDB file, the destructor closes it, so make sure you call that. +class CDB +{ +public: + CDB(const string &cdbfile); + ~CDB(); + + int searchKey(const string &key); + bool searchSuffix(const string &key); + void searchAll(); + bool readNext(pair &value); + vector findall(string &key); + +private: + int d_fd; + bool moveToNext(); + struct cdb d_cdb; + struct cdb_find d_cdbf; + char *d_key; + unsigned d_seqPtr; + enum SearchType { SearchSuffix, SearchKey, SearchAll } d_searchType; +}; + +#endif // CDB_HH diff --git a/modules/tinydnsbackend/tinydnsbackend.cc b/modules/tinydnsbackend/tinydnsbackend.cc new file mode 100644 index 0000000..228ac34 --- /dev/null +++ b/modules/tinydnsbackend/tinydnsbackend.cc @@ -0,0 +1,355 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "tinydnsbackend.hh" +#include "pdns/lock.hh" +#include +#include "pdns/misc.hh" +#include "pdns/iputils.hh" +#include "pdns/dnspacket.hh" +#include "pdns/dnsrecords.hh" +#include + + +static string backendname="[TinyDNSBackend] "; +uint32_t TinyDNSBackend::s_lastId; +pthread_mutex_t TinyDNSBackend::s_domainInfoLock=PTHREAD_MUTEX_INITIALIZER; +TinyDNSBackend::TDI_suffix_t TinyDNSBackend::s_domainInfo; + +vector TinyDNSBackend::getLocations() +{ + vector ret; + + if (! d_dnspacket) { + return ret; + } + + //TODO: We do not have IPv6 support. + Netmask remote = d_dnspacket->getRealRemote(); + if (remote.getBits() != 32) { + return ret; + } + + unsigned long addr = remote.getNetwork().sin4.sin_addr.s_addr; + + char key[6]; + key[0] = '\000'; + key[1] = '\045'; + key[2] = (addr )&0xff; + key[3] = (addr >> 8)&0xff; + key[4] = (addr >> 16)&0xff; + key[5] = (addr >> 24)&0xff; + + for (int i=4;i>=0;i--) { + string searchkey(key, i+2); + CDB *reader = new CDB(getArg("dbfile")); + ret = reader->findall(searchkey); + delete reader; + + //Biggest item wins, so when we find something, we can jump out. + if (ret.size() > 0) { + break; + } + } + + return ret; +} + +TinyDNSBackend::TinyDNSBackend(const string &suffix) +{ + setArgPrefix("tinydns"+suffix); + d_suffix = suffix; + d_locations = mustDo("locations"); + d_ignorebogus = mustDo("ignore-bogus-records"); + d_taiepoch = 4611686018427387904ULL + getArgAsNum("tai-adjust"); + d_dnspacket = NULL; + d_cdbReader = NULL; + d_isAxfr = false; + d_isWildcardQuery = false; +} + +void TinyDNSBackend::getUpdatedMasters(vector* retDomains) { + Lock l(&s_domainInfoLock); //TODO: We could actually lock less if we do it per suffix. + + if (! s_domainInfo.count(d_suffix)) { + TDI_t tmp; + s_domainInfo.insert( make_pair(d_suffix,tmp) ); + } + + TDI_t *domains = &s_domainInfo[d_suffix]; + + vector allDomains; + getAllDomains(&allDomains); + if (domains->size() == 0 && !mustDo("notify-on-startup")) { + for (vector::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) { + di->notified_serial = 0; + } + } + + for(vector::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) { + TDIByZone_t& zone_index = domains->get(); + TDIByZone_t::iterator itByZone = zone_index.find(di->zone); + if (itByZone == zone_index.end()) { + s_lastId++; + + TinyDomainInfo tmp; + tmp.zone = di->zone; + tmp.id = s_lastId; + tmp.notified_serial = di->serial; + domains->insert(tmp); + + di->id = s_lastId; + if (di->notified_serial > 0) { + retDomains->push_back(*di); + } + } else { + if (itByZone->notified_serial < di->serial) { + di->id = itByZone->id; + retDomains->push_back(*di); + } + } + } +} + +void TinyDNSBackend::setNotified(uint32_t id, uint32_t serial) { + Lock l(&s_domainInfoLock); + if (!s_domainInfo.count(d_suffix)) { + throw new PDNSException("Can't get list of domains to set the serial."); + } + TDI_t *domains = &s_domainInfo[d_suffix]; + TDIById_t& domain_index = domains->get(); + TDIById_t::iterator itById = domain_index.find(id); + if (itById == domain_index.end()) { + g_log<zone<<" to "< *domains, bool include_disabled) { + d_isAxfr=true; + d_dnspacket = NULL; + + d_cdbReader=std::unique_ptr(new CDB(getArg("dbfile"))); + d_cdbReader->searchAll(); + DNSResourceRecord rr; + + while (get(rr)) { + if (rr.qtype.getCode() == QType::SOA) { + SOAData sd; + fillSOAData(rr.content, sd); + + DomainInfo di; + di.id = -1; //TODO: Check if this is ok. + di.backend=this; + di.zone = rr.qname; + di.serial = sd.serial; + di.notified_serial = sd.serial; + di.kind = DomainInfo::Master; + di.last_check = time(0); + domains->push_back(di); + } + } +} + +bool TinyDNSBackend::list(const DNSName &target, int domain_id, bool include_disabled) { + d_isAxfr=true; + string key = target.toDNSStringLC(); + d_cdbReader=std::unique_ptr(new CDB(getArg("dbfile"))); + return d_cdbReader->searchSuffix(key); +} + +void TinyDNSBackend::lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p, int zoneId) { + d_isAxfr = false; + string queryDomain = toLowerCanonic(qdomain.toString()); + + string key=simpleCompress(queryDomain); + + DLOG(g_log<(new CDB(getArg("dbfile"))); + d_cdbReader->searchKey(key); + d_dnspacket = pkt_p; +} + + +bool TinyDNSBackend::get(DNSResourceRecord &rr) +{ + pair record; + + while (d_cdbReader->readNext(record)) { + string val = record.second; + string key = record.first; + + //DLOG(g_log< locations = getLocations(); + while(locations.size() > 0) { + string locId = locations.back(); + locations.pop_back(); + + if (recloc[0] == locId[0] && recloc[1] == locId[1]) { + foundLocation = true; + break; + } + } + if (!foundLocation) { + continue; + } + } + } + + if (d_isAxfr && (val[2] == '\052' || val[2] == '\053' )) { // Keys are not stored with wildcard character, with AXFR we need to add that. + key.insert(0, 1, '\052'); + key.insert(0, 1, '\001'); + } + // rr.qname.clear(); + rr.qname=DNSName(key.c_str(), key.size(), 0, false); + rr.domain_id=-1; + // 11:13.21 <@ahu> IT IS ALWAYS AUTH --- well not really because we are just a backend :-) + // We could actually do NSEC3-NARROW DNSSEC according to Habbie, if we do, we need to change something here. + rr.auth = true; + + rr.ttl = pr.get32BitInt(); + uint64_t timestamp = pr.get32BitInt(); + timestamp <<= 32; + timestamp += pr.get32BitInt(); + if(timestamp) { + uint64_t now = d_taiepoch + time(NULL); + if (rr.ttl == 0) { + if (timestamp < now) { + continue; + } + rr.ttl = timestamp - now; + } else if (now <= timestamp) { + continue; + } + } + try { + DNSRecord dr; + dr.d_class = 1; + dr.d_type = rr.qtype.getCode(); + dr.d_clen = val.size()-pr.getPosition(); + + auto drc = DNSRecordContent::mastermake(dr, pr); + rr.content = drc->getZoneRepresentation(); + DLOG(cerr<<"CONTENT: "< +#include +#include +#include +#include "cdb.hh" +#include "pdns/lock.hh" +#include +#include +#include + +using namespace ::boost; +using namespace ::boost::multi_index; + +struct TinyDomainInfo { + uint32_t id; + uint32_t notified_serial; + DNSName zone; + + bool operator<(const TinyDomainInfo& tdi) const + { + return zone < tdi.zone; + } +}; + +struct TDI_SerialModifier { + TDI_SerialModifier (const int newSerial) : d_newSerial(newSerial) {} + + void operator()(TinyDomainInfo& tdi) + { + tdi.notified_serial = d_newSerial; + } + + private: + int d_newSerial; +}; + + +class TinyDNSBackend : public DNSBackend +{ +public: + // Methods for simple operation + TinyDNSBackend(const string &suffix); + void lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1) override; + bool list(const DNSName &target, int domain_id, bool include_disabled=false) override; + bool get(DNSResourceRecord &rr) override; + void getAllDomains(vector *domains, bool include_disabled=false) override; + + //Master mode operation + void getUpdatedMasters(vector* domains) override; + void setNotified(uint32_t id, uint32_t serial) override; +private: + vector getLocations(); + + //TypeDefs + struct tag_zone{}; + struct tag_domainid{}; + typedef multi_index_container< + TinyDomainInfo, + indexed_by< + hashed_unique, member >, + hashed_unique, member > + > + > TDI_t; + typedef map TDI_suffix_t; + typedef TDI_t::index::type TDIByZone_t; + typedef TDI_t::index::type TDIById_t; + + //data member variables + uint64_t d_taiepoch; + QType d_qtype; + std::unique_ptr d_cdbReader; + DNSPacket *d_dnspacket; // used for location and edns-client support. + bool d_isWildcardQuery; // Indicate if the query received was a wildcard query. + bool d_isAxfr; // Indicate if we received a list() and not a lookup(). + bool d_locations; + bool d_ignorebogus; + string d_suffix; + + // Statics + static pthread_mutex_t s_domainInfoLock; + static TDI_suffix_t s_domainInfo; + static uint32_t s_lastId; // used to give a domain an id. +}; + +#endif // TINYDNSBACKEND_HH diff --git a/pdns/Makefile.am b/pdns/Makefile.am new file mode 100644 index 0000000..2b7c304 --- /dev/null +++ b/pdns/Makefile.am @@ -0,0 +1,1635 @@ +JSON11_LIBS = $(top_builddir)/ext/json11/libjson11.la + +AM_CPPFLAGS += \ + -I$(top_srcdir)/ext/json11 \ + $(YAHTTP_CFLAGS) \ + $(LIBEDIT_CFLAGS) \ + $(LIBCRYPTO_INCLUDES) \ + $(SYSTEMD_CFLAGS) \ + $(YAML_CFLAGS) + +AM_CXXFLAGS = \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DPKGLIBDIR=\"$(pkglibdir)\" \ + -DLOCALSTATEDIR=\"$(socketdir)\" + +AM_LDFLAGS = \ + $(PROGRAM_LDFLAGS) \ + $(THREADFLAGS) + +AM_LFLAGS = -i +AM_YFLAGS = -d --verbose --debug + +if PKCS11 +AM_CPPFLAGS += $(P11KIT1_CFLAGS) +endif + +if SQLITE3 +AM_CPPFLAGS += $(SQLITE3_CFLAGS) +endif + +if LUA +AM_CPPFLAGS +=$(LUA_CFLAGS) +endif + +if GSS_TSIG +AM_CPPFLAGS +=$(GSS_CFLAGS) +endif + +if LIBSODIUM +AM_CPPFLAGS +=$(LIBSODIUM_CFLAGS) +endif + +EXTRA_DIST = \ + dnslabeltext.rl \ + dnslabeltext.cc \ + dnsmessage.proto \ + effective_tld_names.dat \ + mtasker.cc \ + inflighter.cc \ + bind-dnssec.schema.sqlite3.sql \ + bindparser.h \ + named.conf.parsertest \ + pdns.service.in \ + ixfrdist.service.in \ + ixfrdist.example.yml \ + lua-record.cc \ + minicurl.cc \ + minicurl.hh + +BUILT_SOURCES = \ + bind-dnssec.schema.sqlite3.sql.h \ + bindparser.h \ + dnslabeltext.cc + +CLEANFILES = \ + *.gcda \ + *.gcno \ + *.gcov \ + backends/gsql/gsqlbackend.gcda \ + backends/gsql/gsqlbackend.gcno \ + backends/gsql/gsqlbackend.gcov \ + dnsmessage.pb.cc dnsmessage.pb.h \ + pdns.conf-dist + +noinst_SCRIPTS = pdns.init +sysconf_DATA = pdns.conf-dist + +sbin_PROGRAMS = pdns_server +bin_PROGRAMS = \ + pdns_control \ + pdnsutil \ + zone2sql \ + zone2json + +if TOOLS +bin_PROGRAMS += \ + dnsgram \ + dnspcap2calidns \ + dnsreplay \ + dnsscan \ + dnsscope \ + dnswasher \ + dumresp \ + pdns_notify \ + nproxy \ + nsec3dig \ + saxfr \ + stubquery \ + ixplore \ + sdig + +bin_PROGRAMS += calidns + +if HAVE_BOOST_GE_148 +bin_PROGRAMS += \ + dnsbulktest \ + dnstcpbench +endif + +endif # TOOLS + +if IXFRDIST +bin_PROGRAMS += \ + ixfrdist + +sysconf_DATA += \ + ixfrdist.example.yml +endif + +EXTRA_PROGRAMS = \ + calidns \ + comfun \ + dnsbulktest \ + dnsdemog \ + dnsgram \ + dnspcap2calidns \ + dnsreplay \ + dnsscan \ + dnsscope \ + dnstcpbench \ + dnswasher \ + dumresp \ + kvresp \ + ixplore \ + ixfrdist \ + pdns_notify \ + nproxy \ + nsec3dig \ + saxfr \ + stubquery \ + sdig \ + speedtest \ + testrunner \ + toysdig \ + tsig-tests \ + zone2ldap + +pdns_server_SOURCES = \ + arguments.cc arguments.hh \ + ascii.hh \ + auth-carbon.cc \ + auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh \ + auth-querycache.cc auth-querycache.hh \ + backends/gsql/gsqlbackend.cc backends/gsql/gsqlbackend.hh \ + backends/gsql/ssql.hh \ + base32.cc base32.hh \ + base64.cc base64.hh \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.cc \ + cachecleaner.hh \ + circular_buffer.hh \ + comment.hh \ + common_startup.cc common_startup.hh \ + communicator.cc communicator.hh \ + dbdnsseckeeper.cc \ + digests.hh \ + distributor.hh \ + dns.cc dns.hh \ + dns_random.cc dns_random.hh \ + dnsbackend.cc dnsbackend.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnspacket.cc dnspacket.hh \ + dnsparser.cc \ + dnsproxy.cc dnsproxy.hh \ + dnsrecords.cc dnsrecords.hh \ + dnssecinfra.cc dnssecinfra.hh \ + dnsseckeeper.hh \ + dnssecsigner.cc \ + dnswriter.cc \ + dynhandler.cc dynhandler.hh \ + dynlistener.cc dynlistener.hh \ + dynmessenger.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + gss_context.cc gss_context.hh \ + iputils.cc iputils.hh \ + ixfr.cc ixfr.hh \ + json.cc json.hh \ + lock.hh \ + logger.cc logger.hh \ + lua-base4.cc lua-base4.hh \ + lua-auth4.cc lua-auth4.hh \ + mastercommunicator.cc \ + misc.cc misc.hh \ + nameserver.cc nameserver.hh \ + namespaces.hh \ + nsecrecords.cc \ + opensslsigners.cc opensslsigners.hh \ + packetcache.hh \ + packethandler.cc packethandler.hh \ + pdnsexception.hh \ + qtype.cc qtype.hh \ + rcpgenerator.cc \ + receiver.cc \ + resolver.cc resolver.hh \ + responsestats.cc responsestats.hh responsestats-auth.cc \ + rfc2136handler.cc \ + secpoll-auth.cc secpoll-auth.hh \ + serialtweaker.cc \ + sha.hh \ + signingpipe.cc signingpipe.hh \ + sillyrecords.cc \ + slavecommunicator.cc \ + statbag.cc statbag.hh \ + stubresolver.cc stubresolver.hh \ + tcpreceiver.cc tcpreceiver.hh \ + threadname.hh threadname.cc \ + tsigverifier.cc tsigverifier.hh \ + tsigutils.hh tsigutils.cc \ + tkey.cc \ + ueberbackend.cc ueberbackend.hh \ + uuid-utils.hh uuid-utils.cc \ + unix_semaphore.cc \ + unix_utility.cc \ + utility.hh \ + version.cc version.hh \ + webserver.cc webserver.hh \ + ws-api.cc ws-api.hh \ + ws-auth.cc ws-auth.hh \ + zoneparser-tng.cc + +pdns_server_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +EXTRA_pdns_server_DEPENDENCIES = @moduleobjects@ +pdns_server_LDADD = \ + @moduleobjects@ \ + @modulelibs@ \ + $(LIBDL) \ + $(YAHTTP_LIBS) \ + $(JSON11_LIBS) \ + $(LIBCRYPTO_LIBS) \ + $(SYSTEMD_LIBS) + +if HAVE_LUA_RECORDS +pdns_server_SOURCES += lua-record.cc minicurl.cc minicurl.hh +pdns_server_LDADD += $(LIBCURL) +endif + +if LIBSODIUM +pdns_server_SOURCES += sodiumsigners.cc +pdns_server_LDADD += $(LIBSODIUM_LIBS) +endif + +if LIBDECAF +pdns_server_SOURCES += decafsigners.cc +pdns_server_LDADD += $(LIBDECAF_LIBS) +endif + +if SQLITE3 +pdns_server_SOURCES += ssqlite3.cc ssqlite3.hh +pdns_server_LDADD += $(SQLITE3_LIBS) +endif + +if ORACLE +pdns_server_LDADD += $(ORACLE_LIBS) +endif + +if PKCS11 +pdns_server_SOURCES += pkcs11signers.cc pkcs11signers.hh +pdns_server_LDADD += $(P11KIT1_LIBS) +endif + +if LUA +pdns_server_LDADD += $(LUA_LIBS) +endif + +if GSS_TSIG +pdns_server_LDADD += $(GSS_LIBS) +endif + +pdnsutil_SOURCES = \ + arguments.cc \ + auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh \ + auth-querycache.cc auth-querycache.hh \ + backends/gsql/gsqlbackend.cc backends/gsql/gsqlbackend.hh \ + backends/gsql/ssql.hh \ + base32.cc \ + base64.cc base64.hh \ + bindlexer.l \ + bindparser.yy \ + cachecleaner.hh \ + circular_buffer.hh \ + dbdnsseckeeper.cc \ + dnsbackend.cc \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnspacket.cc \ + dnsparser.cc dnsparser.hh \ + dns_random.cc \ + dnsrecords.cc \ + dnssecinfra.cc dnssecinfra.hh \ + dnssecsigner.cc \ + dnswriter.cc dnswriter.hh \ + dynlistener.cc \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc \ + gss_context.cc gss_context.hh \ + ipcipher.cc ipcipher.hh \ + iputils.cc iputils.hh \ + json.cc \ + logger.cc \ + lua-auth4.cc lua-auth4.hh \ + lua-base4.cc lua-base4.hh \ + misc.cc misc.hh \ + nsecrecords.cc \ + opensslsigners.cc opensslsigners.hh \ + pdnsutil.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + serialtweaker.cc \ + signingpipe.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + stubresolver.cc stubresolver.hh \ + threadname.hh threadname.cc \ + tsigutils.hh tsigutils.cc \ + ueberbackend.cc \ + unix_utility.cc \ + zoneparser-tng.cc + +pdnsutil_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +EXTRA_pdnsutil_DEPENDENCIES = @moduleobjects@ +pdnsutil_LDADD = \ + @moduleobjects@ \ + @modulelibs@ \ + $(YAHTTP_LIBS) \ + $(JSON11_LIBS) \ + $(LIBDL) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(LIBCRYPTO_LIBS) \ + $(IPCRYPT_LIBS) + +if LIBSODIUM +pdnsutil_SOURCES += sodiumsigners.cc +pdnsutil_LDADD += $(LIBSODIUM_LIBS) +endif + +if LIBDECAF +pdnsutil_SOURCES += decafsigners.cc +pdnsutil_LDADD += $(LIBDECAF_LIBS) +endif + +if SQLITE3 +pdnsutil_SOURCES += ssqlite3.cc ssqlite3.hh +pdnsutil_LDADD += $(SQLITE3_LIBS) +endif + +if ORACLE +pdnsutil_LDADD += $(ORACLE_LIBS) +endif + +if PKCS11 +pdnsutil_SOURCES += pkcs11signers.cc pkcs11signers.hh +pdnsutil_LDADD += $(P11KIT1_LIBS) +endif + +if LUA +pdnsutil_LDADD += $(LUA_LIBS) +endif + +if GSS_TSIG +pdnsutil_LDADD += $(GSS_LIBS) +endif + +zone2sql_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dns.cc \ + dns_random_urandom.cc \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + json.cc json.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2sql.cc \ + zoneparser-tng.cc + +zone2sql_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS) +zone2sql_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +zone2json_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2json.cc \ + zoneparser-tng.cc + +zone2json_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS) +zone2json_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +# pkglib_LTLIBRARIES = iputils.la +# iputils_la_SOURCES = lua-iputils.cc +# iputils_la_LDFLAGS= -module -avoid-version + +if LDAP +bin_PROGRAMS += zone2ldap +endif + +zone2ldap_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dns_random_urandom.cc \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2ldap.cc \ + zoneparser-tng.cc + +zone2ldap_LDADD = $(LIBCRYPTO_LIBS) +zone2ldap_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +sdig_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + ednssubnet.cc iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sdig.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + unix_utility.cc + +sdig_LDADD = $(LIBCRYPTO_LIBS) +sdig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +if HAVE_LIBCURL +sdig_SOURCES += minicurl.cc minicurl.hh +sdig_LDADD += $(LIBCURL) +endif + +calidns_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + calidns.cc \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + unix_utility.cc + +calidns_LDADD = $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) +calidns_LDFLAGS = $(AM_LDFLAGS) $(THREADFLAGS) $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dumresp_SOURCES = \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dumresp.cc \ + logger.cc \ + misc.cc misc.hh \ + statbag.cc \ + unix_utility.cc \ + qtype.cc + +kvresp_SOURCES = \ + dnslabeltext.cc dnsname.cc dnsname.hh \ + kvresp.cc \ + logger.cc \ + misc.cc misc.hh \ + statbag.cc \ + unix_utility.cc \ + qtype.cc + +stubquery_SOURCES = \ + arguments.cc arguments.hh \ + base32.cc \ + base64.cc \ + dns_random_urandom.cc \ + dnslabeltext.cc \ + dnsname.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + stubresolver.cc stubresolver.hh \ + stubquery.cc \ + unix_utility.cc + +stubquery_LDADD = $(LIBCRYPTO_LIBS) +stubquery_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +saxfr_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + saxfr.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + unix_utility.cc + +saxfr_LDADD = $(LIBCRYPTO_LIBS) +saxfr_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +if PKCS11 +saxfr_SOURCES += pkcs11signers.cc pkcs11signers.hh +saxfr_LDADD += $(P11KIT1_LIBS) +endif + +if GSS_TSIG +saxfr_LDADD += $(GSS_LIBS) +endif + +ixfrdist_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh \ + iputils.hh iputils.cc \ + ixfr.cc ixfr.hh \ + ixfrdist.cc \ + ixfrutils.cc ixfrutils.hh \ + ixfrdist-stats.hh ixfrdist-stats.cc \ + ixfrdist-web.hh ixfrdist-web.cc \ + logger.cc logger.hh\ + misc.cc misc.hh \ + mplexer.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + resolver.cc \ + pollmplexer.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + threadname.hh threadname.cc \ + tsigverifier.cc tsigverifier.hh \ + unix_utility.cc \ + uuid-utils.hh uuid-utils.cc \ + webserver.hh webserver.cc \ + zoneparser-tng.cc + + +ixfrdist_LDADD = \ + $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(JSON11_LIBS) \ + $(LIBCRYPTO_LIBS) \ + $(YAHTTP_LIBS) \ + $(YAML_LIBS) + +ixfrdist_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +if PKCS11 +ixfrdist_SOURCES += pkcs11signers.cc pkcs11signers.hh +ixfrdist_LDADD += $(P11KIT1_LIBS) +endif + +if GSS_TSIG +ixfrdist_LDADD += $(GSS_LIBS) +endif + + +ixplore_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + resolver.cc \ + ixfr.cc ixfr.hh \ + ixfrutils.cc ixfrutils.hh \ + ixplore.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + tsigverifier.cc tsigverifier.hh \ + unix_utility.cc zoneparser-tng.cc + +ixplore_LDADD = $(LIBCRYPTO_LIBS) +ixplore_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +if PKCS11 +ixplore_SOURCES += pkcs11signers.cc pkcs11signers.hh +ixplore_LDADD += $(P11KIT1_LIBS) +endif + +if GSS_TSIG +ixplore_LDADD += $(GSS_LIBS) +endif + + +dnstcpbench_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnstcpbench.cc \ + dnswriter.cc dnswriter.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + threadname.hh threadname.cc \ + unix_utility.cc + +dnstcpbench_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnstcpbench_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +nsec3dig_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsec3dig.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + unix_utility.cc + +nsec3dig_LDADD = $(LIBCRYPTO_LIBS) +nsec3dig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +if PKCS11 +nsec3dig_SOURCES += pkcs11signers.cc pkcs11signers.hh +nsec3dig_LDADD += $(P11KIT1_LIBS) +endif + +if GSS_TSIG +nsec3dig_LDADD += $(GSS_LIBS) +endif + +toysdig_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dns_random_urandom.cc \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + ednssubnet.cc ednssubnet.hh \ + filterpo.hh \ + gss_context.cc gss_context.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + opensslsigners.cc opensslsigners.hh \ + qtype.cc \ + root-dnssec.hh \ + rcpgenerator.cc rcpgenerator.hh \ + rec-lua-conf.hh \ + recursor_cache.hh \ + sholder.hh \ + sillyrecords.cc \ + sortlist.hh \ + sstuff.hh \ + statbag.cc \ + toysdig.cc \ + unix_utility.cc \ + validate.cc validate.hh + + +toysdig_LDFLAGS = $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) +toysdig_LDADD = $(LIBCRYPTO_LIBS) + +if GSS_TSIG +toysdig_LDADD += $(GSS_LIBS) +endif + +if PKCS11 +toysdig_SOURCES += pkcs11signers.cc pkcs11signers.hh +toysdig_LDADD += $(P11KIT1_LIBS) +endif + +tsig_tests_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + digests.hh \ + dns.cc \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + resolver.cc \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + tsig-tests.cc \ + tsigverifier.cc tsigverifier.hh \ + unix_utility.cc + +tsig_tests_LDADD = $(LIBCRYPTO_LIBS) +tsig_tests_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) + +if PKCS11 +tsig_tests_SOURCES += pkcs11signers.cc pkcs11signers.hh +tsig_tests_LDADD += $(P11KIT1_LIBS) +endif + +if GSS_TSIG +tsig_tests_LDADD += $(GSS_LIBS) +endif + +speedtest_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + speedtest.cc \ + statbag.cc \ + unix_utility.cc \ + iputils.cc + +speedtest_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +speedtest_LDADD = $(LIBCRYPTO_LIBS) \ + $(RT_LIBS) + +dnswasher_SOURCES = \ + base64.cc \ + dnslabeltext.cc \ + dnsname.hh dnsname.cc \ + dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnswasher.cc \ + dnswriter.hh \ + ipcipher.cc ipcipher.hh \ + logger.cc \ + misc.cc \ + qtype.cc \ + statbag.cc \ + unix_utility.cc + +dnswasher_LDFLAGS = $(AM_LDFLAGS) $(BOOST_PROGRAM_OPTIONS_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +dnswasher_LDADD = $(BOOST_PROGRAM_OPTIONS_LIBS) $(LIBCRYPTO_LIBS) $(IPCRYPT_LIBS) + +dnsbulktest_SOURCES = \ + base32.cc \ + base64.cc \ + dnsbulktest.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc + +dnsbulktest_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsbulktest_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +comfun_SOURCES = \ + base32.cc \ + base64.cc \ + comfun.cc \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zoneparser-tng.cc zoneparser-tng.hh + +comfun_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +comfun_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + + +dnsscan_SOURCES = \ + anadns.hh \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsscan.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsscan_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsscan_LDADD = $(LIBCRYPTO_LIBS) + +dnsreplay_SOURCES = \ + anadns.hh \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsreplay.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsreplay_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsreplay_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +nproxy_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + mplexer.hh \ + nproxy.cc \ + nsecrecords.cc \ + pollmplexer.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc + +nproxy_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +nproxy_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +pdns_notify_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + notify.cc \ + nsecrecords.cc \ + pollmplexer.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + dns_random.cc + +pdns_notify_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +pdns_notify_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +if LIBSODIUM +pdns_notify_LDADD += $(LIBSODIUM_LIBS) +endif + +dnsscope_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsscope.cc \ + dnswriter.cc dnswriter.hh \ + histog.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + statnode.cc statnode.hh \ + unix_utility.cc \ + utility.hh + +dnsscope_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsscope_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +dnsgram_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnsgram.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsgram_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsgram_LDADD = \ + $(LIBCRYPTO_LIBS) + +dnsdemog_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnsdemog.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsdemog_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsdemog_LDADD = \ + $(LIBCRYPTO_LIBS) + +dnspcap2calidns_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnspcap2calidns.cc \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnspcap2calidns_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnspcap2calidns_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +if HAVE_PROTOBUF +if HAVE_PROTOC +bin_PROGRAMS += dnspcap2protobuf + +dnsmessage.pb.cc: dnsmessage.proto + $(AM_V_GEN)$(PROTOC) --cpp_out=./ $< + +BUILT_SOURCES += dnsmessage.pb.cc +dnspcap2protobuf.$(OBJEXT): dnsmessage.pb.cc + +dnspcap2protobuf_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnspcap2protobuf.cc \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + gettime.cc gettime.hh \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + protobuf.cc protobuf.hh \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh \ + uuid-utils.hh uuid-utils.cc + +nodist_dnspcap2protobuf_SOURCES=dnsmessage.pb.cc dnsmessage.pb.h + +dnspcap2protobuf_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnspcap2protobuf_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(PROTOBUF_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(RT_LIBS) +endif +endif + +pdns.conf-dist: pdns_server + $(AM_V_GEN)./pdns_server --no-config --config 2>/dev/null > $@ + +testrunner_SOURCES = \ + arguments.cc \ + auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh \ + auth-querycache.cc auth-querycache.hh \ + base32.cc \ + base64.cc \ + bindlexer.l \ + bindparser.yy \ + dbdnsseckeeper.cc \ + dns.cc \ + dns_random.cc \ + dnsbackend.cc \ + dnslabeltext.cc \ + dnsname.cc \ + dnsname.hh \ + dnspacket.cc \ + dnsparser.hh dnsparser.cc \ + dnsrecords.cc \ + dnssecinfra.cc \ + dnssecsigner.cc \ + dnswriter.cc \ + ednsoptions.cc ednsoptions.hh \ + ednscookies.cc ednscookies.hh \ + ednssubnet.cc \ + gettime.cc gettime.hh \ + gss_context.cc gss_context.hh \ + ipcipher.cc ipcipher.hh \ + iputils.cc \ + ixfr.cc ixfr.hh \ + logger.cc \ + lua-auth4.hh lua-auth4.cc \ + lua-base4.hh lua-base4.cc \ + stubresolver.hh stubresolver.cc \ + misc.cc \ + nameserver.cc \ + nsecrecords.cc \ + opensslsigners.cc opensslsigners.hh \ + pollmplexer.cc \ + qtype.cc \ + rcpgenerator.cc \ + responsestats.cc \ + responsestats-auth.cc \ + sillyrecords.cc \ + statbag.cc \ + test-arguments_cc.cc \ + test-base32_cc.cc \ + test-base64_cc.cc \ + test-bindparser_cc.cc \ + test-common.hh \ + test-dnsrecordcontent.cc \ + test-digests_hh.cc \ + test-distributor_hh.cc \ + test-dns_random_hh.cc \ + test-dnsname_cc.cc \ + test-dnsparser_cc.cc \ + test-dnsparser_hh.cc \ + test-dnsrecords_cc.cc \ + test-dnswriter_cc.cc \ + test-ipcrypt_cc.cc \ + test-iputils_hh.cc \ + test-ixfr_cc.cc \ + test-lock_hh.cc \ + test-lua_auth4_cc.cc \ + test-misc_hh.cc \ + test-mplexer.cc \ + test-nameserver_cc.cc \ + test-packetcache_cc.cc \ + test-packetcache_hh.cc \ + test-rcpgenerator_cc.cc \ + test-signers.cc \ + test-sha_hh.cc \ + test-statbag_cc.cc \ + test-tsig.cc \ + test-zoneparser_tng_cc.cc \ + testrunner.cc \ + threadname.hh threadname.cc \ + tsigverifier.cc tsigverifier.hh \ + ueberbackend.cc \ + unix_utility.cc \ + zoneparser-tng.cc zoneparser-tng.hh + +testrunner_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) + +testrunner_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ + $(RT_LIBS) \ + $(LUA_LIBS) \ + $(LIBDL) \ + $(IPCRYPT_LIBS) + +if PKCS11 +testrunner_SOURCES += pkcs11signers.cc pkcs11signers.hh +testrunner_LDADD += $(P11KIT1_LIBS) +endif + +if LIBSODIUM +testrunner_SOURCES += sodiumsigners.cc +testrunner_LDADD += $(LIBSODIUM_LIBS) +endif + +if LIBDECAF +testrunner_SOURCES += decafsigners.cc +testrunner_LDADD += $(LIBDECAF_LIBS) +endif + +if HAVE_FREEBSD +ixfrdist_SOURCES += kqueuemplexer.cc +testrunner_SOURCES += kqueuemplexer.cc +endif + +if HAVE_LINUX +ixfrdist_SOURCES += epollmplexer.cc +testrunner_SOURCES += epollmplexer.cc +endif + +if HAVE_SOLARIS +ixfrdist_SOURCES += \ + devpollmplexer.cc \ + portsmplexer.cc +testrunner_SOURCES += \ + devpollmplexer.cc \ + portsmplexer.cc +endif + +pdns_control_SOURCES = \ + arguments.cc \ + dynloader.cc \ + dynmessenger.cc \ + logger.cc \ + misc.cc \ + qtype.cc \ + statbag.cc \ + unix_utility.cc \ + dnsname.cc \ + dnslabeltext.cc + +if UNIT_TESTS + +if HAVE_BOOST_GE_148 +TESTS_ENVIRONMENT = env BOOST_TEST_LOG_LEVEL=message SRCDIR='$(srcdir)' +TESTS=testrunner +else +check-local: + @echo "Unit tests disabled, boost is too old" +endif + +else +check-local: + @echo "Unit tests are not enabled" + @echo "Run ./configure --enable-unit-tests" +endif + +if FUZZ_TARGETS + +LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o + +standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cc + +fuzz_targets_programs = \ + fuzz_target_dnsdistcache \ + fuzz_target_moadnsparser \ + fuzz_target_packetcache \ + fuzz_target_zoneparsertng + +fuzz_targets: $(fuzz_targets_programs) + +bin_PROGRAMS += \ + $(fuzz_targets_programs) + +fuzz_targets_libs = \ + $(LIBCRYPTO_LIBS) \ + $(LIB_FUZZING_ENGINE) +fuzz_targets_ldflags = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(FUZZING_LDFLAGS) + +# we need the mockup runner to be built, but not linked if a real fuzzing engine is used +fuzz_targets_deps = standalone_fuzz_target_runner.o + +fuzz_target_moadnsparser_SOURCES = \ + fuzz_moadnsparser.cc \ + base32.cc base32.hh \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc dnsrecords.hh \ + dnswriter.cc dnswriter.hh \ + logger.cc logger.hh \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc statbag.hh \ + unix_utility.cc \ + utility.hh + +fuzz_target_moadnsparser_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_target_moadnsparser_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_target_moadnsparser_LDADD = $(fuzz_targets_libs) + +fuzz_target_packetcache_SOURCES = \ + fuzz_packetcache.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + ednsoptions.cc ednsoptions.hh \ + misc.cc misc.hh \ + packetcache.hh \ + qtype.cc qtype.hh \ + statbag.cc statbag.hh + +fuzz_target_packetcache_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_target_packetcache_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_target_packetcache_LDADD = $(fuzz_targets_libs) + +fuzz_target_dnsdistcache_SOURCES = \ + fuzz_dnsdistcache.cc \ + dnsdist-cache.cc dnsdist-cache.hh \ + dnsdist-ecs.cc dnsdist-ecs.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnswriter.cc dnswriter.hh \ + doh.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc iputils.hh \ + misc.cc misc.hh \ + packetcache.hh \ + qtype.cc qtype.hh + +fuzz_target_dnsdistcache_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_target_dnsdistcache_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_target_dnsdistcache_LDADD = $(fuzz_targets_libs) + +fuzz_target_zoneparsertng_SOURCES = \ + fuzz_zoneparsertng.cc \ + base32.cc base32.hh \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc dnsrecords.hh \ + dnswriter.cc dnswriter.hh \ + logger.cc logger.hh \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc statbag.hh \ + unix_utility.cc \ + utility.hh \ + zoneparser-tng.cc zoneparser-tng.hh + +fuzz_target_zoneparsertng_DEPENDENCIES = $(fuzz_targets_deps) +fuzz_target_zoneparsertng_LDFLAGS = $(fuzz_targets_ldflags) +fuzz_target_zoneparsertng_LDADD = $(fuzz_targets_libs) + +endif + +dnslabeltext.cc: dnslabeltext.rl + $(AM_V_GEN)$(RAGEL) $< -o dnslabeltext.cc + +bind-dnssec.schema.sqlite3.sql.h: bind-dnssec.schema.sqlite3.sql + ( echo 'static char sqlCreate[] __attribute__((unused))=' ; sed 's/$$/"/g' $< | sed 's/^/"/g' ; echo ';' ) > $@ + +# for bindparser.h/hh +.hh.h: + cp $< $@ + +bindlexer.$(OBJEXT): bindparser.h + +curl_verbose = $(curl_verbose_$(V)) +curl_verbose_ = $(curl_verbose_$(AM_DEFAULT_VERBOSITY)) +curl_verbose_0 = @echo " CURL " $@; +$(srcdir)/effective_tld_names.dat: + $(curl_verbose)if ! curl -s -S https://publicsuffix.org/list/public_suffix_list.dat > $@; then rm -f $@; exit 1; fi + +pubsuffix.cc: $(srcdir)/effective_tld_names.dat + $(AM_V_GEN)./mkpubsuffixcc + +pdns_recursor rec_control: + @echo "Please build the recursor from the recursordist/ dir" + @exit 1 + +dnsdist: + @echo "Please build dnsdist from the dnsdistdist/ dir" + @exit 1 + +if HAVE_SYSTEMD +pdns.service: pdns.service.in + $(AM_V_GEN)sed -e 's![@]sbindir[@]!$(sbindir)!' < $< > $@ +if !HAVE_SYSTEMD_LOCK_PERSONALITY + $(AM_V_GEN)perl -ni -e 'print unless /^LockPersonality/' $@ +endif +if !HAVE_SYSTEMD_PRIVATE_DEVICES + $(AM_V_GEN)perl -ni -e 'print unless /^PrivateDevices/' $@ +endif +if !HAVE_SYSTEMD_PRIVATE_TMP + $(AM_V_GEN)perl -ni -e 'print unless /^PrivateTmp/' $@ +endif +if !HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS + $(AM_V_GEN)perl -ni -e 'print unless /^ProtectControlGroups/' $@ +endif +if !HAVE_SYSTEMD_PROTECT_HOME + $(AM_V_GEN)perl -ni -e 'print unless /^ProtectHome/' $@ +endif +if !HAVE_SYSTEMD_PROTECT_KERNEL_MODULES + $(AM_V_GEN)perl -ni -e 'print unless /^ProtectKernelModules/' $@ +endif +if !HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES + $(AM_V_GEN)perl -ni -e 'print unless /^ProtectKernelTunables/' $@ +endif +if !HAVE_SYSTEMD_PROTECT_SYSTEM + $(AM_V_GEN)perl -ni -e 'print unless /^ProtectSystem/' $@ +endif +if !HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES + $(AM_V_GEN)perl -ni -e 'print unless /^RestrictAddressFamilies/' $@ +endif +if !HAVE_SYSTEMD_RESTRICT_NAMESPACES + $(AM_V_GEN)perl -ni -e 'print unless /^RestrictNamespaces/' $@ +endif +if !HAVE_SYSTEMD_RESTRICT_REALTIME + $(AM_V_GEN)perl -ni -e 'print unless /^RestrictRealtime/' $@ +endif +if !HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES + $(AM_V_GEN)perl -ni -e 'print unless /^SystemCallArchitectures/' $@ +endif +if !HAVE_SYSTEMD_SYSTEM_CALL_FILTER + $(AM_V_GEN)perl -ni -e 'print unless /^SystemCallFilter/' $@ +endif + +pdns@.service: pdns.service + $(AM_V_GEN)sed -e 's!/pdns_server!& --config-name=%i!' \ + -e 's!Authoritative Server!& %i!' \ + < $< > $@ + +systemdsystemunitdir = $(SYSTEMD_DIR) + +systemdsystemunit_DATA = \ + pdns.service \ + pdns@.service + +CLEANFILES += \ + pdns.service \ + pdns@.service + +if IXFRDIST +ixfrdist.service: ixfrdist.service.in + $(AM_V_GEN)sed -e 's![@]bindir[@]!$(bindir)!' < $< > $@ + +ixfrdist@.service: ixfrdist.service + $(AM_V_GEN)sed -e 's!/ixfrdist!& --config $(sysconfdir)/ixfrdist-%i.yml!' \ + < $< > $@ + +systemdsystemunit_DATA += \ + ixfrdist.service \ + ixfrdist@.service +endif # IXFRDIST + +CLEANFILES += \ + ixfrdist.service \ + ixfrdist@.service + +endif # HAVE_SYSTEMD diff --git a/pdns/Makefile.in b/pdns/Makefile.in new file mode 100644 index 0000000..0bc639c --- /dev/null +++ b/pdns/Makefile.in @@ -0,0 +1,3573 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@PKCS11_TRUE@am__append_1 = $(P11KIT1_CFLAGS) +@SQLITE3_TRUE@am__append_2 = $(SQLITE3_CFLAGS) +@LUA_TRUE@am__append_3 = $(LUA_CFLAGS) +@GSS_TSIG_TRUE@am__append_4 = $(GSS_CFLAGS) +@LIBSODIUM_TRUE@am__append_5 = $(LIBSODIUM_CFLAGS) +sbin_PROGRAMS = pdns_server$(EXEEXT) +bin_PROGRAMS = pdns_control$(EXEEXT) pdnsutil$(EXEEXT) \ + zone2sql$(EXEEXT) zone2json$(EXEEXT) $(am__EXEEXT_1) \ + $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ + $(am__EXEEXT_5) $(am__EXEEXT_7) +@TOOLS_TRUE@am__append_6 = dnsgram dnspcap2calidns dnsreplay dnsscan \ +@TOOLS_TRUE@ dnsscope dnswasher dumresp pdns_notify nproxy \ +@TOOLS_TRUE@ nsec3dig saxfr stubquery ixplore sdig calidns +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@am__append_7 = \ +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@ dnsbulktest \ +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@ dnstcpbench + +@IXFRDIST_TRUE@am__append_8 = \ +@IXFRDIST_TRUE@ ixfrdist + +@IXFRDIST_TRUE@am__append_9 = \ +@IXFRDIST_TRUE@ ixfrdist.example.yml + +EXTRA_PROGRAMS = calidns$(EXEEXT) comfun$(EXEEXT) dnsbulktest$(EXEEXT) \ + dnsdemog$(EXEEXT) dnsgram$(EXEEXT) dnspcap2calidns$(EXEEXT) \ + dnsreplay$(EXEEXT) dnsscan$(EXEEXT) dnsscope$(EXEEXT) \ + dnstcpbench$(EXEEXT) dnswasher$(EXEEXT) dumresp$(EXEEXT) \ + kvresp$(EXEEXT) ixplore$(EXEEXT) ixfrdist$(EXEEXT) \ + pdns_notify$(EXEEXT) nproxy$(EXEEXT) nsec3dig$(EXEEXT) \ + saxfr$(EXEEXT) stubquery$(EXEEXT) sdig$(EXEEXT) \ + speedtest$(EXEEXT) testrunner$(EXEEXT) toysdig$(EXEEXT) \ + tsig-tests$(EXEEXT) zone2ldap$(EXEEXT) +@HAVE_LUA_RECORDS_TRUE@am__append_10 = lua-record.cc minicurl.cc minicurl.hh +@HAVE_LUA_RECORDS_TRUE@am__append_11 = $(LIBCURL) +@LIBSODIUM_TRUE@am__append_12 = sodiumsigners.cc +@LIBSODIUM_TRUE@am__append_13 = $(LIBSODIUM_LIBS) +@LIBDECAF_TRUE@am__append_14 = decafsigners.cc +@LIBDECAF_TRUE@am__append_15 = $(LIBDECAF_LIBS) +@SQLITE3_TRUE@am__append_16 = ssqlite3.cc ssqlite3.hh +@SQLITE3_TRUE@am__append_17 = $(SQLITE3_LIBS) +@ORACLE_TRUE@am__append_18 = $(ORACLE_LIBS) +@PKCS11_TRUE@am__append_19 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_20 = $(P11KIT1_LIBS) +@LUA_TRUE@am__append_21 = $(LUA_LIBS) +@GSS_TSIG_TRUE@am__append_22 = $(GSS_LIBS) +@LIBSODIUM_TRUE@am__append_23 = sodiumsigners.cc +@LIBSODIUM_TRUE@am__append_24 = $(LIBSODIUM_LIBS) +@LIBDECAF_TRUE@am__append_25 = decafsigners.cc +@LIBDECAF_TRUE@am__append_26 = $(LIBDECAF_LIBS) +@SQLITE3_TRUE@am__append_27 = ssqlite3.cc ssqlite3.hh +@SQLITE3_TRUE@am__append_28 = $(SQLITE3_LIBS) +@ORACLE_TRUE@am__append_29 = $(ORACLE_LIBS) +@PKCS11_TRUE@am__append_30 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_31 = $(P11KIT1_LIBS) +@LUA_TRUE@am__append_32 = $(LUA_LIBS) +@GSS_TSIG_TRUE@am__append_33 = $(GSS_LIBS) + +# pkglib_LTLIBRARIES = iputils.la +# iputils_la_SOURCES = lua-iputils.cc +# iputils_la_LDFLAGS= -module -avoid-version +@LDAP_TRUE@am__append_34 = zone2ldap +@HAVE_LIBCURL_TRUE@am__append_35 = minicurl.cc minicurl.hh +@HAVE_LIBCURL_TRUE@am__append_36 = $(LIBCURL) +@PKCS11_TRUE@am__append_37 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_38 = $(P11KIT1_LIBS) +@GSS_TSIG_TRUE@am__append_39 = $(GSS_LIBS) +@PKCS11_TRUE@am__append_40 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_41 = $(P11KIT1_LIBS) +@GSS_TSIG_TRUE@am__append_42 = $(GSS_LIBS) +@PKCS11_TRUE@am__append_43 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_44 = $(P11KIT1_LIBS) +@GSS_TSIG_TRUE@am__append_45 = $(GSS_LIBS) +@PKCS11_TRUE@am__append_46 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_47 = $(P11KIT1_LIBS) +@GSS_TSIG_TRUE@am__append_48 = $(GSS_LIBS) +@GSS_TSIG_TRUE@am__append_49 = $(GSS_LIBS) +@PKCS11_TRUE@am__append_50 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_51 = $(P11KIT1_LIBS) +@PKCS11_TRUE@am__append_52 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_53 = $(P11KIT1_LIBS) +@GSS_TSIG_TRUE@am__append_54 = $(GSS_LIBS) +@LIBSODIUM_TRUE@am__append_55 = $(LIBSODIUM_LIBS) +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@am__append_56 = dnspcap2protobuf +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@am__append_57 = dnsmessage.pb.cc +@PKCS11_TRUE@am__append_58 = pkcs11signers.cc pkcs11signers.hh +@PKCS11_TRUE@am__append_59 = $(P11KIT1_LIBS) +@LIBSODIUM_TRUE@am__append_60 = sodiumsigners.cc +@LIBSODIUM_TRUE@am__append_61 = $(LIBSODIUM_LIBS) +@LIBDECAF_TRUE@am__append_62 = decafsigners.cc +@LIBDECAF_TRUE@am__append_63 = $(LIBDECAF_LIBS) +@HAVE_FREEBSD_TRUE@am__append_64 = kqueuemplexer.cc +@HAVE_FREEBSD_TRUE@am__append_65 = kqueuemplexer.cc +@HAVE_LINUX_TRUE@am__append_66 = epollmplexer.cc +@HAVE_LINUX_TRUE@am__append_67 = epollmplexer.cc +@HAVE_SOLARIS_TRUE@am__append_68 = \ +@HAVE_SOLARIS_TRUE@ devpollmplexer.cc \ +@HAVE_SOLARIS_TRUE@ portsmplexer.cc + +@HAVE_SOLARIS_TRUE@am__append_69 = \ +@HAVE_SOLARIS_TRUE@ devpollmplexer.cc \ +@HAVE_SOLARIS_TRUE@ portsmplexer.cc + +@HAVE_BOOST_GE_148_TRUE@@UNIT_TESTS_TRUE@TESTS = testrunner$(EXEEXT) +@FUZZ_TARGETS_TRUE@am__append_70 = \ +@FUZZ_TARGETS_TRUE@ $(fuzz_targets_programs) + +@HAVE_SYSTEMD_TRUE@am__append_71 = pdns.service pdns@.service \ +@HAVE_SYSTEMD_TRUE@ ixfrdist.service ixfrdist@.service +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@am__append_72 = \ +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ ixfrdist.service \ +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ ixfrdist@.service + +subdir = pdns +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_pthread_set_name.m4 \ + $(top_srcdir)/m4/ax_arg_default_enable_disable.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libcurl.m4 \ + $(top_srcdir)/m4/libtool.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/pdns_check_bison.m4 \ + $(top_srcdir)/m4/pdns_check_cdb.m4 \ + $(top_srcdir)/m4/pdns_check_clock_gettime.m4 \ + $(top_srcdir)/m4/pdns_check_curl_program.m4 \ + $(top_srcdir)/m4/pdns_check_flex.m4 \ + $(top_srcdir)/m4/pdns_check_ldap.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_ecdsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcrypto_eddsa.m4 \ + $(top_srcdir)/m4/pdns_check_libcurl.m4 \ + $(top_srcdir)/m4/pdns_check_lmdb.m4 \ + $(top_srcdir)/m4/pdns_check_lua_hpp.m4 \ + $(top_srcdir)/m4/pdns_check_network_libs.m4 \ + $(top_srcdir)/m4/pdns_check_opendbx.m4 \ + $(top_srcdir)/m4/pdns_check_os.m4 \ + $(top_srcdir)/m4/pdns_check_ragel.m4 \ + $(top_srcdir)/m4/pdns_check_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_check_virtualenv.m4 \ + $(top_srcdir)/m4/pdns_d_fortify_source.m4 \ + $(top_srcdir)/m4/pdns_enable_backend_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_coverage.m4 \ + $(top_srcdir)/m4/pdns_enable_fuzz_targets.m4 \ + $(top_srcdir)/m4/pdns_enable_gss_tsig.m4 \ + $(top_srcdir)/m4/pdns_enable_ixfrdist.m4 \ + $(top_srcdir)/m4/pdns_enable_kiss.m4 \ + $(top_srcdir)/m4/pdns_enable_malloc_trace.m4 \ + $(top_srcdir)/m4/pdns_enable_p11kit.m4 \ + $(top_srcdir)/m4/pdns_enable_remotebackend_zeromq.m4 \ + $(top_srcdir)/m4/pdns_enable_reproducible.m4 \ + $(top_srcdir)/m4/pdns_enable_sanitizers.m4 \ + $(top_srcdir)/m4/pdns_enable_tools.m4 \ + $(top_srcdir)/m4/pdns_enable_unit_tests.m4 \ + $(top_srcdir)/m4/pdns_enable_verbose_logging.m4 \ + $(top_srcdir)/m4/pdns_from_git.m4 \ + $(top_srcdir)/m4/pdns_param_ssp_buffer_size.m4 \ + $(top_srcdir)/m4/pdns_pie.m4 $(top_srcdir)/m4/pdns_relro.m4 \ + $(top_srcdir)/m4/pdns_stack_protector.m4 \ + $(top_srcdir)/m4/pdns_with_geo.m4 \ + $(top_srcdir)/m4/pdns_with_libdecaf.m4 \ + $(top_srcdir)/m4/pdns_with_libsodium.m4 \ + $(top_srcdir)/m4/pdns_with_lua.m4 \ + $(top_srcdir)/m4/pdns_with_lua_records.m4 \ + $(top_srcdir)/m4/pdns_with_mysql.m4 \ + $(top_srcdir)/m4/pdns_with_oracle.m4 \ + $(top_srcdir)/m4/pdns_with_postgresql.m4 \ + $(top_srcdir)/m4/pdns_with_protobuf.m4 \ + $(top_srcdir)/m4/pdns_with_sqlite3.m4 \ + $(top_srcdir)/m4/pdns_with_unixodbc.m4 \ + $(top_srcdir)/m4/systemd.m4 $(top_srcdir)/m4/tm-gmtoff.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdns.init +CONFIG_CLEAN_VPATH_FILES = +@TOOLS_TRUE@am__EXEEXT_1 = dnsgram$(EXEEXT) dnspcap2calidns$(EXEEXT) \ +@TOOLS_TRUE@ dnsreplay$(EXEEXT) dnsscan$(EXEEXT) \ +@TOOLS_TRUE@ dnsscope$(EXEEXT) dnswasher$(EXEEXT) \ +@TOOLS_TRUE@ dumresp$(EXEEXT) pdns_notify$(EXEEXT) \ +@TOOLS_TRUE@ nproxy$(EXEEXT) nsec3dig$(EXEEXT) saxfr$(EXEEXT) \ +@TOOLS_TRUE@ stubquery$(EXEEXT) ixplore$(EXEEXT) sdig$(EXEEXT) \ +@TOOLS_TRUE@ calidns$(EXEEXT) +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@am__EXEEXT_2 = \ +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@ dnsbulktest$(EXEEXT) \ +@HAVE_BOOST_GE_148_TRUE@@TOOLS_TRUE@ dnstcpbench$(EXEEXT) +@IXFRDIST_TRUE@am__EXEEXT_3 = ixfrdist$(EXEEXT) +@LDAP_TRUE@am__EXEEXT_4 = zone2ldap$(EXEEXT) +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@am__EXEEXT_5 = dnspcap2protobuf$(EXEEXT) +@FUZZ_TARGETS_TRUE@am__EXEEXT_6 = fuzz_target_dnsdistcache$(EXEEXT) \ +@FUZZ_TARGETS_TRUE@ fuzz_target_moadnsparser$(EXEEXT) \ +@FUZZ_TARGETS_TRUE@ fuzz_target_packetcache$(EXEEXT) \ +@FUZZ_TARGETS_TRUE@ fuzz_target_zoneparsertng$(EXEEXT) +@FUZZ_TARGETS_TRUE@am__EXEEXT_7 = $(am__EXEEXT_6) +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \ + "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(systemdsystemunitdir)" +PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) +am_calidns_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + calidns.$(OBJEXT) dns_random_urandom.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) ednsoptions.$(OBJEXT) \ + ednssubnet.$(OBJEXT) iputils.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) +calidns_OBJECTS = $(am_calidns_OBJECTS) +am__DEPENDENCIES_1 = +calidns_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +calidns_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(calidns_LDFLAGS) $(LDFLAGS) -o $@ +am_comfun_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) comfun.$(OBJEXT) \ + dns.$(OBJEXT) dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) \ + zoneparser-tng.$(OBJEXT) +comfun_OBJECTS = $(am_comfun_OBJECTS) +comfun_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +comfun_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(comfun_LDFLAGS) $(LDFLAGS) -o $@ +am_dnsbulktest_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnsbulktest.$(OBJEXT) dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) +dnsbulktest_OBJECTS = $(am_dnsbulktest_OBJECTS) +dnsbulktest_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +dnsbulktest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsbulktest_LDFLAGS) $(LDFLAGS) -o $@ +am_dnsdemog_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnsdemog.$(OBJEXT) dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnspcap.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnswriter.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) +dnsdemog_OBJECTS = $(am_dnsdemog_OBJECTS) +dnsdemog_DEPENDENCIES = $(am__DEPENDENCIES_1) +dnsdemog_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsdemog_LDFLAGS) $(LDFLAGS) -o $@ +am_dnsgram_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnsgram.$(OBJEXT) dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnspcap.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnswriter.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) +dnsgram_OBJECTS = $(am_dnsgram_OBJECTS) +dnsgram_DEPENDENCIES = $(am__DEPENDENCIES_1) +dnsgram_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsgram_LDFLAGS) $(LDFLAGS) -o $@ +am_dnspcap2calidns_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnspcap.$(OBJEXT) dnspcap2calidns.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) ednsoptions.$(OBJEXT) \ + ednssubnet.$(OBJEXT) iputils.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) +dnspcap2calidns_OBJECTS = $(am_dnspcap2calidns_OBJECTS) +dnspcap2calidns_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +dnspcap2calidns_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(dnspcap2calidns_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__dnspcap2protobuf_SOURCES_DIST = base32.cc base64.cc base64.hh \ + dnslabeltext.cc dnsname.cc dnsname.hh dnsparser.cc \ + dnsparser.hh dnspcap.cc dnspcap.hh dnspcap2protobuf.cc \ + dnsrecords.cc dnswriter.cc dnswriter.hh gettime.cc gettime.hh \ + iputils.cc logger.cc misc.cc nsecrecords.cc protobuf.cc \ + protobuf.hh qtype.cc rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc statbag.cc unix_utility.cc utility.hh \ + uuid-utils.hh uuid-utils.cc +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@am_dnspcap2protobuf_OBJECTS = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ base32.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ base64.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnslabeltext.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsname.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsparser.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnspcap.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnspcap2protobuf.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsrecords.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnswriter.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ gettime.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ iputils.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ logger.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ misc.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ nsecrecords.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ protobuf.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ qtype.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ rcpgenerator.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ sillyrecords.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ statbag.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ unix_utility.$(OBJEXT) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ uuid-utils.$(OBJEXT) +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@nodist_dnspcap2protobuf_OBJECTS = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsmessage.pb.$(OBJEXT) +dnspcap2protobuf_OBJECTS = $(am_dnspcap2protobuf_OBJECTS) \ + $(nodist_dnspcap2protobuf_OBJECTS) +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnspcap2protobuf_DEPENDENCIES = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(am__DEPENDENCIES_1) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(am__DEPENDENCIES_1) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(am__DEPENDENCIES_1) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(am__DEPENDENCIES_1) +dnspcap2protobuf_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(dnspcap2protobuf_LDFLAGS) \ + $(LDFLAGS) -o $@ +am_dnsreplay_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnspcap.$(OBJEXT) dnsrecords.$(OBJEXT) dnsreplay.$(OBJEXT) \ + dnswriter.$(OBJEXT) ednsoptions.$(OBJEXT) ednssubnet.$(OBJEXT) \ + iputils.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) +dnsreplay_OBJECTS = $(am_dnsreplay_OBJECTS) +dnsreplay_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +dnsreplay_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsreplay_LDFLAGS) $(LDFLAGS) -o $@ +am_dnsscan_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnspcap.$(OBJEXT) dnsrecords.$(OBJEXT) dnsscan.$(OBJEXT) \ + dnswriter.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) +dnsscan_OBJECTS = $(am_dnsscan_OBJECTS) +dnsscan_DEPENDENCIES = $(am__DEPENDENCIES_1) +dnsscan_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsscan_LDFLAGS) $(LDFLAGS) -o $@ +am_dnsscope_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns.$(OBJEXT) dnslabeltext.$(OBJEXT) \ + dnsname.$(OBJEXT) dnsparser.$(OBJEXT) dnspcap.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnsscope.$(OBJEXT) dnswriter.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) statnode.$(OBJEXT) unix_utility.$(OBJEXT) +dnsscope_OBJECTS = $(am_dnsscope_OBJECTS) +dnsscope_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +dnsscope_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnsscope_LDFLAGS) $(LDFLAGS) -o $@ +am_dnstcpbench_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnstcpbench.$(OBJEXT) dnswriter.$(OBJEXT) \ + iputils.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) threadname.$(OBJEXT) \ + unix_utility.$(OBJEXT) +dnstcpbench_OBJECTS = $(am_dnstcpbench_OBJECTS) +dnstcpbench_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +dnstcpbench_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnstcpbench_LDFLAGS) $(LDFLAGS) -o $@ +am_dnswasher_OBJECTS = base64.$(OBJEXT) dnslabeltext.$(OBJEXT) \ + dnsname.$(OBJEXT) dnspcap.$(OBJEXT) dnswasher.$(OBJEXT) \ + ipcipher.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + qtype.$(OBJEXT) statbag.$(OBJEXT) unix_utility.$(OBJEXT) +dnswasher_OBJECTS = $(am_dnswasher_OBJECTS) +dnswasher_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +dnswasher_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(dnswasher_LDFLAGS) $(LDFLAGS) -o $@ +am_dumresp_OBJECTS = dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + dumresp.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) qtype.$(OBJEXT) +dumresp_OBJECTS = $(am_dumresp_OBJECTS) +dumresp_LDADD = $(LDADD) +am__fuzz_target_dnsdistcache_SOURCES_DIST = fuzz_dnsdistcache.cc \ + dnsdist-cache.cc dnsdist-cache.hh dnsdist-ecs.cc \ + dnsdist-ecs.hh dnslabeltext.cc dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh dnswriter.cc dnswriter.hh doh.hh \ + ednsoptions.cc ednsoptions.hh ednssubnet.cc ednssubnet.hh \ + iputils.cc iputils.hh misc.cc misc.hh packetcache.hh qtype.cc \ + qtype.hh +@FUZZ_TARGETS_TRUE@am_fuzz_target_dnsdistcache_OBJECTS = \ +@FUZZ_TARGETS_TRUE@ fuzz_dnsdistcache.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnsdist-cache.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnsdist-ecs.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnsparser.$(OBJEXT) dnswriter.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ ednsoptions.$(OBJEXT) ednssubnet.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ iputils.$(OBJEXT) misc.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ qtype.$(OBJEXT) +fuzz_target_dnsdistcache_OBJECTS = \ + $(am_fuzz_target_dnsdistcache_OBJECTS) +@FUZZ_TARGETS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +fuzz_target_dnsdistcache_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(fuzz_target_dnsdistcache_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__fuzz_target_moadnsparser_SOURCES_DIST = fuzz_moadnsparser.cc \ + base32.cc base32.hh base64.cc base64.hh dnslabeltext.cc \ + dnsname.cc dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnsrecords.hh dnswriter.cc dnswriter.hh logger.cc logger.hh \ + misc.cc misc.hh nsecrecords.cc qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh sillyrecords.cc statbag.cc \ + statbag.hh unix_utility.cc utility.hh +@FUZZ_TARGETS_TRUE@am_fuzz_target_moadnsparser_OBJECTS = \ +@FUZZ_TARGETS_TRUE@ fuzz_moadnsparser.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ base32.$(OBJEXT) base64.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnswriter.$(OBJEXT) logger.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ unix_utility.$(OBJEXT) +fuzz_target_moadnsparser_OBJECTS = \ + $(am_fuzz_target_moadnsparser_OBJECTS) +fuzz_target_moadnsparser_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(fuzz_target_moadnsparser_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__fuzz_target_packetcache_SOURCES_DIST = fuzz_packetcache.cc \ + dnslabeltext.cc dnsname.cc dnsname.hh ednsoptions.cc \ + ednsoptions.hh misc.cc misc.hh packetcache.hh qtype.cc \ + qtype.hh statbag.cc statbag.hh +@FUZZ_TARGETS_TRUE@am_fuzz_target_packetcache_OBJECTS = \ +@FUZZ_TARGETS_TRUE@ fuzz_packetcache.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ ednsoptions.$(OBJEXT) misc.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ qtype.$(OBJEXT) statbag.$(OBJEXT) +fuzz_target_packetcache_OBJECTS = \ + $(am_fuzz_target_packetcache_OBJECTS) +fuzz_target_packetcache_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(fuzz_target_packetcache_LDFLAGS) \ + $(LDFLAGS) -o $@ +am__fuzz_target_zoneparsertng_SOURCES_DIST = fuzz_zoneparsertng.cc \ + base32.cc base32.hh base64.cc base64.hh dnslabeltext.cc \ + dnsname.cc dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnsrecords.hh dnswriter.cc dnswriter.hh logger.cc logger.hh \ + misc.cc misc.hh nsecrecords.cc qtype.cc qtype.hh \ + rcpgenerator.cc rcpgenerator.hh sillyrecords.cc statbag.cc \ + statbag.hh unix_utility.cc utility.hh zoneparser-tng.cc \ + zoneparser-tng.hh +@FUZZ_TARGETS_TRUE@am_fuzz_target_zoneparsertng_OBJECTS = \ +@FUZZ_TARGETS_TRUE@ fuzz_zoneparsertng.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ base32.$(OBJEXT) base64.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ dnswriter.$(OBJEXT) logger.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ unix_utility.$(OBJEXT) \ +@FUZZ_TARGETS_TRUE@ zoneparser-tng.$(OBJEXT) +fuzz_target_zoneparsertng_OBJECTS = \ + $(am_fuzz_target_zoneparsertng_OBJECTS) +fuzz_target_zoneparsertng_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(fuzz_target_zoneparsertng_LDFLAGS) $(LDFLAGS) -o $@ +am__ixfrdist_SOURCES_DIST = arguments.cc base32.cc base64.cc base64.hh \ + dns.cc dns_random_urandom.cc dns_random.hh dnslabeltext.cc \ + dnsname.cc dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.hh iputils.cc ixfr.cc ixfr.hh \ + ixfrdist.cc ixfrutils.cc ixfrutils.hh ixfrdist-stats.hh \ + ixfrdist-stats.cc ixfrdist-web.hh ixfrdist-web.cc logger.cc \ + logger.hh misc.cc misc.hh mplexer.hh nsecrecords.cc qtype.cc \ + rcpgenerator.cc rcpgenerator.hh resolver.cc pollmplexer.cc \ + sillyrecords.cc sstuff.hh statbag.cc threadname.hh \ + threadname.cc tsigverifier.cc tsigverifier.hh unix_utility.cc \ + uuid-utils.hh uuid-utils.cc webserver.hh webserver.cc \ + zoneparser-tng.cc pkcs11signers.cc pkcs11signers.hh \ + kqueuemplexer.cc epollmplexer.cc devpollmplexer.cc \ + portsmplexer.cc +@PKCS11_TRUE@am__objects_1 = pkcs11signers.$(OBJEXT) +@HAVE_FREEBSD_TRUE@am__objects_2 = kqueuemplexer.$(OBJEXT) +@HAVE_LINUX_TRUE@am__objects_3 = epollmplexer.$(OBJEXT) +@HAVE_SOLARIS_TRUE@am__objects_4 = devpollmplexer.$(OBJEXT) \ +@HAVE_SOLARIS_TRUE@ portsmplexer.$(OBJEXT) +am_ixfrdist_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns.$(OBJEXT) dns_random_urandom.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + gss_context.$(OBJEXT) iputils.$(OBJEXT) ixfr.$(OBJEXT) \ + ixfrdist.$(OBJEXT) ixfrutils.$(OBJEXT) \ + ixfrdist-stats.$(OBJEXT) ixfrdist-web.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) resolver.$(OBJEXT) \ + pollmplexer.$(OBJEXT) sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + threadname.$(OBJEXT) tsigverifier.$(OBJEXT) \ + unix_utility.$(OBJEXT) uuid-utils.$(OBJEXT) \ + webserver.$(OBJEXT) zoneparser-tng.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) +ixfrdist_OBJECTS = $(am_ixfrdist_OBJECTS) +@PKCS11_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@GSS_TSIG_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +ixfrdist_DEPENDENCIES = $(am__DEPENDENCIES_1) $(JSON11_LIBS) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +ixfrdist_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(ixfrdist_LDFLAGS) $(LDFLAGS) -o $@ +am__ixplore_SOURCES_DIST = arguments.cc base32.cc base64.cc base64.hh \ + dns.cc dns_random_urandom.cc dns_random.hh dnslabeltext.cc \ + dnsname.cc dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.cc logger.cc misc.cc misc.hh \ + nsecrecords.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + resolver.cc ixfr.cc ixfr.hh ixfrutils.cc ixfrutils.hh \ + ixplore.cc sillyrecords.cc sstuff.hh statbag.cc \ + tsigverifier.cc tsigverifier.hh unix_utility.cc \ + zoneparser-tng.cc pkcs11signers.cc pkcs11signers.hh +am_ixplore_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns.$(OBJEXT) dns_random_urandom.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + gss_context.$(OBJEXT) iputils.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) resolver.$(OBJEXT) ixfr.$(OBJEXT) \ + ixfrutils.$(OBJEXT) ixplore.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) tsigverifier.$(OBJEXT) \ + unix_utility.$(OBJEXT) zoneparser-tng.$(OBJEXT) \ + $(am__objects_1) +ixplore_OBJECTS = $(am_ixplore_OBJECTS) +ixplore_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +ixplore_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(ixplore_LDFLAGS) $(LDFLAGS) -o $@ +am_kvresp_OBJECTS = dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) \ + kvresp.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) qtype.$(OBJEXT) +kvresp_OBJECTS = $(am_kvresp_OBJECTS) +kvresp_LDADD = $(LDADD) +am_nproxy_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nproxy.$(OBJEXT) nsecrecords.$(OBJEXT) \ + pollmplexer.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) +nproxy_OBJECTS = $(am_nproxy_OBJECTS) +nproxy_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +nproxy_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(nproxy_LDFLAGS) $(LDFLAGS) -o $@ +am__nsec3dig_SOURCES_DIST = base32.cc base64.cc base64.hh dnsname.cc \ + dnsname.hh dnslabeltext.cc dnsparser.cc dnsparser.hh \ + dnsrecords.cc dnssecinfra.cc dnswriter.cc dnswriter.hh \ + gss_context.cc gss_context.hh iputils.cc logger.cc misc.cc \ + misc.hh nsec3dig.cc nsecrecords.cc qtype.cc rcpgenerator.cc \ + rcpgenerator.hh sillyrecords.cc sstuff.hh statbag.cc \ + unix_utility.cc pkcs11signers.cc pkcs11signers.hh +am_nsec3dig_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnsname.$(OBJEXT) dnslabeltext.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + gss_context.$(OBJEXT) iputils.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsec3dig.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) $(am__objects_1) +nsec3dig_OBJECTS = $(am_nsec3dig_OBJECTS) +nsec3dig_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +nsec3dig_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(nsec3dig_LDFLAGS) $(LDFLAGS) -o $@ +am_pdns_control_OBJECTS = arguments.$(OBJEXT) dynloader.$(OBJEXT) \ + dynmessenger.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + qtype.$(OBJEXT) statbag.$(OBJEXT) unix_utility.$(OBJEXT) \ + dnsname.$(OBJEXT) dnslabeltext.$(OBJEXT) +pdns_control_OBJECTS = $(am_pdns_control_OBJECTS) +pdns_control_LDADD = $(LDADD) +am_pdns_notify_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns.$(OBJEXT) dnslabeltext.$(OBJEXT) \ + dnsname.$(OBJEXT) dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnswriter.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + notify.$(OBJEXT) nsecrecords.$(OBJEXT) pollmplexer.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) dns_random.$(OBJEXT) +pdns_notify_OBJECTS = $(am_pdns_notify_OBJECTS) +@LIBSODIUM_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1) +pdns_notify_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_5) +pdns_notify_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(pdns_notify_LDFLAGS) $(LDFLAGS) -o $@ +am__pdns_server_SOURCES_DIST = arguments.cc arguments.hh ascii.hh \ + auth-carbon.cc auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh auth-querycache.cc \ + auth-querycache.hh backends/gsql/gsqlbackend.cc \ + backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base32.cc \ + base32.hh base64.cc base64.hh bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l bindparser.cc cachecleaner.hh circular_buffer.hh \ + comment.hh common_startup.cc common_startup.hh communicator.cc \ + communicator.hh dbdnsseckeeper.cc digests.hh distributor.hh \ + dns.cc dns.hh dns_random.cc dns_random.hh dnsbackend.cc \ + dnsbackend.hh dnslabeltext.cc dnsname.cc dnsname.hh \ + dnspacket.cc dnspacket.hh dnsparser.cc dnsproxy.cc dnsproxy.hh \ + dnsrecords.cc dnsrecords.hh dnssecinfra.cc dnssecinfra.hh \ + dnsseckeeper.hh dnssecsigner.cc dnswriter.cc dynhandler.cc \ + dynhandler.hh dynlistener.cc dynlistener.hh dynmessenger.hh \ + ednsoptions.cc ednsoptions.hh ednssubnet.cc ednssubnet.hh \ + gss_context.cc gss_context.hh iputils.cc iputils.hh ixfr.cc \ + ixfr.hh json.cc json.hh lock.hh logger.cc logger.hh \ + lua-base4.cc lua-base4.hh lua-auth4.cc lua-auth4.hh \ + mastercommunicator.cc misc.cc misc.hh nameserver.cc \ + nameserver.hh namespaces.hh nsecrecords.cc opensslsigners.cc \ + opensslsigners.hh packetcache.hh packethandler.cc \ + packethandler.hh pdnsexception.hh qtype.cc qtype.hh \ + rcpgenerator.cc receiver.cc resolver.cc resolver.hh \ + responsestats.cc responsestats.hh responsestats-auth.cc \ + rfc2136handler.cc secpoll-auth.cc secpoll-auth.hh \ + serialtweaker.cc sha.hh signingpipe.cc signingpipe.hh \ + sillyrecords.cc slavecommunicator.cc statbag.cc statbag.hh \ + stubresolver.cc stubresolver.hh tcpreceiver.cc tcpreceiver.hh \ + threadname.hh threadname.cc tsigverifier.cc tsigverifier.hh \ + tsigutils.hh tsigutils.cc tkey.cc ueberbackend.cc \ + ueberbackend.hh uuid-utils.hh uuid-utils.cc unix_semaphore.cc \ + unix_utility.cc utility.hh version.cc version.hh webserver.cc \ + webserver.hh ws-api.cc ws-api.hh ws-auth.cc ws-auth.hh \ + zoneparser-tng.cc lua-record.cc minicurl.cc minicurl.hh \ + sodiumsigners.cc decafsigners.cc ssqlite3.cc ssqlite3.hh \ + pkcs11signers.cc pkcs11signers.hh +am__dirstamp = $(am__leading_dot)dirstamp +@HAVE_LUA_RECORDS_TRUE@am__objects_5 = lua-record.$(OBJEXT) \ +@HAVE_LUA_RECORDS_TRUE@ minicurl.$(OBJEXT) +@LIBSODIUM_TRUE@am__objects_6 = sodiumsigners.$(OBJEXT) +@LIBDECAF_TRUE@am__objects_7 = decafsigners.$(OBJEXT) +@SQLITE3_TRUE@am__objects_8 = ssqlite3.$(OBJEXT) +am_pdns_server_OBJECTS = arguments.$(OBJEXT) auth-carbon.$(OBJEXT) \ + auth-caches.$(OBJEXT) auth-packetcache.$(OBJEXT) \ + auth-querycache.$(OBJEXT) backends/gsql/gsqlbackend.$(OBJEXT) \ + base32.$(OBJEXT) base64.$(OBJEXT) bindlexer.$(OBJEXT) \ + bindparser.$(OBJEXT) common_startup.$(OBJEXT) \ + communicator.$(OBJEXT) dbdnsseckeeper.$(OBJEXT) dns.$(OBJEXT) \ + dns_random.$(OBJEXT) dnsbackend.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnspacket.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnsproxy.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnssecinfra.$(OBJEXT) dnssecsigner.$(OBJEXT) \ + dnswriter.$(OBJEXT) dynhandler.$(OBJEXT) dynlistener.$(OBJEXT) \ + ednsoptions.$(OBJEXT) ednssubnet.$(OBJEXT) \ + gss_context.$(OBJEXT) iputils.$(OBJEXT) ixfr.$(OBJEXT) \ + json.$(OBJEXT) logger.$(OBJEXT) lua-base4.$(OBJEXT) \ + lua-auth4.$(OBJEXT) mastercommunicator.$(OBJEXT) \ + misc.$(OBJEXT) nameserver.$(OBJEXT) nsecrecords.$(OBJEXT) \ + opensslsigners.$(OBJEXT) packethandler.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) receiver.$(OBJEXT) \ + resolver.$(OBJEXT) responsestats.$(OBJEXT) \ + responsestats-auth.$(OBJEXT) rfc2136handler.$(OBJEXT) \ + secpoll-auth.$(OBJEXT) serialtweaker.$(OBJEXT) \ + signingpipe.$(OBJEXT) sillyrecords.$(OBJEXT) \ + slavecommunicator.$(OBJEXT) statbag.$(OBJEXT) \ + stubresolver.$(OBJEXT) tcpreceiver.$(OBJEXT) \ + threadname.$(OBJEXT) tsigverifier.$(OBJEXT) \ + tsigutils.$(OBJEXT) tkey.$(OBJEXT) ueberbackend.$(OBJEXT) \ + uuid-utils.$(OBJEXT) unix_semaphore.$(OBJEXT) \ + unix_utility.$(OBJEXT) version.$(OBJEXT) webserver.$(OBJEXT) \ + ws-api.$(OBJEXT) ws-auth.$(OBJEXT) zoneparser-tng.$(OBJEXT) \ + $(am__objects_5) $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) $(am__objects_1) +pdns_server_OBJECTS = $(am_pdns_server_OBJECTS) +@HAVE_LUA_RECORDS_TRUE@am__DEPENDENCIES_6 = $(am__DEPENDENCIES_1) +@LIBDECAF_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1) +@SQLITE3_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_1) +@ORACLE_TRUE@am__DEPENDENCIES_9 = $(am__DEPENDENCIES_1) +@LUA_TRUE@am__DEPENDENCIES_10 = $(am__DEPENDENCIES_1) +pdns_server_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(JSON11_LIBS) $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_6) $(am__DEPENDENCIES_5) \ + $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_8) \ + $(am__DEPENDENCIES_9) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_10) $(am__DEPENDENCIES_4) +pdns_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(pdns_server_LDFLAGS) $(LDFLAGS) -o $@ +am__pdnsutil_SOURCES_DIST = arguments.cc auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh auth-querycache.cc \ + auth-querycache.hh backends/gsql/gsqlbackend.cc \ + backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base32.cc \ + base64.cc base64.hh bindlexer.l bindparser.yy cachecleaner.hh \ + circular_buffer.hh dbdnsseckeeper.cc dnsbackend.cc dns.cc \ + dnslabeltext.cc dnsname.cc dnsname.hh dnspacket.cc \ + dnsparser.cc dnsparser.hh dns_random.cc dnsrecords.cc \ + dnssecinfra.cc dnssecinfra.hh dnssecsigner.cc dnswriter.cc \ + dnswriter.hh dynlistener.cc ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc gss_context.cc gss_context.hh ipcipher.cc \ + ipcipher.hh iputils.cc iputils.hh json.cc logger.cc \ + lua-auth4.cc lua-auth4.hh lua-base4.cc lua-base4.hh misc.cc \ + misc.hh nsecrecords.cc opensslsigners.cc opensslsigners.hh \ + pdnsutil.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + serialtweaker.cc signingpipe.cc sillyrecords.cc sstuff.hh \ + statbag.cc stubresolver.cc stubresolver.hh threadname.hh \ + threadname.cc tsigutils.hh tsigutils.cc ueberbackend.cc \ + unix_utility.cc zoneparser-tng.cc sodiumsigners.cc \ + decafsigners.cc ssqlite3.cc ssqlite3.hh pkcs11signers.cc \ + pkcs11signers.hh +am_pdnsutil_OBJECTS = arguments.$(OBJEXT) auth-caches.$(OBJEXT) \ + auth-packetcache.$(OBJEXT) auth-querycache.$(OBJEXT) \ + backends/gsql/gsqlbackend.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) bindlexer.$(OBJEXT) bindparser.$(OBJEXT) \ + dbdnsseckeeper.$(OBJEXT) dnsbackend.$(OBJEXT) dns.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnspacket.$(OBJEXT) \ + dnsparser.$(OBJEXT) dns_random.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnssecinfra.$(OBJEXT) dnssecsigner.$(OBJEXT) \ + dnswriter.$(OBJEXT) dynlistener.$(OBJEXT) \ + ednsoptions.$(OBJEXT) ednssubnet.$(OBJEXT) \ + gss_context.$(OBJEXT) ipcipher.$(OBJEXT) iputils.$(OBJEXT) \ + json.$(OBJEXT) logger.$(OBJEXT) lua-auth4.$(OBJEXT) \ + lua-base4.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + opensslsigners.$(OBJEXT) pdnsutil.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) serialtweaker.$(OBJEXT) \ + signingpipe.$(OBJEXT) sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + stubresolver.$(OBJEXT) threadname.$(OBJEXT) \ + tsigutils.$(OBJEXT) ueberbackend.$(OBJEXT) \ + unix_utility.$(OBJEXT) zoneparser-tng.$(OBJEXT) \ + $(am__objects_6) $(am__objects_7) $(am__objects_8) \ + $(am__objects_1) +pdnsutil_OBJECTS = $(am_pdnsutil_OBJECTS) +pdnsutil_DEPENDENCIES = $(am__DEPENDENCIES_1) $(JSON11_LIBS) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_7) \ + $(am__DEPENDENCIES_8) $(am__DEPENDENCIES_9) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_10) \ + $(am__DEPENDENCIES_4) +pdnsutil_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(pdnsutil_LDFLAGS) $(LDFLAGS) -o $@ +am__saxfr_SOURCES_DIST = base32.cc base64.cc base64.hh \ + dns_random_urandom.cc dns_random.hh dnslabeltext.cc dnsname.cc \ + dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.cc logger.cc misc.cc misc.hh \ + nsecrecords.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + saxfr.cc sillyrecords.cc sstuff.hh statbag.cc unix_utility.cc \ + pkcs11signers.cc pkcs11signers.hh +am_saxfr_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dns_random_urandom.$(OBJEXT) dnslabeltext.$(OBJEXT) \ + dnsname.$(OBJEXT) dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) \ + dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + gss_context.$(OBJEXT) iputils.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) saxfr.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) $(am__objects_1) +saxfr_OBJECTS = $(am_saxfr_OBJECTS) +saxfr_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +saxfr_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(saxfr_LDFLAGS) $(LDFLAGS) -o $@ +am__sdig_SOURCES_DIST = base32.cc base64.cc base64.hh dns.cc \ + dnslabeltext.cc dnsname.cc dnsname.hh dnsparser.cc \ + dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \ + ednssubnet.cc iputils.cc logger.cc misc.cc misc.hh \ + nsecrecords.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + sdig.cc sillyrecords.cc sstuff.hh statbag.cc unix_utility.cc \ + minicurl.cc minicurl.hh +@HAVE_LIBCURL_TRUE@am__objects_9 = minicurl.$(OBJEXT) +am_sdig_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) dns.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) ednssubnet.$(OBJEXT) \ + iputils.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + sdig.$(OBJEXT) sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + unix_utility.$(OBJEXT) $(am__objects_9) +sdig_OBJECTS = $(am_sdig_OBJECTS) +@HAVE_LIBCURL_TRUE@am__DEPENDENCIES_11 = $(am__DEPENDENCIES_1) +sdig_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_11) +sdig_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(sdig_LDFLAGS) $(LDFLAGS) -o $@ +am_speedtest_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + speedtest.$(OBJEXT) statbag.$(OBJEXT) unix_utility.$(OBJEXT) \ + iputils.$(OBJEXT) +speedtest_OBJECTS = $(am_speedtest_OBJECTS) +speedtest_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +speedtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(speedtest_LDFLAGS) $(LDFLAGS) -o $@ +am_stubquery_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns_random_urandom.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) iputils.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) stubresolver.$(OBJEXT) stubquery.$(OBJEXT) \ + unix_utility.$(OBJEXT) +stubquery_OBJECTS = $(am_stubquery_OBJECTS) +stubquery_DEPENDENCIES = $(am__DEPENDENCIES_1) +stubquery_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(stubquery_LDFLAGS) $(LDFLAGS) -o $@ +am__testrunner_SOURCES_DIST = arguments.cc auth-caches.cc \ + auth-caches.hh auth-packetcache.cc auth-packetcache.hh \ + auth-querycache.cc auth-querycache.hh base32.cc base64.cc \ + bindlexer.l bindparser.yy dbdnsseckeeper.cc dns.cc \ + dns_random.cc dnsbackend.cc dnslabeltext.cc dnsname.cc \ + dnsname.hh dnspacket.cc dnsparser.hh dnsparser.cc \ + dnsrecords.cc dnssecinfra.cc dnssecsigner.cc dnswriter.cc \ + ednsoptions.cc ednsoptions.hh ednscookies.cc ednscookies.hh \ + ednssubnet.cc gettime.cc gettime.hh gss_context.cc \ + gss_context.hh ipcipher.cc ipcipher.hh iputils.cc ixfr.cc \ + ixfr.hh logger.cc lua-auth4.hh lua-auth4.cc lua-base4.hh \ + lua-base4.cc stubresolver.hh stubresolver.cc misc.cc \ + nameserver.cc nsecrecords.cc opensslsigners.cc \ + opensslsigners.hh pollmplexer.cc qtype.cc rcpgenerator.cc \ + responsestats.cc responsestats-auth.cc sillyrecords.cc \ + statbag.cc test-arguments_cc.cc test-base32_cc.cc \ + test-base64_cc.cc test-bindparser_cc.cc test-common.hh \ + test-dnsrecordcontent.cc test-digests_hh.cc \ + test-distributor_hh.cc test-dns_random_hh.cc \ + test-dnsname_cc.cc test-dnsparser_cc.cc test-dnsparser_hh.cc \ + test-dnsrecords_cc.cc test-dnswriter_cc.cc test-ipcrypt_cc.cc \ + test-iputils_hh.cc test-ixfr_cc.cc test-lock_hh.cc \ + test-lua_auth4_cc.cc test-misc_hh.cc test-mplexer.cc \ + test-nameserver_cc.cc test-packetcache_cc.cc \ + test-packetcache_hh.cc test-rcpgenerator_cc.cc test-signers.cc \ + test-sha_hh.cc test-statbag_cc.cc test-tsig.cc \ + test-zoneparser_tng_cc.cc testrunner.cc threadname.hh \ + threadname.cc tsigverifier.cc tsigverifier.hh ueberbackend.cc \ + unix_utility.cc zoneparser-tng.cc zoneparser-tng.hh \ + pkcs11signers.cc pkcs11signers.hh sodiumsigners.cc \ + decafsigners.cc kqueuemplexer.cc epollmplexer.cc \ + devpollmplexer.cc portsmplexer.cc +am_testrunner_OBJECTS = arguments.$(OBJEXT) auth-caches.$(OBJEXT) \ + auth-packetcache.$(OBJEXT) auth-querycache.$(OBJEXT) \ + base32.$(OBJEXT) base64.$(OBJEXT) bindlexer.$(OBJEXT) \ + bindparser.$(OBJEXT) dbdnsseckeeper.$(OBJEXT) dns.$(OBJEXT) \ + dns_random.$(OBJEXT) dnsbackend.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnspacket.$(OBJEXT) \ + dnsparser.$(OBJEXT) dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) \ + dnssecsigner.$(OBJEXT) dnswriter.$(OBJEXT) \ + ednsoptions.$(OBJEXT) ednscookies.$(OBJEXT) \ + ednssubnet.$(OBJEXT) gettime.$(OBJEXT) gss_context.$(OBJEXT) \ + ipcipher.$(OBJEXT) iputils.$(OBJEXT) ixfr.$(OBJEXT) \ + logger.$(OBJEXT) lua-auth4.$(OBJEXT) lua-base4.$(OBJEXT) \ + stubresolver.$(OBJEXT) misc.$(OBJEXT) nameserver.$(OBJEXT) \ + nsecrecords.$(OBJEXT) opensslsigners.$(OBJEXT) \ + pollmplexer.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + responsestats.$(OBJEXT) responsestats-auth.$(OBJEXT) \ + sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + test-arguments_cc.$(OBJEXT) test-base32_cc.$(OBJEXT) \ + test-base64_cc.$(OBJEXT) test-bindparser_cc.$(OBJEXT) \ + test-dnsrecordcontent.$(OBJEXT) test-digests_hh.$(OBJEXT) \ + test-distributor_hh.$(OBJEXT) test-dns_random_hh.$(OBJEXT) \ + test-dnsname_cc.$(OBJEXT) test-dnsparser_cc.$(OBJEXT) \ + test-dnsparser_hh.$(OBJEXT) test-dnsrecords_cc.$(OBJEXT) \ + test-dnswriter_cc.$(OBJEXT) test-ipcrypt_cc.$(OBJEXT) \ + test-iputils_hh.$(OBJEXT) test-ixfr_cc.$(OBJEXT) \ + test-lock_hh.$(OBJEXT) test-lua_auth4_cc.$(OBJEXT) \ + test-misc_hh.$(OBJEXT) test-mplexer.$(OBJEXT) \ + test-nameserver_cc.$(OBJEXT) test-packetcache_cc.$(OBJEXT) \ + test-packetcache_hh.$(OBJEXT) test-rcpgenerator_cc.$(OBJEXT) \ + test-signers.$(OBJEXT) test-sha_hh.$(OBJEXT) \ + test-statbag_cc.$(OBJEXT) test-tsig.$(OBJEXT) \ + test-zoneparser_tng_cc.$(OBJEXT) testrunner.$(OBJEXT) \ + threadname.$(OBJEXT) tsigverifier.$(OBJEXT) \ + ueberbackend.$(OBJEXT) unix_utility.$(OBJEXT) \ + zoneparser-tng.$(OBJEXT) $(am__objects_1) $(am__objects_6) \ + $(am__objects_7) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) +testrunner_OBJECTS = $(am_testrunner_OBJECTS) +testrunner_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_5) \ + $(am__DEPENDENCIES_7) +testrunner_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(testrunner_LDFLAGS) $(LDFLAGS) -o $@ +am__toysdig_SOURCES_DIST = base32.cc base64.cc base64.hh \ + dns_random_urandom.cc dnsname.cc dnsname.hh dnslabeltext.cc \ + dnsparser.cc dnsparser.hh dnsrecords.cc dnssecinfra.cc \ + dnswriter.cc dnswriter.hh ednssubnet.cc ednssubnet.hh \ + filterpo.hh gss_context.cc gss_context.hh iputils.cc logger.cc \ + misc.cc misc.hh nsecrecords.cc opensslsigners.cc \ + opensslsigners.hh qtype.cc root-dnssec.hh rcpgenerator.cc \ + rcpgenerator.hh rec-lua-conf.hh recursor_cache.hh sholder.hh \ + sillyrecords.cc sortlist.hh sstuff.hh statbag.cc toysdig.cc \ + unix_utility.cc validate.cc validate.hh pkcs11signers.cc \ + pkcs11signers.hh +am_toysdig_OBJECTS = base32.$(OBJEXT) base64.$(OBJEXT) \ + dns_random_urandom.$(OBJEXT) dnsname.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + ednssubnet.$(OBJEXT) gss_context.$(OBJEXT) iputils.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + opensslsigners.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) toysdig.$(OBJEXT) unix_utility.$(OBJEXT) \ + validate.$(OBJEXT) $(am__objects_1) +toysdig_OBJECTS = $(am_toysdig_OBJECTS) +toysdig_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4) \ + $(am__DEPENDENCIES_3) +toysdig_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(toysdig_LDFLAGS) $(LDFLAGS) -o $@ +am__tsig_tests_SOURCES_DIST = arguments.cc base32.cc base64.cc \ + base64.hh digests.hh dns.cc dns_random_urandom.cc \ + dns_random.hh dnslabeltext.cc dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh dnsrecords.cc dnssecinfra.cc \ + dnswriter.cc dnswriter.hh gss_context.cc gss_context.hh \ + logger.cc misc.cc misc.hh nsecrecords.cc qtype.cc \ + rcpgenerator.cc rcpgenerator.hh resolver.cc sillyrecords.cc \ + sstuff.hh statbag.cc tsig-tests.cc tsigverifier.cc \ + tsigverifier.hh unix_utility.cc pkcs11signers.cc \ + pkcs11signers.hh +am_tsig_tests_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) dns.$(OBJEXT) dns_random_urandom.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnssecinfra.$(OBJEXT) dnswriter.$(OBJEXT) \ + gss_context.$(OBJEXT) logger.$(OBJEXT) misc.$(OBJEXT) \ + nsecrecords.$(OBJEXT) qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) \ + resolver.$(OBJEXT) sillyrecords.$(OBJEXT) statbag.$(OBJEXT) \ + tsig-tests.$(OBJEXT) tsigverifier.$(OBJEXT) \ + unix_utility.$(OBJEXT) $(am__objects_1) +tsig_tests_OBJECTS = $(am_tsig_tests_OBJECTS) +tsig_tests_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_4) +tsig_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(tsig_tests_LDFLAGS) $(LDFLAGS) -o $@ +am_zone2json_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) bindlexer.$(OBJEXT) bindparser.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsname.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) zone2json.$(OBJEXT) \ + zoneparser-tng.$(OBJEXT) +zone2json_OBJECTS = $(am_zone2json_OBJECTS) +zone2json_DEPENDENCIES = $(am__DEPENDENCIES_1) $(JSON11_LIBS) +zone2json_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(zone2json_LDFLAGS) $(LDFLAGS) -o $@ +am_zone2ldap_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) bindlexer.$(OBJEXT) bindparser.$(OBJEXT) \ + dns_random_urandom.$(OBJEXT) dnsname.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) logger.$(OBJEXT) \ + misc.$(OBJEXT) nsecrecords.$(OBJEXT) qtype.$(OBJEXT) \ + rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) zone2ldap.$(OBJEXT) \ + zoneparser-tng.$(OBJEXT) +zone2ldap_OBJECTS = $(am_zone2ldap_OBJECTS) +zone2ldap_DEPENDENCIES = $(am__DEPENDENCIES_1) +zone2ldap_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(zone2ldap_LDFLAGS) $(LDFLAGS) -o $@ +am_zone2sql_OBJECTS = arguments.$(OBJEXT) base32.$(OBJEXT) \ + base64.$(OBJEXT) bindlexer.$(OBJEXT) bindparser.$(OBJEXT) \ + dns.$(OBJEXT) dns_random_urandom.$(OBJEXT) dnsname.$(OBJEXT) \ + dnslabeltext.$(OBJEXT) dnsparser.$(OBJEXT) \ + dnsrecords.$(OBJEXT) dnswriter.$(OBJEXT) json.$(OBJEXT) \ + logger.$(OBJEXT) misc.$(OBJEXT) nsecrecords.$(OBJEXT) \ + qtype.$(OBJEXT) rcpgenerator.$(OBJEXT) sillyrecords.$(OBJEXT) \ + statbag.$(OBJEXT) unix_utility.$(OBJEXT) zone2sql.$(OBJEXT) \ + zoneparser-tng.$(OBJEXT) +zone2sql_OBJECTS = $(am_zone2sql_OBJECTS) +zone2sql_DEPENDENCIES = $(am__DEPENDENCIES_1) $(JSON11_LIBS) +zone2sql_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(zone2sql_LDFLAGS) $(LDFLAGS) -o $@ +SCRIPTS = $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +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_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) +LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS) +AM_V_LEX = $(am__v_LEX_@AM_V@) +am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) +am__v_LEX_0 = @echo " LEX " $@; +am__v_LEX_1 = +YLWRAP = $(top_srcdir)/build-aux/ylwrap +am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ + -e s/c++$$/h++/ -e s/c$$/h/ +YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) +LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS) +AM_V_YACC = $(am__v_YACC_@AM_V@) +am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) +am__v_YACC_0 = @echo " YACC " $@; +am__v_YACC_1 = +SOURCES = $(calidns_SOURCES) $(comfun_SOURCES) $(dnsbulktest_SOURCES) \ + $(dnsdemog_SOURCES) $(dnsgram_SOURCES) \ + $(dnspcap2calidns_SOURCES) $(dnspcap2protobuf_SOURCES) \ + $(nodist_dnspcap2protobuf_SOURCES) $(dnsreplay_SOURCES) \ + $(dnsscan_SOURCES) $(dnsscope_SOURCES) $(dnstcpbench_SOURCES) \ + $(dnswasher_SOURCES) $(dumresp_SOURCES) \ + $(fuzz_target_dnsdistcache_SOURCES) \ + $(fuzz_target_moadnsparser_SOURCES) \ + $(fuzz_target_packetcache_SOURCES) \ + $(fuzz_target_zoneparsertng_SOURCES) $(ixfrdist_SOURCES) \ + $(ixplore_SOURCES) $(kvresp_SOURCES) $(nproxy_SOURCES) \ + $(nsec3dig_SOURCES) $(pdns_control_SOURCES) \ + $(pdns_notify_SOURCES) $(pdns_server_SOURCES) \ + $(pdnsutil_SOURCES) $(saxfr_SOURCES) $(sdig_SOURCES) \ + $(speedtest_SOURCES) $(stubquery_SOURCES) \ + $(testrunner_SOURCES) $(toysdig_SOURCES) $(tsig_tests_SOURCES) \ + $(zone2json_SOURCES) $(zone2ldap_SOURCES) $(zone2sql_SOURCES) +DIST_SOURCES = $(calidns_SOURCES) $(comfun_SOURCES) \ + $(dnsbulktest_SOURCES) $(dnsdemog_SOURCES) $(dnsgram_SOURCES) \ + $(dnspcap2calidns_SOURCES) \ + $(am__dnspcap2protobuf_SOURCES_DIST) $(dnsreplay_SOURCES) \ + $(dnsscan_SOURCES) $(dnsscope_SOURCES) $(dnstcpbench_SOURCES) \ + $(dnswasher_SOURCES) $(dumresp_SOURCES) \ + $(am__fuzz_target_dnsdistcache_SOURCES_DIST) \ + $(am__fuzz_target_moadnsparser_SOURCES_DIST) \ + $(am__fuzz_target_packetcache_SOURCES_DIST) \ + $(am__fuzz_target_zoneparsertng_SOURCES_DIST) \ + $(am__ixfrdist_SOURCES_DIST) $(am__ixplore_SOURCES_DIST) \ + $(kvresp_SOURCES) $(nproxy_SOURCES) \ + $(am__nsec3dig_SOURCES_DIST) $(pdns_control_SOURCES) \ + $(pdns_notify_SOURCES) $(am__pdns_server_SOURCES_DIST) \ + $(am__pdnsutil_SOURCES_DIST) $(am__saxfr_SOURCES_DIST) \ + $(am__sdig_SOURCES_DIST) $(speedtest_SOURCES) \ + $(stubquery_SOURCES) $(am__testrunner_SOURCES_DIST) \ + $(am__toysdig_SOURCES_DIST) $(am__tsig_tests_SOURCES_DIST) \ + $(zone2json_SOURCES) $(zone2ldap_SOURCES) $(zone2sql_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +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; }; \ + } +DATA = $(sysconf_DATA) $(systemdsystemunit_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/pdns.init.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver \ + $(top_srcdir)/build-aux/ylwrap bindlexer.c bindparser.cc \ + bindparser.hh +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/ext/json11 \ + $(YAHTTP_CFLAGS) $(LIBEDIT_CFLAGS) $(LIBCRYPTO_INCLUDES) \ + $(SYSTEMD_CFLAGS) $(YAML_CFLAGS) $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SERIALIZATION_LDFLAGS = @BOOST_SERIALIZATION_LDFLAGS@ +BOOST_SERIALIZATION_LDPATH = @BOOST_SERIALIZATION_LDPATH@ +BOOST_SERIALIZATION_LIBS = @BOOST_SERIALIZATION_LIBS@ +BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS = @BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS@ +BOOST_UNIT_TEST_FRAMEWORK_LDPATH = @BOOST_UNIT_TEST_FRAMEWORK_LDPATH@ +BOOST_UNIT_TEST_FRAMEWORK_LIBS = @BOOST_UNIT_TEST_FRAMEWORK_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_CFLAGS = @CDB_CFLAGS@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CURL = @CURL@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +DYNLINKFLAGS = @DYNLINKFLAGS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEOIP_CFLAGS = @GEOIP_CFLAGS@ +GEOIP_LIBS = @GEOIP_LIBS@ +GREP = @GREP@ +GSS_CFLAGS = @GSS_CFLAGS@ +GSS_LIBS = @GSS_LIBS@ +GSS_TSIG = @GSS_TSIG@ +HAVE_CXX11 = @HAVE_CXX11@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPCRYPT_CFLAGS = @IPCRYPT_CFLAGS@ +IPCRYPT_LIBS = @IPCRYPT_LIBS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCRYPTO_INCLUDES = @LIBCRYPTO_INCLUDES@ +LIBCRYPTO_LDFLAGS = @LIBCRYPTO_LDFLAGS@ +LIBCRYPTO_LIBS = @LIBCRYPTO_LIBS@ +LIBCURL = @LIBCURL@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBDECAF_LIBS = @LIBDECAF_LIBS@ +LIBDL = @LIBDL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_CFLAGS = @LIBZMQ_CFLAGS@ +LIBZMQ_LIBS = @LIBZMQ_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMDB_CFLAGS = @MMDB_CFLAGS@ +MMDB_LIBS = @MMDB_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_config = @MYSQL_config@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENDBX_CFLAGS = @OPENDBX_CFLAGS@ +OPENDBX_LIBS = @OPENDBX_LIBS@ +ORACLE_CFLAGS = @ORACLE_CFLAGS@ +ORACLE_LIBS = @ORACLE_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11KIT1_CFLAGS = @P11KIT1_CFLAGS@ +P11KIT1_LIBS = @P11KIT1_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGEVERSION = @PACKAGEVERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROGRAM_LDFLAGS = @PROGRAM_LDFLAGS@ +PROTOBUF_CFLAGS = @PROTOBUF_CFLAGS@ +PROTOBUF_LIBS = @PROTOBUF_LIBS@ +PROTOC = @PROTOC@ +RAGEL = @RAGEL@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +REMOTEBACKEND_ZEROMQ = @REMOTEBACKEND_ZEROMQ@ +RT_LIBS = @RT_LIBS@ +SANITIZER_FLAGS = @SANITIZER_FLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +STRIP = @STRIP@ +SYSTEMCTL = @SYSTEMCTL@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_DIR = @SYSTEMD_DIR@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEMD_MODULES_LOAD = @SYSTEMD_MODULES_LOAD@ +THREADFLAGS = @THREADFLAGS@ +UNIXODBC_CFLAGS = @UNIXODBC_CFLAGS@ +UNIXODBC_LIBS = @UNIXODBC_LIBS@ +UNIXODBC_config = @UNIXODBC_config@ +VERSION = @VERSION@ +VIRTUALENV = @VIRTUALENV@ +WARN_CFLAGS = @WARN_CFLAGS@ +YACC = @YACC@ +YAHTTP_CFLAGS = @YAHTTP_CFLAGS@ +YAHTTP_LIBS = @YAHTTP_LIBS@ +YAML_CFLAGS = @YAML_CFLAGS@ +YAML_LIBS = @YAML_LIBS@ +YFLAGS = @YFLAGS@ +_libcurl_config = @_libcurl_config@ +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@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledirs = @moduledirs@ +modulelibs = @modulelibs@ +moduleobjects = @moduleobjects@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pdns_configure_args = @pdns_configure_args@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +socketdir = @socketdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemd = @systemd@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +JSON11_LIBS = $(top_builddir)/ext/json11/libjson11.la +AM_CXXFLAGS = \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DPKGLIBDIR=\"$(pkglibdir)\" \ + -DLOCALSTATEDIR=\"$(socketdir)\" + +AM_LDFLAGS = \ + $(PROGRAM_LDFLAGS) \ + $(THREADFLAGS) + +AM_LFLAGS = -i +AM_YFLAGS = -d --verbose --debug +EXTRA_DIST = \ + dnslabeltext.rl \ + dnslabeltext.cc \ + dnsmessage.proto \ + effective_tld_names.dat \ + mtasker.cc \ + inflighter.cc \ + bind-dnssec.schema.sqlite3.sql \ + bindparser.h \ + named.conf.parsertest \ + pdns.service.in \ + ixfrdist.service.in \ + ixfrdist.example.yml \ + lua-record.cc \ + minicurl.cc \ + minicurl.hh + +BUILT_SOURCES = bind-dnssec.schema.sqlite3.sql.h bindparser.h \ + dnslabeltext.cc $(am__append_57) +CLEANFILES = *.gcda *.gcno *.gcov backends/gsql/gsqlbackend.gcda \ + backends/gsql/gsqlbackend.gcno backends/gsql/gsqlbackend.gcov \ + dnsmessage.pb.cc dnsmessage.pb.h pdns.conf-dist \ + $(am__append_71) +noinst_SCRIPTS = pdns.init +sysconf_DATA = pdns.conf-dist $(am__append_9) +pdns_server_SOURCES = arguments.cc arguments.hh ascii.hh \ + auth-carbon.cc auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh auth-querycache.cc \ + auth-querycache.hh backends/gsql/gsqlbackend.cc \ + backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base32.cc \ + base32.hh base64.cc base64.hh bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l bindparser.cc cachecleaner.hh circular_buffer.hh \ + comment.hh common_startup.cc common_startup.hh communicator.cc \ + communicator.hh dbdnsseckeeper.cc digests.hh distributor.hh \ + dns.cc dns.hh dns_random.cc dns_random.hh dnsbackend.cc \ + dnsbackend.hh dnslabeltext.cc dnsname.cc dnsname.hh \ + dnspacket.cc dnspacket.hh dnsparser.cc dnsproxy.cc dnsproxy.hh \ + dnsrecords.cc dnsrecords.hh dnssecinfra.cc dnssecinfra.hh \ + dnsseckeeper.hh dnssecsigner.cc dnswriter.cc dynhandler.cc \ + dynhandler.hh dynlistener.cc dynlistener.hh dynmessenger.hh \ + ednsoptions.cc ednsoptions.hh ednssubnet.cc ednssubnet.hh \ + gss_context.cc gss_context.hh iputils.cc iputils.hh ixfr.cc \ + ixfr.hh json.cc json.hh lock.hh logger.cc logger.hh \ + lua-base4.cc lua-base4.hh lua-auth4.cc lua-auth4.hh \ + mastercommunicator.cc misc.cc misc.hh nameserver.cc \ + nameserver.hh namespaces.hh nsecrecords.cc opensslsigners.cc \ + opensslsigners.hh packetcache.hh packethandler.cc \ + packethandler.hh pdnsexception.hh qtype.cc qtype.hh \ + rcpgenerator.cc receiver.cc resolver.cc resolver.hh \ + responsestats.cc responsestats.hh responsestats-auth.cc \ + rfc2136handler.cc secpoll-auth.cc secpoll-auth.hh \ + serialtweaker.cc sha.hh signingpipe.cc signingpipe.hh \ + sillyrecords.cc slavecommunicator.cc statbag.cc statbag.hh \ + stubresolver.cc stubresolver.hh tcpreceiver.cc tcpreceiver.hh \ + threadname.hh threadname.cc tsigverifier.cc tsigverifier.hh \ + tsigutils.hh tsigutils.cc tkey.cc ueberbackend.cc \ + ueberbackend.hh uuid-utils.hh uuid-utils.cc unix_semaphore.cc \ + unix_utility.cc utility.hh version.cc version.hh webserver.cc \ + webserver.hh ws-api.cc ws-api.hh ws-auth.cc ws-auth.hh \ + zoneparser-tng.cc $(am__append_10) $(am__append_12) \ + $(am__append_14) $(am__append_16) $(am__append_19) +pdns_server_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +EXTRA_pdns_server_DEPENDENCIES = @moduleobjects@ +pdns_server_LDADD = @moduleobjects@ @modulelibs@ $(LIBDL) \ + $(YAHTTP_LIBS) $(JSON11_LIBS) $(LIBCRYPTO_LIBS) \ + $(SYSTEMD_LIBS) $(am__append_11) $(am__append_13) \ + $(am__append_15) $(am__append_17) $(am__append_18) \ + $(am__append_20) $(am__append_21) $(am__append_22) +pdnsutil_SOURCES = arguments.cc auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh auth-querycache.cc \ + auth-querycache.hh backends/gsql/gsqlbackend.cc \ + backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base32.cc \ + base64.cc base64.hh bindlexer.l bindparser.yy cachecleaner.hh \ + circular_buffer.hh dbdnsseckeeper.cc dnsbackend.cc dns.cc \ + dnslabeltext.cc dnsname.cc dnsname.hh dnspacket.cc \ + dnsparser.cc dnsparser.hh dns_random.cc dnsrecords.cc \ + dnssecinfra.cc dnssecinfra.hh dnssecsigner.cc dnswriter.cc \ + dnswriter.hh dynlistener.cc ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc gss_context.cc gss_context.hh ipcipher.cc \ + ipcipher.hh iputils.cc iputils.hh json.cc logger.cc \ + lua-auth4.cc lua-auth4.hh lua-base4.cc lua-base4.hh misc.cc \ + misc.hh nsecrecords.cc opensslsigners.cc opensslsigners.hh \ + pdnsutil.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + serialtweaker.cc signingpipe.cc sillyrecords.cc sstuff.hh \ + statbag.cc stubresolver.cc stubresolver.hh threadname.hh \ + threadname.cc tsigutils.hh tsigutils.cc ueberbackend.cc \ + unix_utility.cc zoneparser-tng.cc $(am__append_23) \ + $(am__append_25) $(am__append_27) $(am__append_30) +pdnsutil_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(DYNLINKFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +EXTRA_pdnsutil_DEPENDENCIES = @moduleobjects@ +pdnsutil_LDADD = @moduleobjects@ @modulelibs@ $(YAHTTP_LIBS) \ + $(JSON11_LIBS) $(LIBDL) $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(LIBCRYPTO_LIBS) $(IPCRYPT_LIBS) $(am__append_24) \ + $(am__append_26) $(am__append_28) $(am__append_29) \ + $(am__append_31) $(am__append_32) $(am__append_33) +zone2sql_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dns.cc \ + dns_random_urandom.cc \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + json.cc json.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2sql.cc \ + zoneparser-tng.cc + +zone2sql_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS) +zone2sql_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +zone2json_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2json.cc \ + zoneparser-tng.cc + +zone2json_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS) +zone2json_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +zone2ldap_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc \ + bind-dnssec.schema.sqlite3.sql.h \ + bindlexer.l \ + bindparser.yy \ + bindparserclasses.hh \ + dns_random_urandom.cc \ + dnsname.cc dnsname.hh \ + dnslabeltext.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zone2ldap.cc \ + zoneparser-tng.cc + +zone2ldap_LDADD = $(LIBCRYPTO_LIBS) +zone2ldap_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +sdig_SOURCES = base32.cc base64.cc base64.hh dns.cc dnslabeltext.cc \ + dnsname.cc dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnswriter.cc dnswriter.hh ednssubnet.cc iputils.cc logger.cc \ + misc.cc misc.hh nsecrecords.cc qtype.cc rcpgenerator.cc \ + rcpgenerator.hh sdig.cc sillyrecords.cc sstuff.hh statbag.cc \ + unix_utility.cc $(am__append_35) +sdig_LDADD = $(LIBCRYPTO_LIBS) $(am__append_36) +sdig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +calidns_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + calidns.cc \ + dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + unix_utility.cc + +calidns_LDADD = $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +calidns_LDFLAGS = $(AM_LDFLAGS) $(THREADFLAGS) $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dumresp_SOURCES = \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dumresp.cc \ + logger.cc \ + misc.cc misc.hh \ + statbag.cc \ + unix_utility.cc \ + qtype.cc + +kvresp_SOURCES = \ + dnslabeltext.cc dnsname.cc dnsname.hh \ + kvresp.cc \ + logger.cc \ + misc.cc misc.hh \ + statbag.cc \ + unix_utility.cc \ + qtype.cc + +stubquery_SOURCES = \ + arguments.cc arguments.hh \ + base32.cc \ + base64.cc \ + dns_random_urandom.cc \ + dnslabeltext.cc \ + dnsname.cc \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + stubresolver.cc stubresolver.hh \ + stubquery.cc \ + unix_utility.cc + +stubquery_LDADD = $(LIBCRYPTO_LIBS) +stubquery_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +saxfr_SOURCES = base32.cc base64.cc base64.hh dns_random_urandom.cc \ + dns_random.hh dnslabeltext.cc dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh dnsrecords.cc dnssecinfra.cc \ + dnswriter.cc dnswriter.hh gss_context.cc gss_context.hh \ + iputils.cc logger.cc misc.cc misc.hh nsecrecords.cc qtype.cc \ + rcpgenerator.cc rcpgenerator.hh saxfr.cc sillyrecords.cc \ + sstuff.hh statbag.cc unix_utility.cc $(am__append_37) +saxfr_LDADD = $(LIBCRYPTO_LIBS) $(am__append_38) $(am__append_39) +saxfr_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +ixfrdist_SOURCES = arguments.cc base32.cc base64.cc base64.hh dns.cc \ + dns_random_urandom.cc dns_random.hh dnslabeltext.cc dnsname.cc \ + dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.hh iputils.cc ixfr.cc ixfr.hh \ + ixfrdist.cc ixfrutils.cc ixfrutils.hh ixfrdist-stats.hh \ + ixfrdist-stats.cc ixfrdist-web.hh ixfrdist-web.cc logger.cc \ + logger.hh misc.cc misc.hh mplexer.hh nsecrecords.cc qtype.cc \ + rcpgenerator.cc rcpgenerator.hh resolver.cc pollmplexer.cc \ + sillyrecords.cc sstuff.hh statbag.cc threadname.hh \ + threadname.cc tsigverifier.cc tsigverifier.hh unix_utility.cc \ + uuid-utils.hh uuid-utils.cc webserver.hh webserver.cc \ + zoneparser-tng.cc $(am__append_40) $(am__append_64) \ + $(am__append_66) $(am__append_68) +ixfrdist_LDADD = $(BOOST_PROGRAM_OPTIONS_LIBS) $(JSON11_LIBS) \ + $(LIBCRYPTO_LIBS) $(YAHTTP_LIBS) $(YAML_LIBS) $(am__append_41) \ + $(am__append_42) +ixfrdist_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +ixplore_SOURCES = arguments.cc base32.cc base64.cc base64.hh dns.cc \ + dns_random_urandom.cc dns_random.hh dnslabeltext.cc dnsname.cc \ + dnsname.hh dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.cc logger.cc misc.cc misc.hh \ + nsecrecords.cc qtype.cc rcpgenerator.cc rcpgenerator.hh \ + resolver.cc ixfr.cc ixfr.hh ixfrutils.cc ixfrutils.hh \ + ixplore.cc sillyrecords.cc sstuff.hh statbag.cc \ + tsigverifier.cc tsigverifier.hh unix_utility.cc \ + zoneparser-tng.cc $(am__append_43) +ixplore_LDADD = $(LIBCRYPTO_LIBS) $(am__append_44) $(am__append_45) +ixplore_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +dnstcpbench_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnstcpbench.cc \ + dnswriter.cc dnswriter.hh \ + iputils.cc \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + sstuff.hh \ + statbag.cc \ + threadname.hh threadname.cc \ + unix_utility.cc + +dnstcpbench_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnstcpbench_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +nsec3dig_SOURCES = base32.cc base64.cc base64.hh dnsname.cc dnsname.hh \ + dnslabeltext.cc dnsparser.cc dnsparser.hh dnsrecords.cc \ + dnssecinfra.cc dnswriter.cc dnswriter.hh gss_context.cc \ + gss_context.hh iputils.cc logger.cc misc.cc misc.hh \ + nsec3dig.cc nsecrecords.cc qtype.cc rcpgenerator.cc \ + rcpgenerator.hh sillyrecords.cc sstuff.hh statbag.cc \ + unix_utility.cc $(am__append_46) +nsec3dig_LDADD = $(LIBCRYPTO_LIBS) $(am__append_47) $(am__append_48) +nsec3dig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +toysdig_SOURCES = base32.cc base64.cc base64.hh dns_random_urandom.cc \ + dnsname.cc dnsname.hh dnslabeltext.cc dnsparser.cc \ + dnsparser.hh dnsrecords.cc dnssecinfra.cc dnswriter.cc \ + dnswriter.hh ednssubnet.cc ednssubnet.hh filterpo.hh \ + gss_context.cc gss_context.hh iputils.cc logger.cc misc.cc \ + misc.hh nsecrecords.cc opensslsigners.cc opensslsigners.hh \ + qtype.cc root-dnssec.hh rcpgenerator.cc rcpgenerator.hh \ + rec-lua-conf.hh recursor_cache.hh sholder.hh sillyrecords.cc \ + sortlist.hh sstuff.hh statbag.cc toysdig.cc unix_utility.cc \ + validate.cc validate.hh $(am__append_50) +toysdig_LDFLAGS = $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +toysdig_LDADD = $(LIBCRYPTO_LIBS) $(am__append_49) $(am__append_51) +tsig_tests_SOURCES = arguments.cc base32.cc base64.cc base64.hh \ + digests.hh dns.cc dns_random_urandom.cc dns_random.hh \ + dnslabeltext.cc dnsname.cc dnsname.hh dnsparser.cc \ + dnsparser.hh dnsrecords.cc dnssecinfra.cc dnswriter.cc \ + dnswriter.hh gss_context.cc gss_context.hh logger.cc misc.cc \ + misc.hh nsecrecords.cc qtype.cc rcpgenerator.cc \ + rcpgenerator.hh resolver.cc sillyrecords.cc sstuff.hh \ + statbag.cc tsig-tests.cc tsigverifier.cc tsigverifier.hh \ + unix_utility.cc $(am__append_52) +tsig_tests_LDADD = $(LIBCRYPTO_LIBS) $(am__append_53) $(am__append_54) +tsig_tests_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +speedtest_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc misc.hh \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + speedtest.cc \ + statbag.cc \ + unix_utility.cc \ + iputils.cc + +speedtest_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +speedtest_LDADD = $(LIBCRYPTO_LIBS) \ + $(RT_LIBS) + +dnswasher_SOURCES = \ + base64.cc \ + dnslabeltext.cc \ + dnsname.hh dnsname.cc \ + dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnswasher.cc \ + dnswriter.hh \ + ipcipher.cc ipcipher.hh \ + logger.cc \ + misc.cc \ + qtype.cc \ + statbag.cc \ + unix_utility.cc + +dnswasher_LDFLAGS = $(AM_LDFLAGS) $(BOOST_PROGRAM_OPTIONS_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +dnswasher_LDADD = $(BOOST_PROGRAM_OPTIONS_LIBS) $(LIBCRYPTO_LIBS) $(IPCRYPT_LIBS) +dnsbulktest_SOURCES = \ + base32.cc \ + base64.cc \ + dnsbulktest.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc + +dnsbulktest_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsbulktest_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +comfun_SOURCES = \ + base32.cc \ + base64.cc \ + comfun.cc \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zoneparser-tng.cc zoneparser-tng.hh + +comfun_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +comfun_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +dnsscan_SOURCES = \ + anadns.hh \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsscan.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsscan_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsscan_LDADD = $(LIBCRYPTO_LIBS) +dnsreplay_SOURCES = \ + anadns.hh \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsreplay.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsreplay_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsreplay_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +nproxy_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + mplexer.hh \ + nproxy.cc \ + nsecrecords.cc \ + pollmplexer.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc + +nproxy_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +nproxy_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +pdns_notify_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + notify.cc \ + nsecrecords.cc \ + pollmplexer.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + dns_random.cc + +pdns_notify_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +pdns_notify_LDADD = $(LIBCRYPTO_LIBS) $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(am__append_55) +dnsscope_SOURCES = \ + arguments.cc \ + base32.cc \ + base64.cc base64.hh \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnsscope.cc \ + dnswriter.cc dnswriter.hh \ + histog.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + statnode.cc statnode.hh \ + unix_utility.cc \ + utility.hh + +dnsscope_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnsscope_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +dnsgram_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnsgram.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsgram_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsgram_LDADD = \ + $(LIBCRYPTO_LIBS) + +dnsdemog_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnsdemog.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnsdemog_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) + +dnsdemog_LDADD = \ + $(LIBCRYPTO_LIBS) + +dnspcap2calidns_SOURCES = \ + base32.cc \ + base64.cc base64.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc dnsparser.hh \ + dnspcap.cc dnspcap.hh \ + dnspcap2calidns.cc \ + dnsrecords.cc \ + dnswriter.cc dnswriter.hh \ + ednsoptions.cc ednsoptions.hh \ + ednssubnet.cc ednssubnet.hh \ + iputils.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc rcpgenerator.hh \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + utility.hh + +dnspcap2calidns_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +dnspcap2calidns_LDADD = \ + $(LIBCRYPTO_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnspcap2protobuf_SOURCES = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ base32.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ base64.cc base64.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnslabeltext.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsname.cc dnsname.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsparser.cc dnsparser.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnspcap.cc dnspcap.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnspcap2protobuf.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnsrecords.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ dnswriter.cc dnswriter.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ gettime.cc gettime.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ iputils.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ logger.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ misc.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ nsecrecords.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ protobuf.cc protobuf.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ qtype.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ rcpgenerator.cc rcpgenerator.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ sillyrecords.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ statbag.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ unix_utility.cc \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ utility.hh \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ uuid-utils.hh uuid-utils.cc + +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@nodist_dnspcap2protobuf_SOURCES = dnsmessage.pb.cc dnsmessage.pb.h +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnspcap2protobuf_LDFLAGS = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(AM_LDFLAGS) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(LIBCRYPTO_LDFLAGS) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnspcap2protobuf_LDADD = \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(LIBCRYPTO_LIBS) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(PROTOBUF_LIBS) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(BOOST_PROGRAM_OPTIONS_LIBS) \ +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(RT_LIBS) + +testrunner_SOURCES = arguments.cc auth-caches.cc auth-caches.hh \ + auth-packetcache.cc auth-packetcache.hh auth-querycache.cc \ + auth-querycache.hh base32.cc base64.cc bindlexer.l \ + bindparser.yy dbdnsseckeeper.cc dns.cc dns_random.cc \ + dnsbackend.cc dnslabeltext.cc dnsname.cc dnsname.hh \ + dnspacket.cc dnsparser.hh dnsparser.cc dnsrecords.cc \ + dnssecinfra.cc dnssecsigner.cc dnswriter.cc ednsoptions.cc \ + ednsoptions.hh ednscookies.cc ednscookies.hh ednssubnet.cc \ + gettime.cc gettime.hh gss_context.cc gss_context.hh \ + ipcipher.cc ipcipher.hh iputils.cc ixfr.cc ixfr.hh logger.cc \ + lua-auth4.hh lua-auth4.cc lua-base4.hh lua-base4.cc \ + stubresolver.hh stubresolver.cc misc.cc nameserver.cc \ + nsecrecords.cc opensslsigners.cc opensslsigners.hh \ + pollmplexer.cc qtype.cc rcpgenerator.cc responsestats.cc \ + responsestats-auth.cc sillyrecords.cc statbag.cc \ + test-arguments_cc.cc test-base32_cc.cc test-base64_cc.cc \ + test-bindparser_cc.cc test-common.hh test-dnsrecordcontent.cc \ + test-digests_hh.cc test-distributor_hh.cc \ + test-dns_random_hh.cc test-dnsname_cc.cc test-dnsparser_cc.cc \ + test-dnsparser_hh.cc test-dnsrecords_cc.cc \ + test-dnswriter_cc.cc test-ipcrypt_cc.cc test-iputils_hh.cc \ + test-ixfr_cc.cc test-lock_hh.cc test-lua_auth4_cc.cc \ + test-misc_hh.cc test-mplexer.cc test-nameserver_cc.cc \ + test-packetcache_cc.cc test-packetcache_hh.cc \ + test-rcpgenerator_cc.cc test-signers.cc test-sha_hh.cc \ + test-statbag_cc.cc test-tsig.cc test-zoneparser_tng_cc.cc \ + testrunner.cc threadname.hh threadname.cc tsigverifier.cc \ + tsigverifier.hh ueberbackend.cc unix_utility.cc \ + zoneparser-tng.cc zoneparser-tng.hh $(am__append_58) \ + $(am__append_60) $(am__append_62) $(am__append_65) \ + $(am__append_67) $(am__append_69) +testrunner_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(LIBCRYPTO_LDFLAGS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) + +testrunner_LDADD = $(LIBCRYPTO_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ + $(RT_LIBS) $(LUA_LIBS) $(LIBDL) $(IPCRYPT_LIBS) \ + $(am__append_59) $(am__append_61) $(am__append_63) +pdns_control_SOURCES = \ + arguments.cc \ + dynloader.cc \ + dynmessenger.cc \ + logger.cc \ + misc.cc \ + qtype.cc \ + statbag.cc \ + unix_utility.cc \ + dnsname.cc \ + dnslabeltext.cc + +@HAVE_BOOST_GE_148_TRUE@@UNIT_TESTS_TRUE@TESTS_ENVIRONMENT = env BOOST_TEST_LOG_LEVEL=message SRCDIR='$(srcdir)' +@FUZZ_TARGETS_TRUE@fuzz_targets_programs = \ +@FUZZ_TARGETS_TRUE@ fuzz_target_dnsdistcache \ +@FUZZ_TARGETS_TRUE@ fuzz_target_moadnsparser \ +@FUZZ_TARGETS_TRUE@ fuzz_target_packetcache \ +@FUZZ_TARGETS_TRUE@ fuzz_target_zoneparsertng + +@FUZZ_TARGETS_TRUE@fuzz_targets_libs = \ +@FUZZ_TARGETS_TRUE@ $(LIBCRYPTO_LIBS) \ +@FUZZ_TARGETS_TRUE@ $(LIB_FUZZING_ENGINE) + +@FUZZ_TARGETS_TRUE@fuzz_targets_ldflags = \ +@FUZZ_TARGETS_TRUE@ $(AM_LDFLAGS) \ +@FUZZ_TARGETS_TRUE@ $(DYNLINKFLAGS) \ +@FUZZ_TARGETS_TRUE@ $(LIBCRYPTO_LDFLAGS) \ +@FUZZ_TARGETS_TRUE@ $(FUZZING_LDFLAGS) + + +# we need the mockup runner to be built, but not linked if a real fuzzing engine is used +@FUZZ_TARGETS_TRUE@fuzz_targets_deps = standalone_fuzz_target_runner.o +@FUZZ_TARGETS_TRUE@fuzz_target_moadnsparser_SOURCES = \ +@FUZZ_TARGETS_TRUE@ fuzz_moadnsparser.cc \ +@FUZZ_TARGETS_TRUE@ base32.cc base32.hh \ +@FUZZ_TARGETS_TRUE@ base64.cc base64.hh \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.cc \ +@FUZZ_TARGETS_TRUE@ dnsname.cc dnsname.hh \ +@FUZZ_TARGETS_TRUE@ dnsparser.cc dnsparser.hh \ +@FUZZ_TARGETS_TRUE@ dnsrecords.cc dnsrecords.hh \ +@FUZZ_TARGETS_TRUE@ dnswriter.cc dnswriter.hh \ +@FUZZ_TARGETS_TRUE@ logger.cc logger.hh \ +@FUZZ_TARGETS_TRUE@ misc.cc misc.hh \ +@FUZZ_TARGETS_TRUE@ nsecrecords.cc \ +@FUZZ_TARGETS_TRUE@ qtype.cc qtype.hh \ +@FUZZ_TARGETS_TRUE@ rcpgenerator.cc rcpgenerator.hh \ +@FUZZ_TARGETS_TRUE@ sillyrecords.cc \ +@FUZZ_TARGETS_TRUE@ statbag.cc statbag.hh \ +@FUZZ_TARGETS_TRUE@ unix_utility.cc \ +@FUZZ_TARGETS_TRUE@ utility.hh + +@FUZZ_TARGETS_TRUE@fuzz_target_moadnsparser_DEPENDENCIES = $(fuzz_targets_deps) +@FUZZ_TARGETS_TRUE@fuzz_target_moadnsparser_LDFLAGS = $(fuzz_targets_ldflags) +@FUZZ_TARGETS_TRUE@fuzz_target_moadnsparser_LDADD = $(fuzz_targets_libs) +@FUZZ_TARGETS_TRUE@fuzz_target_packetcache_SOURCES = \ +@FUZZ_TARGETS_TRUE@ fuzz_packetcache.cc \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.cc \ +@FUZZ_TARGETS_TRUE@ dnsname.cc dnsname.hh \ +@FUZZ_TARGETS_TRUE@ ednsoptions.cc ednsoptions.hh \ +@FUZZ_TARGETS_TRUE@ misc.cc misc.hh \ +@FUZZ_TARGETS_TRUE@ packetcache.hh \ +@FUZZ_TARGETS_TRUE@ qtype.cc qtype.hh \ +@FUZZ_TARGETS_TRUE@ statbag.cc statbag.hh + +@FUZZ_TARGETS_TRUE@fuzz_target_packetcache_DEPENDENCIES = $(fuzz_targets_deps) +@FUZZ_TARGETS_TRUE@fuzz_target_packetcache_LDFLAGS = $(fuzz_targets_ldflags) +@FUZZ_TARGETS_TRUE@fuzz_target_packetcache_LDADD = $(fuzz_targets_libs) +@FUZZ_TARGETS_TRUE@fuzz_target_dnsdistcache_SOURCES = \ +@FUZZ_TARGETS_TRUE@ fuzz_dnsdistcache.cc \ +@FUZZ_TARGETS_TRUE@ dnsdist-cache.cc dnsdist-cache.hh \ +@FUZZ_TARGETS_TRUE@ dnsdist-ecs.cc dnsdist-ecs.hh \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.cc \ +@FUZZ_TARGETS_TRUE@ dnsname.cc dnsname.hh \ +@FUZZ_TARGETS_TRUE@ dnsparser.cc dnsparser.hh \ +@FUZZ_TARGETS_TRUE@ dnswriter.cc dnswriter.hh \ +@FUZZ_TARGETS_TRUE@ doh.hh \ +@FUZZ_TARGETS_TRUE@ ednsoptions.cc ednsoptions.hh \ +@FUZZ_TARGETS_TRUE@ ednssubnet.cc ednssubnet.hh \ +@FUZZ_TARGETS_TRUE@ iputils.cc iputils.hh \ +@FUZZ_TARGETS_TRUE@ misc.cc misc.hh \ +@FUZZ_TARGETS_TRUE@ packetcache.hh \ +@FUZZ_TARGETS_TRUE@ qtype.cc qtype.hh + +@FUZZ_TARGETS_TRUE@fuzz_target_dnsdistcache_DEPENDENCIES = $(fuzz_targets_deps) +@FUZZ_TARGETS_TRUE@fuzz_target_dnsdistcache_LDFLAGS = $(fuzz_targets_ldflags) +@FUZZ_TARGETS_TRUE@fuzz_target_dnsdistcache_LDADD = $(fuzz_targets_libs) +@FUZZ_TARGETS_TRUE@fuzz_target_zoneparsertng_SOURCES = \ +@FUZZ_TARGETS_TRUE@ fuzz_zoneparsertng.cc \ +@FUZZ_TARGETS_TRUE@ base32.cc base32.hh \ +@FUZZ_TARGETS_TRUE@ base64.cc base64.hh \ +@FUZZ_TARGETS_TRUE@ dnslabeltext.cc \ +@FUZZ_TARGETS_TRUE@ dnsname.cc dnsname.hh \ +@FUZZ_TARGETS_TRUE@ dnsparser.cc dnsparser.hh \ +@FUZZ_TARGETS_TRUE@ dnsrecords.cc dnsrecords.hh \ +@FUZZ_TARGETS_TRUE@ dnswriter.cc dnswriter.hh \ +@FUZZ_TARGETS_TRUE@ logger.cc logger.hh \ +@FUZZ_TARGETS_TRUE@ misc.cc misc.hh \ +@FUZZ_TARGETS_TRUE@ nsecrecords.cc \ +@FUZZ_TARGETS_TRUE@ qtype.cc qtype.hh \ +@FUZZ_TARGETS_TRUE@ rcpgenerator.cc rcpgenerator.hh \ +@FUZZ_TARGETS_TRUE@ sillyrecords.cc \ +@FUZZ_TARGETS_TRUE@ statbag.cc statbag.hh \ +@FUZZ_TARGETS_TRUE@ unix_utility.cc \ +@FUZZ_TARGETS_TRUE@ utility.hh \ +@FUZZ_TARGETS_TRUE@ zoneparser-tng.cc zoneparser-tng.hh + +@FUZZ_TARGETS_TRUE@fuzz_target_zoneparsertng_DEPENDENCIES = $(fuzz_targets_deps) +@FUZZ_TARGETS_TRUE@fuzz_target_zoneparsertng_LDFLAGS = $(fuzz_targets_ldflags) +@FUZZ_TARGETS_TRUE@fuzz_target_zoneparsertng_LDADD = $(fuzz_targets_libs) +curl_verbose = $(curl_verbose_$(V)) +curl_verbose_ = $(curl_verbose_$(AM_DEFAULT_VERBOSITY)) +curl_verbose_0 = @echo " CURL " $@; +@HAVE_SYSTEMD_TRUE@systemdsystemunitdir = $(SYSTEMD_DIR) +@HAVE_SYSTEMD_TRUE@systemdsystemunit_DATA = pdns.service pdns@.service \ +@HAVE_SYSTEMD_TRUE@ $(am__append_72) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .h .hh .l .lo .log .o .obj .test .test$(EXEEXT) .trs .yy +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign pdns/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign pdns/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +pdns.init: $(top_builddir)/config.status $(srcdir)/pdns.init.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @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 \ + ; 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)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_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 +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || 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)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_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 + +calidns$(EXEEXT): $(calidns_OBJECTS) $(calidns_DEPENDENCIES) $(EXTRA_calidns_DEPENDENCIES) + @rm -f calidns$(EXEEXT) + $(AM_V_CXXLD)$(calidns_LINK) $(calidns_OBJECTS) $(calidns_LDADD) $(LIBS) + +comfun$(EXEEXT): $(comfun_OBJECTS) $(comfun_DEPENDENCIES) $(EXTRA_comfun_DEPENDENCIES) + @rm -f comfun$(EXEEXT) + $(AM_V_CXXLD)$(comfun_LINK) $(comfun_OBJECTS) $(comfun_LDADD) $(LIBS) + +dnsbulktest$(EXEEXT): $(dnsbulktest_OBJECTS) $(dnsbulktest_DEPENDENCIES) $(EXTRA_dnsbulktest_DEPENDENCIES) + @rm -f dnsbulktest$(EXEEXT) + $(AM_V_CXXLD)$(dnsbulktest_LINK) $(dnsbulktest_OBJECTS) $(dnsbulktest_LDADD) $(LIBS) + +dnsdemog$(EXEEXT): $(dnsdemog_OBJECTS) $(dnsdemog_DEPENDENCIES) $(EXTRA_dnsdemog_DEPENDENCIES) + @rm -f dnsdemog$(EXEEXT) + $(AM_V_CXXLD)$(dnsdemog_LINK) $(dnsdemog_OBJECTS) $(dnsdemog_LDADD) $(LIBS) + +dnsgram$(EXEEXT): $(dnsgram_OBJECTS) $(dnsgram_DEPENDENCIES) $(EXTRA_dnsgram_DEPENDENCIES) + @rm -f dnsgram$(EXEEXT) + $(AM_V_CXXLD)$(dnsgram_LINK) $(dnsgram_OBJECTS) $(dnsgram_LDADD) $(LIBS) + +dnspcap2calidns$(EXEEXT): $(dnspcap2calidns_OBJECTS) $(dnspcap2calidns_DEPENDENCIES) $(EXTRA_dnspcap2calidns_DEPENDENCIES) + @rm -f dnspcap2calidns$(EXEEXT) + $(AM_V_CXXLD)$(dnspcap2calidns_LINK) $(dnspcap2calidns_OBJECTS) $(dnspcap2calidns_LDADD) $(LIBS) + +dnspcap2protobuf$(EXEEXT): $(dnspcap2protobuf_OBJECTS) $(dnspcap2protobuf_DEPENDENCIES) $(EXTRA_dnspcap2protobuf_DEPENDENCIES) + @rm -f dnspcap2protobuf$(EXEEXT) + $(AM_V_CXXLD)$(dnspcap2protobuf_LINK) $(dnspcap2protobuf_OBJECTS) $(dnspcap2protobuf_LDADD) $(LIBS) + +dnsreplay$(EXEEXT): $(dnsreplay_OBJECTS) $(dnsreplay_DEPENDENCIES) $(EXTRA_dnsreplay_DEPENDENCIES) + @rm -f dnsreplay$(EXEEXT) + $(AM_V_CXXLD)$(dnsreplay_LINK) $(dnsreplay_OBJECTS) $(dnsreplay_LDADD) $(LIBS) + +dnsscan$(EXEEXT): $(dnsscan_OBJECTS) $(dnsscan_DEPENDENCIES) $(EXTRA_dnsscan_DEPENDENCIES) + @rm -f dnsscan$(EXEEXT) + $(AM_V_CXXLD)$(dnsscan_LINK) $(dnsscan_OBJECTS) $(dnsscan_LDADD) $(LIBS) + +dnsscope$(EXEEXT): $(dnsscope_OBJECTS) $(dnsscope_DEPENDENCIES) $(EXTRA_dnsscope_DEPENDENCIES) + @rm -f dnsscope$(EXEEXT) + $(AM_V_CXXLD)$(dnsscope_LINK) $(dnsscope_OBJECTS) $(dnsscope_LDADD) $(LIBS) + +dnstcpbench$(EXEEXT): $(dnstcpbench_OBJECTS) $(dnstcpbench_DEPENDENCIES) $(EXTRA_dnstcpbench_DEPENDENCIES) + @rm -f dnstcpbench$(EXEEXT) + $(AM_V_CXXLD)$(dnstcpbench_LINK) $(dnstcpbench_OBJECTS) $(dnstcpbench_LDADD) $(LIBS) + +dnswasher$(EXEEXT): $(dnswasher_OBJECTS) $(dnswasher_DEPENDENCIES) $(EXTRA_dnswasher_DEPENDENCIES) + @rm -f dnswasher$(EXEEXT) + $(AM_V_CXXLD)$(dnswasher_LINK) $(dnswasher_OBJECTS) $(dnswasher_LDADD) $(LIBS) + +dumresp$(EXEEXT): $(dumresp_OBJECTS) $(dumresp_DEPENDENCIES) $(EXTRA_dumresp_DEPENDENCIES) + @rm -f dumresp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(dumresp_OBJECTS) $(dumresp_LDADD) $(LIBS) + +fuzz_target_dnsdistcache$(EXEEXT): $(fuzz_target_dnsdistcache_OBJECTS) $(fuzz_target_dnsdistcache_DEPENDENCIES) $(EXTRA_fuzz_target_dnsdistcache_DEPENDENCIES) + @rm -f fuzz_target_dnsdistcache$(EXEEXT) + $(AM_V_CXXLD)$(fuzz_target_dnsdistcache_LINK) $(fuzz_target_dnsdistcache_OBJECTS) $(fuzz_target_dnsdistcache_LDADD) $(LIBS) + +fuzz_target_moadnsparser$(EXEEXT): $(fuzz_target_moadnsparser_OBJECTS) $(fuzz_target_moadnsparser_DEPENDENCIES) $(EXTRA_fuzz_target_moadnsparser_DEPENDENCIES) + @rm -f fuzz_target_moadnsparser$(EXEEXT) + $(AM_V_CXXLD)$(fuzz_target_moadnsparser_LINK) $(fuzz_target_moadnsparser_OBJECTS) $(fuzz_target_moadnsparser_LDADD) $(LIBS) + +fuzz_target_packetcache$(EXEEXT): $(fuzz_target_packetcache_OBJECTS) $(fuzz_target_packetcache_DEPENDENCIES) $(EXTRA_fuzz_target_packetcache_DEPENDENCIES) + @rm -f fuzz_target_packetcache$(EXEEXT) + $(AM_V_CXXLD)$(fuzz_target_packetcache_LINK) $(fuzz_target_packetcache_OBJECTS) $(fuzz_target_packetcache_LDADD) $(LIBS) + +fuzz_target_zoneparsertng$(EXEEXT): $(fuzz_target_zoneparsertng_OBJECTS) $(fuzz_target_zoneparsertng_DEPENDENCIES) $(EXTRA_fuzz_target_zoneparsertng_DEPENDENCIES) + @rm -f fuzz_target_zoneparsertng$(EXEEXT) + $(AM_V_CXXLD)$(fuzz_target_zoneparsertng_LINK) $(fuzz_target_zoneparsertng_OBJECTS) $(fuzz_target_zoneparsertng_LDADD) $(LIBS) + +ixfrdist$(EXEEXT): $(ixfrdist_OBJECTS) $(ixfrdist_DEPENDENCIES) $(EXTRA_ixfrdist_DEPENDENCIES) + @rm -f ixfrdist$(EXEEXT) + $(AM_V_CXXLD)$(ixfrdist_LINK) $(ixfrdist_OBJECTS) $(ixfrdist_LDADD) $(LIBS) + +ixplore$(EXEEXT): $(ixplore_OBJECTS) $(ixplore_DEPENDENCIES) $(EXTRA_ixplore_DEPENDENCIES) + @rm -f ixplore$(EXEEXT) + $(AM_V_CXXLD)$(ixplore_LINK) $(ixplore_OBJECTS) $(ixplore_LDADD) $(LIBS) + +kvresp$(EXEEXT): $(kvresp_OBJECTS) $(kvresp_DEPENDENCIES) $(EXTRA_kvresp_DEPENDENCIES) + @rm -f kvresp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(kvresp_OBJECTS) $(kvresp_LDADD) $(LIBS) + +nproxy$(EXEEXT): $(nproxy_OBJECTS) $(nproxy_DEPENDENCIES) $(EXTRA_nproxy_DEPENDENCIES) + @rm -f nproxy$(EXEEXT) + $(AM_V_CXXLD)$(nproxy_LINK) $(nproxy_OBJECTS) $(nproxy_LDADD) $(LIBS) + +nsec3dig$(EXEEXT): $(nsec3dig_OBJECTS) $(nsec3dig_DEPENDENCIES) $(EXTRA_nsec3dig_DEPENDENCIES) + @rm -f nsec3dig$(EXEEXT) + $(AM_V_CXXLD)$(nsec3dig_LINK) $(nsec3dig_OBJECTS) $(nsec3dig_LDADD) $(LIBS) + +pdns_control$(EXEEXT): $(pdns_control_OBJECTS) $(pdns_control_DEPENDENCIES) $(EXTRA_pdns_control_DEPENDENCIES) + @rm -f pdns_control$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(pdns_control_OBJECTS) $(pdns_control_LDADD) $(LIBS) + +pdns_notify$(EXEEXT): $(pdns_notify_OBJECTS) $(pdns_notify_DEPENDENCIES) $(EXTRA_pdns_notify_DEPENDENCIES) + @rm -f pdns_notify$(EXEEXT) + $(AM_V_CXXLD)$(pdns_notify_LINK) $(pdns_notify_OBJECTS) $(pdns_notify_LDADD) $(LIBS) +backends/gsql/$(am__dirstamp): + @$(MKDIR_P) backends/gsql + @: > backends/gsql/$(am__dirstamp) +backends/gsql/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) backends/gsql/$(DEPDIR) + @: > backends/gsql/$(DEPDIR)/$(am__dirstamp) +backends/gsql/gsqlbackend.$(OBJEXT): backends/gsql/$(am__dirstamp) \ + backends/gsql/$(DEPDIR)/$(am__dirstamp) + +pdns_server$(EXEEXT): $(pdns_server_OBJECTS) $(pdns_server_DEPENDENCIES) $(EXTRA_pdns_server_DEPENDENCIES) + @rm -f pdns_server$(EXEEXT) + $(AM_V_CXXLD)$(pdns_server_LINK) $(pdns_server_OBJECTS) $(pdns_server_LDADD) $(LIBS) +bindparser.hh: bindparser.cc + @if test ! -f $@; then rm -f bindparser.cc; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) bindparser.cc; else :; fi + +pdnsutil$(EXEEXT): $(pdnsutil_OBJECTS) $(pdnsutil_DEPENDENCIES) $(EXTRA_pdnsutil_DEPENDENCIES) + @rm -f pdnsutil$(EXEEXT) + $(AM_V_CXXLD)$(pdnsutil_LINK) $(pdnsutil_OBJECTS) $(pdnsutil_LDADD) $(LIBS) + +saxfr$(EXEEXT): $(saxfr_OBJECTS) $(saxfr_DEPENDENCIES) $(EXTRA_saxfr_DEPENDENCIES) + @rm -f saxfr$(EXEEXT) + $(AM_V_CXXLD)$(saxfr_LINK) $(saxfr_OBJECTS) $(saxfr_LDADD) $(LIBS) + +sdig$(EXEEXT): $(sdig_OBJECTS) $(sdig_DEPENDENCIES) $(EXTRA_sdig_DEPENDENCIES) + @rm -f sdig$(EXEEXT) + $(AM_V_CXXLD)$(sdig_LINK) $(sdig_OBJECTS) $(sdig_LDADD) $(LIBS) + +speedtest$(EXEEXT): $(speedtest_OBJECTS) $(speedtest_DEPENDENCIES) $(EXTRA_speedtest_DEPENDENCIES) + @rm -f speedtest$(EXEEXT) + $(AM_V_CXXLD)$(speedtest_LINK) $(speedtest_OBJECTS) $(speedtest_LDADD) $(LIBS) + +stubquery$(EXEEXT): $(stubquery_OBJECTS) $(stubquery_DEPENDENCIES) $(EXTRA_stubquery_DEPENDENCIES) + @rm -f stubquery$(EXEEXT) + $(AM_V_CXXLD)$(stubquery_LINK) $(stubquery_OBJECTS) $(stubquery_LDADD) $(LIBS) + +testrunner$(EXEEXT): $(testrunner_OBJECTS) $(testrunner_DEPENDENCIES) $(EXTRA_testrunner_DEPENDENCIES) + @rm -f testrunner$(EXEEXT) + $(AM_V_CXXLD)$(testrunner_LINK) $(testrunner_OBJECTS) $(testrunner_LDADD) $(LIBS) + +toysdig$(EXEEXT): $(toysdig_OBJECTS) $(toysdig_DEPENDENCIES) $(EXTRA_toysdig_DEPENDENCIES) + @rm -f toysdig$(EXEEXT) + $(AM_V_CXXLD)$(toysdig_LINK) $(toysdig_OBJECTS) $(toysdig_LDADD) $(LIBS) + +tsig-tests$(EXEEXT): $(tsig_tests_OBJECTS) $(tsig_tests_DEPENDENCIES) $(EXTRA_tsig_tests_DEPENDENCIES) + @rm -f tsig-tests$(EXEEXT) + $(AM_V_CXXLD)$(tsig_tests_LINK) $(tsig_tests_OBJECTS) $(tsig_tests_LDADD) $(LIBS) + +zone2json$(EXEEXT): $(zone2json_OBJECTS) $(zone2json_DEPENDENCIES) $(EXTRA_zone2json_DEPENDENCIES) + @rm -f zone2json$(EXEEXT) + $(AM_V_CXXLD)$(zone2json_LINK) $(zone2json_OBJECTS) $(zone2json_LDADD) $(LIBS) + +zone2ldap$(EXEEXT): $(zone2ldap_OBJECTS) $(zone2ldap_DEPENDENCIES) $(EXTRA_zone2ldap_DEPENDENCIES) + @rm -f zone2ldap$(EXEEXT) + $(AM_V_CXXLD)$(zone2ldap_LINK) $(zone2ldap_OBJECTS) $(zone2ldap_LDADD) $(LIBS) + +zone2sql$(EXEEXT): $(zone2sql_OBJECTS) $(zone2sql_DEPENDENCIES) $(EXTRA_zone2sql_DEPENDENCIES) + @rm -f zone2sql$(EXEEXT) + $(AM_V_CXXLD)$(zone2sql_LINK) $(zone2sql_OBJECTS) $(zone2sql_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f backends/gsql/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arguments.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-caches.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-carbon.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-packetcache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-querycache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bindlexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bindparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calidns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comfun.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_startup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/communicator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbdnsseckeeper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decafsigners.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devpollmplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns_random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns_random_urandom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsbackend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsbulktest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsdemog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsdist-cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsdist-ecs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsgram.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnslabeltext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsmessage.pb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnspacket.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnspcap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnspcap2calidns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnspcap2protobuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsproxy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsrecords.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsreplay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsscan.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsscope.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssecinfra.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssecsigner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnstcpbench.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnswasher.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnswriter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dumresp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynhandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynlistener.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynloader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynmessenger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ednscookies.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ednsoptions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ednssubnet.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/epollmplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_dnsdistcache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_moadnsparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_packetcache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_zoneparsertng.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gss_context.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipcipher.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iputils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfrdist-stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfrdist-web.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfrdist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfrutils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixplore.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kqueuemplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kvresp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-auth4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-base4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-record.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mastercommunicator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minicurl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nameserver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nproxy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3dig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsecrecords.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opensslsigners.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packethandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsutil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs11signers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pollmplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/portsmplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protobuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qtype.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcpgenerator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/receiver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/responsestats-auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/responsestats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc2136handler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saxfr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/secpoll-auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialtweaker.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signingpipe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sillyrecords.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slavecommunicator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sodiumsigners.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speedtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssqlite3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statbag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statnode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stubquery.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stubresolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcpreceiver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-arguments_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-base32_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-base64_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-bindparser_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-digests_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-distributor_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dns_random_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsname_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsparser_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsparser_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsrecordcontent.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnsrecords_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dnswriter_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ipcrypt_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-iputils_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ixfr_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-lock_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-lua_auth4_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-misc_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-mplexer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-nameserver_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-packetcache_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-packetcache_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-rcpgenerator_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-sha_hh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-signers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-statbag_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-tsig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-zoneparser_tng_cc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testrunner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tkey.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/toysdig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig-tests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsigutils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsigverifier.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ueberbackend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_semaphore.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_utility.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uuid-utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/validate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/webserver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ws-api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ws-auth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone2json.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone2ldap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone2sql.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoneparser-tng.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@backends/gsql/$(DEPDIR)/gsqlbackend.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@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@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@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@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@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@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +.l.c: + $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) + +.yy.cc: + $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-sysconfDATA: $(sysconf_DATA) + @$(NORMAL_INSTALL) + @list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \ + done + +uninstall-sysconfDATA: + @$(NORMAL_UNINSTALL) + @list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir) +install-systemdsystemunitDATA: $(systemdsystemunit_DATA) + @$(NORMAL_INSTALL) + @list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(systemdsystemunitdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(systemdsystemunitdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemdsystemunitdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(systemdsystemunitdir)" || exit $$?; \ + done + +uninstall-systemdsystemunitDATA: + @$(NORMAL_UNINSTALL) + @list='$(systemdsystemunit_DATA)'; test -n "$(systemdsystemunitdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(systemdsystemunitdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +testrunner.log: testrunner$(EXEEXT) + @p='testrunner$(EXEEXT)'; \ + b='testrunner'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +@HAVE_BOOST_GE_148_TRUE@@UNIT_TESTS_TRUE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(systemdsystemunitdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + 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: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f backends/gsql/$(DEPDIR)/$(am__dirstamp) + -rm -f backends/gsql/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -rm -f bindlexer.c + -rm -f bindparser.cc + -rm -f bindparser.hh + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) backends/gsql/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-systemdsystemunitDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-sbinPROGRAMS \ + install-sysconfDATA + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) backends/gsql/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS \ + uninstall-sysconfDATA uninstall-systemdsystemunitDATA + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am \ + check-local clean clean-binPROGRAMS clean-generic \ + clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ + 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-man install-pdf \ + install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ + install-strip install-sysconfDATA \ + install-systemdsystemunitDATA installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ + uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-sbinPROGRAMS uninstall-sysconfDATA \ + uninstall-systemdsystemunitDATA + +.PRECIOUS: Makefile + + +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnsmessage.pb.cc: dnsmessage.proto +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@ $(AM_V_GEN)$(PROTOC) --cpp_out=./ $< +@HAVE_PROTOBUF_TRUE@@HAVE_PROTOC_TRUE@dnspcap2protobuf.$(OBJEXT): dnsmessage.pb.cc + +pdns.conf-dist: pdns_server + $(AM_V_GEN)./pdns_server --no-config --config 2>/dev/null > $@ +@HAVE_BOOST_GE_148_FALSE@@UNIT_TESTS_TRUE@check-local: +@HAVE_BOOST_GE_148_FALSE@@UNIT_TESTS_TRUE@ @echo "Unit tests disabled, boost is too old" + +@UNIT_TESTS_FALSE@check-local: +@UNIT_TESTS_FALSE@ @echo "Unit tests are not enabled" +@UNIT_TESTS_FALSE@ @echo "Run ./configure --enable-unit-tests" + +@FUZZ_TARGETS_TRUE@LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o + +@FUZZ_TARGETS_TRUE@standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cc + +@FUZZ_TARGETS_TRUE@fuzz_targets: $(fuzz_targets_programs) + +dnslabeltext.cc: dnslabeltext.rl + $(AM_V_GEN)$(RAGEL) $< -o dnslabeltext.cc + +bind-dnssec.schema.sqlite3.sql.h: bind-dnssec.schema.sqlite3.sql + ( echo 'static char sqlCreate[] __attribute__((unused))=' ; sed 's/$$/"/g' $< | sed 's/^/"/g' ; echo ';' ) > $@ + +# for bindparser.h/hh +.hh.h: + cp $< $@ + +bindlexer.$(OBJEXT): bindparser.h +$(srcdir)/effective_tld_names.dat: + $(curl_verbose)if ! curl -s -S https://publicsuffix.org/list/public_suffix_list.dat > $@; then rm -f $@; exit 1; fi + +pubsuffix.cc: $(srcdir)/effective_tld_names.dat + $(AM_V_GEN)./mkpubsuffixcc + +pdns_recursor rec_control: + @echo "Please build the recursor from the recursordist/ dir" + @exit 1 + +dnsdist: + @echo "Please build dnsdist from the dnsdistdist/ dir" + @exit 1 + +@HAVE_SYSTEMD_TRUE@pdns.service: pdns.service.in +@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)sed -e 's![@]sbindir[@]!$(sbindir)!' < $< > $@ +@HAVE_SYSTEMD_LOCK_PERSONALITY_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^LockPersonality/' $@ +@HAVE_SYSTEMD_PRIVATE_DEVICES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^PrivateDevices/' $@ +@HAVE_SYSTEMD_PRIVATE_TMP_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^PrivateTmp/' $@ +@HAVE_SYSTEMD_PROTECT_CONTROL_GROUPS_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^ProtectControlGroups/' $@ +@HAVE_SYSTEMD_PROTECT_HOME_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^ProtectHome/' $@ +@HAVE_SYSTEMD_PROTECT_KERNEL_MODULES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^ProtectKernelModules/' $@ +@HAVE_SYSTEMD_PROTECT_KERNEL_TUNABLES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^ProtectKernelTunables/' $@ +@HAVE_SYSTEMD_PROTECT_SYSTEM_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^ProtectSystem/' $@ +@HAVE_SYSTEMD_RESTRICT_ADDRESS_FAMILIES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^RestrictAddressFamilies/' $@ +@HAVE_SYSTEMD_RESTRICT_NAMESPACES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^RestrictNamespaces/' $@ +@HAVE_SYSTEMD_RESTRICT_REALTIME_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^RestrictRealtime/' $@ +@HAVE_SYSTEMD_SYSTEM_CALL_ARCHITECTURES_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^SystemCallArchitectures/' $@ +@HAVE_SYSTEMD_SYSTEM_CALL_FILTER_FALSE@@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)perl -ni -e 'print unless /^SystemCallFilter/' $@ + +@HAVE_SYSTEMD_TRUE@pdns@.service: pdns.service +@HAVE_SYSTEMD_TRUE@ $(AM_V_GEN)sed -e 's!/pdns_server!& --config-name=%i!' \ +@HAVE_SYSTEMD_TRUE@ -e 's!Authoritative Server!& %i!' \ +@HAVE_SYSTEMD_TRUE@ < $< > $@ + +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ixfrdist.service: ixfrdist.service.in +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ $(AM_V_GEN)sed -e 's![@]bindir[@]!$(bindir)!' < $< > $@ + +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ixfrdist@.service: ixfrdist.service +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ $(AM_V_GEN)sed -e 's!/ixfrdist!& --config $(sysconfdir)/ixfrdist-%i.yml!' \ +@HAVE_SYSTEMD_TRUE@@IXFRDIST_TRUE@ < $< > $@ + +# 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. +.NOEXPORT: diff --git a/pdns/anadns.hh b/pdns/anadns.hh new file mode 100644 index 0000000..3465768 --- /dev/null +++ b/pdns/anadns.hh @@ -0,0 +1,88 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_ANADNS_HH +#define PDNS_ANADNS_HH +#include +#include +#include +#include +#include +#include "dnsparser.hh" +#include "iputils.hh" +#include "namespaces.hh" + +struct QuestionIdentifier +{ + QuestionIdentifier() + {} + + bool operator<(const QuestionIdentifier& rhs) const + { + return + tie(d_id, d_qtype, d_source, d_dest, d_qname) < + tie(rhs.d_id, rhs.d_qtype, rhs.d_source, rhs.d_dest, rhs.d_qname); + } + + + // the canonical direction is that of the question + static QuestionIdentifier create(const ComboAddress& src, const ComboAddress& dst, const struct dnsheader& header, const DNSName& qname, uint16_t qtype) + { + QuestionIdentifier ret; + + if(header.qr) { + ret.d_source = dst; + ret.d_dest = src; + } + else { + ret.d_source = src; + ret.d_dest = dst; + } + ret.d_qname=qname; + ret.d_qtype=qtype; + ret.d_id=ntohs(header.id); + return ret; + } + + // the canonical direction is that of the question + static QuestionIdentifier create(const ComboAddress& src, const ComboAddress& dst, const MOADNSParser& mdp) + { + return create(src, dst, mdp.d_header, mdp.d_qname, mdp.d_qtype); + } + + + ComboAddress d_source, d_dest; + + DNSName d_qname; + uint16_t d_qtype; + uint16_t d_id; +}; + +inline ostream& operator<<(ostream &s, const QuestionIdentifier& qi) +{ + s<< "'"< +#include +#include + +#include "namespaces.hh" +#include "logger.hh" +#include +#include +#include +#include +#include + +const ArgvMap::param_t::const_iterator ArgvMap::begin() +{ + return params.begin(); +} + +const ArgvMap::param_t::const_iterator ArgvMap::end() +{ + return params.end(); +} + +string & ArgvMap::set(const string &var) +{ + return params[var]; +} + +bool ArgvMap::mustDo(const string &var) +{ + return ((*this)[var]!="no") && ((*this)[var]!="off"); +} + +vectorArgvMap::list() +{ + vector ret; + for(map::const_iterator i=params.begin();i!=params.end();++i) + ret.push_back(i->first); + return ret; +} + +string ArgvMap::getHelp(const string &item) +{ + return helpmap[item]; +} + +string & ArgvMap::set(const string &var, const string &help) +{ + helpmap[var]=help; + d_typeMap[var]="Parameter"; + return set(var); +} + +void ArgvMap::setCmd(const string &var, const string &help) +{ + helpmap[var]=help; + d_typeMap[var]="Command"; + set(var)="no"; +} + +string & ArgvMap::setSwitch(const string &var, const string &help) +{ + helpmap[var]=help; + d_typeMap[var]="Switch"; + return set(var); +} + + +bool ArgvMap::contains(const string &var, const string &val) +{ + params_t::const_iterator param = params.find(var); + if(param == params.end() || param->second.empty()) { + return false; + } + vector parts; + + stringtok( parts, param->second, ", \t" ); + for (const auto& part: parts) { + if (part == val) { + return true; + } + } + + return false; +} + +string ArgvMap::helpstring(string prefix) +{ + if(prefix=="no") + prefix=""; + + string help; + + for (const auto& i: helpmap) { + if(!prefix.empty() && i.first.find(prefix) != 0) // only print items with prefix + continue; + + help+=" --"; + help+=i.first; + + string type=d_typeMap[i.first]; + + if(type=="Parameter") + help+="=..."; + else if(type=="Switch") + { + help+=" | --"+i.first+"=yes"; + help+=" | --"+i.first+"=no"; + } + + + help+="\n\t"; + help+=i.second; + help+="\n"; + + } + return help; +} + +string ArgvMap::configstring(bool current) +{ + string help; + + if (current) + help="# Autogenerated configuration file based on running instance\n"; + else + help="# Autogenerated configuration file template\n"; + + for(const auto& i: helpmap) { + if(d_typeMap[i.first]=="Command") + continue; + + help+="#################################\n"; + help+="# "; + help+=i.first; + help+="\t"; + help+=i.second; + help+="\n#\n"; + if (current) { + help+=i.first+"="+params[i.first]+"\n\n"; + } else { + help+="# "+i.first+"="+params[i.first]+"\n\n"; + } + } + return help; +} + +const string & ArgvMap::operator[](const string &arg) +{ + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + return params[arg]; +} + +mode_t ArgvMap::asMode(const string &arg) +{ + mode_t mode; + const char *cptr_orig; + char *cptr_ret = NULL; + + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + cptr_orig = params[arg].c_str(); + mode = static_cast(strtol(cptr_orig, &cptr_ret, 8)); + if (mode == 0 && cptr_ret == cptr_orig) + throw ArgException("'" + arg + string("' contains invalid octal mode")); + return mode; +} + +gid_t ArgvMap::asGid(const string &arg) +{ + gid_t gid; + const char *cptr_orig; + char *cptr_ret = NULL; + + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + cptr_orig = params[arg].c_str(); + gid = static_cast(strtol(cptr_orig, &cptr_ret, 0)); + if (gid == 0 && cptr_ret == cptr_orig) { + // try to resolve + struct group *group = getgrnam(params[arg].c_str()); + if (group == NULL) + throw ArgException("'" + arg + string("' contains invalid group")); + gid = group->gr_gid; + } + return gid; +} + +uid_t ArgvMap::asUid(const string &arg) +{ + uid_t uid; + const char *cptr_orig; + char *cptr_ret = NULL; + + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + cptr_orig = params[arg].c_str(); + uid = static_cast(strtol(cptr_orig, &cptr_ret, 0)); + if (uid == 0 && cptr_ret == cptr_orig) { + // try to resolve + struct passwd *pwent = getpwnam(params[arg].c_str()); + if (pwent == NULL) + throw ArgException("'" + arg + string("' contains invalid group")); + uid = pwent->pw_uid; + } + return uid; +} + +int ArgvMap::asNum(const string &arg, int def) +{ + int retval; + const char *cptr_orig; + char *cptr_ret = NULL; + + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + // use default for empty values + if (params[arg].empty()) + return def; + + cptr_orig = params[arg].c_str(); + retval = static_cast(strtol(cptr_orig, &cptr_ret, 0)); + if (!retval && cptr_ret == cptr_orig) + throw ArgException("'"+arg+"' value '"+string(cptr_orig) + string( "' is not a valid number")); + + return retval; +} + +bool ArgvMap::isEmpty(const string &arg) +{ + if(!parmIsset(arg)) + return true; + return params[arg].empty(); +} + +double ArgvMap::asDouble(const string &arg) +{ + double retval; + const char *cptr_orig; + char *cptr_ret = NULL; + + if(!parmIsset(arg)) + throw ArgException(string("Undefined but needed argument: '")+arg+"'"); + + if (params[arg].empty()) + return 0.0; + + cptr_orig = params[arg].c_str(); + retval = strtod(cptr_orig, &cptr_ret); + + if (retval == 0 && cptr_ret == cptr_orig) + throw ArgException("'"+arg+string("' is not valid double")); + + return retval; +} + +ArgvMap::ArgvMap() +{ + +} + +bool ArgvMap::parmIsset(const string &var) +{ + return (params.find(var)!=params.end()); +} + +void ArgvMap::parseOne(const string &arg, const string &parseOnly, bool lax) +{ + string var, val; + string::size_type pos; + bool incremental = false; + + if(arg.find("--") == 0 && (pos=arg.find("+="))!=string::npos) // this is a --port+=25 case + { + var=arg.substr(2,pos-2); + val=arg.substr(pos+2); + incremental = true; + } + else if(arg.find("--") == 0 && (pos=arg.find("="))!=string::npos) // this is a --port=25 case + { + var=arg.substr(2,pos-2); + val=arg.substr(pos+1); + } + else if(arg.find("--") == 0 && (arg.find("=")==string::npos)) // this is a --daemon case + { + var=arg.substr(2); + val=""; + } + else if(arg[0]=='-') + { + var=arg.substr(1); + val=""; + } + else // command + d_cmds.push_back(arg); + + boost::trim(var); + + if(var!="" && (parseOnly.empty() || var==parseOnly)) { + pos=val.find_first_not_of(" \t"); // strip leading whitespace + if(pos && pos!=string::npos) + val=val.substr(pos); + if(parmIsset(var)) + { + if(incremental) + { + if(params[var].empty()) + { + if(!d_cleared.count(var)) + throw ArgException("Incremental parameter '"+var+"' without a parent"); + params[var]=val; + } + else + params[var]+=", " + val; + } + else + { + params[var]=val; + d_cleared.insert(var); + } + } + else if(!lax) + throw ArgException("Trying to set unknown parameter '"+var+"'"); + } +} + +const vector&ArgvMap::getCommands() +{ + return d_cmds; +} + +void ArgvMap::parse(int &argc, char **argv, bool lax) +{ + d_cmds.clear(); + d_cleared.clear(); + for(int n=1;n extraConfigs; + gatherIncludes(extraConfigs); + for(const std::string& fn : extraConfigs) { + if (!file(fn.c_str(), lax, true)) { + g_log << Logger::Error << fn << " could not be parsed" << std::endl; + throw ArgException(fn + " could not be parsed"); + } + } + } + + return true; +} + +void ArgvMap::gatherIncludes(std::vector &extraConfigs) { + extraConfigs.clear(); + if (params["include-dir"].empty()) return; // nothing to do + struct stat st; + DIR *dir; + struct dirent *ent; + + // stat + if (stat(params["include-dir"].c_str(), &st)) { + g_log << Logger::Error << params["include-dir"] << " does not exist!" << std::endl; + throw ArgException(params["include-dir"] + " does not exist!"); + } + + // wonder if it's accessible directory + if (!S_ISDIR(st.st_mode)) { + g_log << Logger::Error << params["include-dir"] << " is not a directory" << std::endl; + throw ArgException(params["include-dir"] + " is not a directory"); + } + + if (!(dir = opendir(params["include-dir"].c_str()))) { + g_log << Logger::Error << params["include-dir"] << " is not accessible" << std::endl; + throw ArgException(params["include-dir"] + " is not accessible"); + } + + while((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') continue; // skip any dots + if (boost::ends_with(ent->d_name, ".conf")) { + // build name + std::ostringstream namebuf; + namebuf << params["include-dir"].c_str() << "/" << ent->d_name; // FIXME: Use some path separator + // ensure it's readable file + if (stat(namebuf.str().c_str(), &st) || !S_ISREG(st.st_mode)) { + g_log << Logger::Error << namebuf.str() << " is not a file" << std::endl; + closedir(dir); + throw ArgException(namebuf.str() + " does not exist!"); + } + extraConfigs.push_back(namebuf.str()); + } + } + std::sort(extraConfigs.begin(), extraConfigs.end(), CIStringComparePOSIX()); + closedir(dir); +} diff --git a/pdns/arguments.hh b/pdns/arguments.hh new file mode 100644 index 0000000..9370595 --- /dev/null +++ b/pdns/arguments.hh @@ -0,0 +1,133 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef ARGUMENTS_HH +#define ARGUMENTS_HH + +#include +#include +#include +#include +#include +#include +#include "misc.hh" +#include "pdnsexception.hh" +#include +#include +#include + +#include "namespaces.hh" + +typedef PDNSException ArgException; + +/** This class helps parsing argc and argv into a map of parameters. We have 3 kinds of formats: + + + -w this leads to a key/value pair of "w"/void + + --port=25 "port"/"25" + + --daemon "daemon"/void + + We do not support "--port 25" syntax. + + It can also read from a file. This file can contain '#' to delimit comments. + + Some sample code: + + \code + + ArgvMap R; + + R.set("port")="25"; // use this to specify default parameters + R.file("./default.conf"); // parse configuration file + + R.parse(argc, argv); // read the arguments from main() + + cout<<"Will we be a daemon?: "<::const_iterator i; + cout<<"via iterator"<first<<"="<second< param_t; //!< use this if you need to know the content of the map + bool parmIsset(const string &var); //!< Checks if a parameter is set to *a* value + bool mustDo(const string &var); //!< if a switch is given, if we must do something (--help) + int asNum(const string &var, int def=0); //!< return a variable value as a number or the default if the variable is empty + mode_t asMode(const string &var); //!< return value interpreted as octal number + uid_t asUid(const string &var); //!< return user id, resolves if necessary + gid_t asGid(const string &var); //!< return group id, resolves if necessary + double asDouble(const string &var); //!< return a variable value as a number + string &set(const string &); //!< Gives a writable reference and allocates space for it + string &set(const string &, const string &); //!< Does the same but also allows one to specify a help message + void setCmd(const string &, const string &); //!< Add a command flag + string &setSwitch(const string &, const string &); //!< Add a command flag + string helpstring(string prefix=""); //!< generates the --help + string configstring(bool current=false); //!< generates the --mkconfig + bool contains(const string &var, const string &val); + bool isEmpty(const string &var); //!< checks if variable has value + + vectorlist(); + string getHelp(const string &item); + + const param_t::const_iterator begin(); //!< iterator semantics + const param_t::const_iterator end(); //!< iterator semantics + const string &operator[](const string &); //!< iterator semantics + const vector&getCommands(); + void gatherIncludes(std::vector &extraConfigs); +private: + void parseOne(const string &unparsed, const string &parseOnly="", bool lax=false); + typedef map params_t; + params_t params; + map helpmap; + map d_typeMap; + vector d_cmds; + std::set d_cleared; +}; + +extern ArgvMap &arg(); + +#endif /* ARGUMENTS_HH */ diff --git a/pdns/ascii.hh b/pdns/ascii.hh new file mode 100644 index 0000000..09f42de --- /dev/null +++ b/pdns/ascii.hh @@ -0,0 +1,41 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +inline bool dns_isspace(char c) +{ + return c==' ' || c=='\t' || c=='\r' || c=='\n'; +} + +inline unsigned char dns_toupper(unsigned char c) +{ + if(c>='a' && c<='z') + c+='A'-'a'; + return c; +} + +inline unsigned char dns_tolower(unsigned char c) +{ + if(c>='A' && c<='Z') + c+='a'-'A'; + return c; +} diff --git a/pdns/auth-caches.cc b/pdns/auth-caches.cc new file mode 100644 index 0000000..c33575a --- /dev/null +++ b/pdns/auth-caches.cc @@ -0,0 +1,57 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "auth-querycache.hh" +#include "auth-packetcache.hh" + +extern AuthPacketCache PC; +extern AuthQueryCache QC; + +/* empty all caches */ +uint64_t purgeAuthCaches() +{ + uint64_t ret = 0; + ret += PC.purge(); + ret += QC.purge(); + return ret; +} + + /* remove specific entries from all caches, can be $ terminated */ +uint64_t purgeAuthCaches(const std::string& match) +{ + uint64_t ret = 0; + ret += PC.purge(match); + ret += QC.purge(match); + return ret; +} + +/* remove specific entries from all caches, no wildcard matching */ +uint64_t purgeAuthCachesExact(const DNSName& qname) +{ + uint64_t ret = 0; + ret += PC.purgeExact(qname); + ret += QC.purgeExact(qname); + return ret; +} + + + diff --git a/pdns/auth-caches.hh b/pdns/auth-caches.hh new file mode 100644 index 0000000..76c248f --- /dev/null +++ b/pdns/auth-caches.hh @@ -0,0 +1,34 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef AUTH_CACHES_HH +#define AUTH_CACHES_HH + +#include +#include + +#include "dnsname.hh" + +uint64_t purgeAuthCaches(); /* empty all caches */ +uint64_t purgeAuthCaches(const std::string& match); /* remove specific entries from all caches, can be $ terminated */ +uint64_t purgeAuthCachesExact(const DNSName& qname); /* remove specific entries from all caches, no wildcard matching */ + +#endif /* AUTH_CACHES_HH */ diff --git a/pdns/auth-carbon.cc b/pdns/auth-carbon.cc new file mode 100644 index 0000000..4d0cfcb --- /dev/null +++ b/pdns/auth-carbon.cc @@ -0,0 +1,104 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "statbag.hh" +#include "logger.hh" +#include "threadname.hh" +#include "iputils.hh" +#include "sstuff.hh" +#include "arguments.hh" +#include "common_startup.hh" + +#include "namespaces.hh" + +void* carbonDumpThread(void*) +try +{ + setThreadName("pdns/carbonDump"); + extern StatBag S; + + string namespace_name=arg()["carbon-namespace"]; + string hostname=arg()["carbon-ourname"]; + if(hostname.empty()) { + char tmp[80]; + memset(tmp, 0, sizeof(tmp)); + gethostname(tmp, sizeof(tmp)); + char *p = strchr(tmp, '.'); + if(p) *p=0; + hostname=tmp; + boost::replace_all(hostname, ".", "_"); + } + string instance_name=arg()["carbon-instance"]; + + vector carbonServers; + stringtok(carbonServers, arg()["carbon-server"], ", "); + + for(;;) { + if(carbonServers.empty()) { + sleep(1); + continue; + } + + string msg; + vector entries = S.getEntries(); + ostringstream str; + time_t now=time(0); + for(const string& entry : entries) { + str< locks; + for(auto& mc : d_maps) { + locks.push_back(new WriteLock(&mc.d_mut)); + } + for(auto wl : locks) { + delete wl; + } + } + catch(...) { + } +} + +bool AuthPacketCache::get(DNSPacket *p, DNSPacket *cached) +{ + if(!d_ttl) { + return false; + } + + cleanupIfNeeded(); + + uint32_t hash = canHashPacket(p->getString()); + p->setHash(hash); + + string value; + bool haveSomething; + time_t now = time(nullptr); + auto& mc = getMap(p->qdomain); + { + TryReadLock rl(&mc.d_mut); + if(!rl.gotIt()) { + S.inc("deferred-packetcache-lookup"); + return false; + } + + haveSomething = getEntryLocked(mc.d_map, p->getString(), hash, p->qdomain, p->qtype.getCode(), p->d_tcp, now, value); + } + + if (!haveSomething) { + (*d_statnummiss)++; + return false; + } + + if(cached->noparse(value.c_str(), value.size()) < 0) { + return false; + } + + (*d_statnumhit)++; + cached->spoofQuestion(p); // for correct case + cached->qdomain = p->qdomain; + cached->qtype = p->qtype; + + return true; +} + +bool AuthPacketCache::entryMatches(cmap_t::index::type::iterator& iter, const std::string& query, const DNSName& qname, uint16_t qtype, bool tcp) +{ + return iter->tcp == tcp && iter->qtype == qtype && iter->qname == qname && queryMatches(iter->query, query, qname); +} + +void AuthPacketCache::insert(DNSPacket *q, DNSPacket *r, unsigned int maxTTL) +{ + if(!d_ttl) { + return; + } + + cleanupIfNeeded(); + + if (ntohs(q->d.qdcount) != 1) { + return; // do not try to cache packets with multiple questions + } + + if (q->qclass != QClass::IN) // we only cache the INternet + return; + + uint32_t ourttl = std::min(d_ttl, maxTTL); + if (ourttl == 0) { + return; + } + + uint32_t hash = q->getHash(); + time_t now = time(nullptr); + CacheEntry entry; + entry.hash = hash; + entry.created = now; + entry.ttd = now + ourttl; + entry.qname = q->qdomain; + entry.qtype = q->qtype.getCode(); + entry.value = r->getString(); + entry.tcp = r->d_tcp; + entry.query = q->getString(); + + auto& mc = getMap(entry.qname); + { + TryWriteLock l(&mc.d_mut); + if (!l.gotIt()) { + S.inc("deferred-packetcache-inserts"); + return; + } + + auto& idx = mc.d_map.get(); + auto range = idx.equal_range(hash); + auto iter = range.first; + + for( ; iter != range.second ; ++iter) { + if (!entryMatches(iter, entry.query, entry.qname, entry.qtype, entry.tcp)) { + continue; + } + + iter->value = entry.value; + iter->ttd = now + ourttl; + iter->created = now; + return; + } + + /* no existing entry found to refresh */ + mc.d_map.insert(entry); + (*d_statnumentries)++; + } +} + +bool AuthPacketCache::getEntryLocked(cmap_t& map, const std::string& query, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& value) +{ + auto& idx = map.get(); + auto range = idx.equal_range(hash); + + for(auto iter = range.first; iter != range.second ; ++iter) { + if (iter->ttd < now) { + continue; + } + + if (!entryMatches(iter, query, qname, qtype, tcp)) { + continue; + } + + value = iter->value; + return true; + } + + return false; +} + +/* clears the entire cache. */ +uint64_t AuthPacketCache::purge() +{ + if(!d_ttl) { + return 0; + } + + d_statnumentries->store(0); + + return purgeLockedCollectionsVector(d_maps); +} + +uint64_t AuthPacketCache::purgeExact(const DNSName& qname) +{ + auto& mc = getMap(qname); + uint64_t delcount = purgeExactLockedCollection(mc, qname); + + *d_statnumentries -= delcount; + + return delcount; +} + +/* purges entries from the packetcache. If match ends on a $, it is treated as a suffix */ +uint64_t AuthPacketCache::purge(const string &match) +{ + if(!d_ttl) { + return 0; + } + + uint64_t delcount = 0; + + if(ends_with(match, "$")) { + delcount = purgeLockedCollectionsVector(d_maps, match); + *d_statnumentries -= delcount; + } + else { + delcount = purgeExact(DNSName(match)); + } + + return delcount; +} + +void AuthPacketCache::cleanup() +{ + uint64_t maxCached = d_maxEntries; + uint64_t cacheSize = *d_statnumentries; + uint64_t totErased = 0; + + totErased = pruneLockedCollectionsVector(d_maps, maxCached, cacheSize); + *d_statnumentries -= totErased; + + DLOG(g_log<<"Done with cache clean, cacheSize: "<<(*d_statnumentries)<<", totErased"< +#include +#include "dns.hh" +#include +#include "namespaces.hh" +using namespace ::boost::multi_index; + +#include + +#include "dnspacket.hh" +#include "lock.hh" +#include "packetcache.hh" + +/** This class performs 'whole packet caching'. Feed it a question packet and it will + try to find an answer. If you have an answer, insert it to have it cached for later use. + Take care not to replace existing cache entries. While this works, it is wasteful. Only + insert packets that where not found by get() + + Locking! + + The cache itself is protected by a read/write lock. Because deleting is a two step process, which + first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes. +*/ + +class AuthPacketCache : public PacketCache +{ +public: + AuthPacketCache(size_t mapsCount=1024); + ~AuthPacketCache(); + + void insert(DNSPacket *q, DNSPacket *r, uint32_t maxTTL); //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources + + bool get(DNSPacket *p, DNSPacket *q); //!< We return a dynamically allocated copy out of our cache. You need to delete it. You also need to spoof in the right ID with the DNSPacket.spoofID() method. + + void cleanup(); //!< force the cache to preen itself from expired packets + uint64_t purge(); + uint64_t purge(const std::string& match); // could be $ terminated. Is not a dnsname! + uint64_t purgeExact(const DNSName& qname); // no wildcard matching here + + uint64_t size() const { return *d_statnumentries; }; + + void setMaxEntries(uint64_t maxEntries) + { + d_maxEntries = maxEntries; + } + void setTTL(uint32_t ttl) + { + d_ttl = ttl; + } + bool enabled() + { + return (d_ttl > 0); + } +private: + + struct CacheEntry + { + mutable string query; + mutable string value; + DNSName qname; + + mutable time_t created{0}; + mutable time_t ttd{0}; + uint32_t hash{0}; + uint16_t qtype{0}; + bool tcp{false}; + }; + + struct HashTag{}; + struct NameTag{}; + struct SequenceTag{}; + typedef multi_index_container< + CacheEntry, + indexed_by < + hashed_non_unique, member >, + ordered_non_unique, member, CanonDNSNameCompare >, + sequenced> + > + > cmap_t; + + struct MapCombo + { + pthread_rwlock_t d_mut; + cmap_t d_map; + }; + + vector d_maps; + MapCombo& getMap(const DNSName& name) + { + return d_maps[name.hash() % d_maps.size()]; + } + + static bool entryMatches(cmap_t::index::type::iterator& iter, const std::string& query, const DNSName& qname, uint16_t qtype, bool tcp); + bool getEntryLocked(cmap_t& map, const std::string& query, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& entry); + void cleanupIfNeeded(); + + AtomicCounter d_ops{0}; + AtomicCounter *d_statnumhit; + AtomicCounter *d_statnummiss; + AtomicCounter *d_statnumentries; + + uint64_t d_maxEntries{0}; + time_t d_lastclean; // doesn't need to be atomic + unsigned long d_nextclean{4096}; + unsigned int d_cleaninterval{4096}; + uint32_t d_ttl{0}; + bool d_cleanskipped{false}; + + static const unsigned int s_mincleaninterval=1000, s_maxcleaninterval=300000; +}; + +#endif /* AUTH_PACKETCACHE_HH */ diff --git a/pdns/auth-querycache.cc b/pdns/auth-querycache.cc new file mode 100644 index 0000000..033ed32 --- /dev/null +++ b/pdns/auth-querycache.cc @@ -0,0 +1,251 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "auth-querycache.hh" +#include "logger.hh" +#include "statbag.hh" +#include "cachecleaner.hh" +extern StatBag S; + +const unsigned int AuthQueryCache::s_mincleaninterval, AuthQueryCache::s_maxcleaninterval; + +AuthQueryCache::AuthQueryCache(size_t mapsCount): d_lastclean(time(nullptr)) +{ + d_maps.resize(mapsCount); + for(auto& mc : d_maps) { + pthread_rwlock_init(&mc.d_mut, 0); + } + + S.declare("query-cache-hit","Number of hits on the query cache"); + S.declare("query-cache-miss","Number of misses on the query cache"); + S.declare("query-cache-size", "Number of entries in the query cache"); + S.declare("deferred-cache-inserts","Amount of cache inserts that were deferred because of maintenance"); + S.declare("deferred-cache-lookup","Amount of cache lookups that were deferred because of maintenance"); + + d_statnumhit=S.getPointer("query-cache-hit"); + d_statnummiss=S.getPointer("query-cache-miss"); + d_statnumentries=S.getPointer("query-cache-size"); +} + +AuthQueryCache::~AuthQueryCache() +{ + try { + vector locks; + for(auto& mc : d_maps) { + locks.push_back(new WriteLock(&mc.d_mut)); + } + for(auto wl : locks) { + delete wl; + } + } + catch(...) { + } +} + +// called from ueberbackend +bool AuthQueryCache::getEntry(const DNSName &qname, const QType& qtype, vector& value, int zoneID) +{ + cleanupIfNeeded(); + + time_t now = time(nullptr); + uint16_t qt = qtype.getCode(); + auto& mc = getMap(qname); + { + TryReadLock rl(&mc.d_mut); + if(!rl.gotIt()) { + S.inc("deferred-cache-lookup"); + return false; + } + + return getEntryLocked(mc.d_map, qname, qt, value, zoneID, now); + } +} + +void AuthQueryCache::insert(const DNSName &qname, const QType& qtype, const vector& value, uint32_t ttl, int zoneID) +{ + cleanupIfNeeded(); + + if(!ttl) + return; + + time_t now = time(nullptr); + CacheEntry val; + val.created = now; + val.ttd = now + ttl; + val.qname = qname; + val.qtype = qtype.getCode(); + val.drs = value; + val.zoneID = zoneID; + + auto& mc = getMap(val.qname); + + { + TryWriteLock l(&mc.d_mut); + if(!l.gotIt()) { + S.inc("deferred-cache-inserts"); + return; + } + + bool inserted; + cmap_t::iterator place; + tie(place, inserted) = mc.d_map.insert(val); + + if (!inserted) { + mc.d_map.replace(place, val); + } + else { + (*d_statnumentries)++; + } + } +} + +bool AuthQueryCache::getEntryLocked(cmap_t& map, const DNSName &qname, uint16_t qtype, vector& value, int zoneID, time_t now) +{ + auto& idx = boost::multi_index::get(map); + auto iter = idx.find(tie(qname, qtype, zoneID)); + + if (iter == idx.end()) { + (*d_statnummiss)++; + return false; + } + + if (iter->ttd < now) { + (*d_statnummiss)++; + return false; + } + + value = iter->drs; + (*d_statnumhit)++; + return true; +} + +map AuthQueryCache::getCounts() +{ + uint64_t queryCacheEntries=0, negQueryCacheEntries=0; + + for(auto& mc : d_maps) { + ReadLock l(&mc.d_mut); + + for(cmap_t::const_iterator iter = mc.d_map.begin() ; iter != mc.d_map.end(); ++iter) { + if(iter->drs.empty()) + negQueryCacheEntries++; + else + queryCacheEntries++; + } + } + map ret; + + ret['!']=negQueryCacheEntries; + ret['Q']=queryCacheEntries; + return ret; +} + +/* clears the entire cache. */ +uint64_t AuthQueryCache::purge() +{ + d_statnumentries->store(0); + + return purgeLockedCollectionsVector(d_maps); +} + +uint64_t AuthQueryCache::purgeExact(const DNSName& qname) +{ + auto& mc = getMap(qname); + uint64_t delcount = purgeExactLockedCollection(mc, qname); + + *d_statnumentries -= delcount; + + return delcount; +} + +/* purges entries from the querycache. If match ends on a $, it is treated as a suffix */ +uint64_t AuthQueryCache::purge(const string &match) +{ + uint64_t delcount = 0; + + if(ends_with(match, "$")) { + delcount = purgeLockedCollectionsVector(d_maps, match); + *d_statnumentries -= delcount; + } + else { + delcount = purgeExact(DNSName(match)); + } + + return delcount; +} + +void AuthQueryCache::cleanup() +{ + uint64_t maxCached = d_maxEntries; + uint64_t cacheSize = *d_statnumentries; + uint64_t totErased = 0; + + totErased = pruneLockedCollectionsVector(d_maps, maxCached, cacheSize); + + *d_statnumentries -= totErased; + DLOG(g_log<<"Done with cache clean, cacheSize: "<<*d_statnumentries<<", totErased"< +#include +#include "dns.hh" +#include +#include "namespaces.hh" +using namespace ::boost::multi_index; + +#include + +#include "dns.hh" +#include "dnspacket.hh" +#include "lock.hh" + +class AuthQueryCache : public boost::noncopyable +{ +public: + AuthQueryCache(size_t mapsCount=1024); + ~AuthQueryCache(); + + void insert(const DNSName &qname, const QType& qtype, const vector& content, uint32_t ttl, int zoneID); + + bool getEntry(const DNSName &qname, const QType& qtype, vector& entry, int zoneID); + + size_t size() { return *d_statnumentries; } //!< number of entries in the cache + void cleanup(); //!< force the cache to preen itself from expired querys + uint64_t purge(); + uint64_t purge(const std::string& match); // could be $ terminated. Is not a dnsname! + uint64_t purgeExact(const DNSName& qname); // no wildcard matching here + + map getCounts(); + + void setMaxEntries(uint64_t maxEntries) + { + d_maxEntries = maxEntries; + } +private: + + struct CacheEntry + { + DNSName qname; + mutable vector drs; + mutable time_t created{0}; + mutable time_t ttd{0}; + uint16_t qtype{0}; + int zoneID{-1}; + }; + + struct HashTag{}; + struct NameTag{}; + struct SequenceTag{}; + typedef multi_index_container< + CacheEntry, + indexed_by < + hashed_unique, composite_key, + member, + member > > , + ordered_non_unique, member, CanonDNSNameCompare >, + sequenced> + > + > cmap_t; + + + struct MapCombo + { + pthread_rwlock_t d_mut; + cmap_t d_map; + }; + + vector d_maps; + MapCombo& getMap(const DNSName& qname) + { + return d_maps[qname.hash() % d_maps.size()]; + } + + bool getEntryLocked(cmap_t& map, const DNSName &content, uint16_t qtype, vector& entry, int zoneID, time_t now); + void cleanupIfNeeded(); + + AtomicCounter d_ops{0}; + AtomicCounter *d_statnumhit; + AtomicCounter *d_statnummiss; + AtomicCounter *d_statnumentries; + + uint64_t d_maxEntries{0}; + time_t d_lastclean; // doesn't need to be atomic + unsigned long d_nextclean{4096}; + unsigned int d_cleaninterval{4096}; + bool d_cleanskipped{false}; + + static const unsigned int s_mincleaninterval=1000, s_maxcleaninterval=300000; +}; + +#endif /* AUTH_QUERYCACHE_HH */ diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc new file mode 100644 index 0000000..0f13175 --- /dev/null +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -0,0 +1,1793 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "pdns/dns.hh" +#include "pdns/dnsbackend.hh" +#include "gsqlbackend.hh" +#include "pdns/dnspacket.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/base32.hh" +#include "pdns/dnssecinfra.hh" +#include +#include +#include +#include + +#define ASSERT_ROW_COLUMNS(query, row, num) { if (row.size() != num) { throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); } } + +GSQLBackend::GSQLBackend(const string &mode, const string &suffix) +{ + setArgPrefix(mode+suffix); + d_db=0; + d_logprefix="["+mode+"Backend"+suffix+"] "; + + try + { + d_dnssecQueries = mustDo("dnssec"); + } + catch (const ArgException&) + { + d_dnssecQueries = false; + } + + d_NoIdQuery=getArg("basic-query"); + d_IdQuery=getArg("id-query"); + d_ANYNoIdQuery=getArg("any-query"); + d_ANYIdQuery=getArg("any-id-query"); + + d_listQuery=getArg("list-query"); + d_listSubZoneQuery=getArg("list-subzone-query"); + + d_InfoOfDomainsZoneQuery=getArg("info-zone-query"); + d_InfoOfAllSlaveDomainsQuery=getArg("info-all-slaves-query"); + d_SuperMasterInfoQuery=getArg("supermaster-query"); + d_GetSuperMasterIPs=getArg("supermaster-name-to-ips"); + d_InsertZoneQuery=getArg("insert-zone-query"); + d_InsertRecordQuery=getArg("insert-record-query"); + d_UpdateMasterOfZoneQuery=getArg("update-master-query"); + d_UpdateKindOfZoneQuery=getArg("update-kind-query"); + d_UpdateSerialOfZoneQuery=getArg("update-serial-query"); + d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query"); + d_UpdateAccountOfZoneQuery=getArg("update-account-query"); + d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query"); + d_DeleteDomainQuery=getArg("delete-domain-query"); + d_DeleteZoneQuery=getArg("delete-zone-query"); + d_DeleteRRSetQuery=getArg("delete-rrset-query"); + d_DeleteNamesQuery=getArg("delete-names-query"); + d_getAllDomainsQuery=getArg("get-all-domains-query"); + + d_InsertEmptyNonTerminalOrderQuery=getArg("insert-empty-non-terminal-order-query"); + d_DeleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query"); + d_RemoveEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query"); + + d_ListCommentsQuery = getArg("list-comments-query"); + d_InsertCommentQuery = getArg("insert-comment-query"); + d_DeleteCommentRRsetQuery = getArg("delete-comment-rrset-query"); + d_DeleteCommentsQuery = getArg("delete-comments-query"); + + d_firstOrderQuery = getArg("get-order-first-query"); + d_beforeOrderQuery = getArg("get-order-before-query"); + d_afterOrderQuery = getArg("get-order-after-query"); + d_lastOrderQuery = getArg("get-order-last-query"); + + d_updateOrderNameAndAuthQuery = getArg("update-ordername-and-auth-query"); + d_updateOrderNameAndAuthTypeQuery = getArg("update-ordername-and-auth-type-query"); + d_nullifyOrderNameAndUpdateAuthQuery = getArg("nullify-ordername-and-update-auth-query"); + d_nullifyOrderNameAndUpdateAuthTypeQuery = getArg("nullify-ordername-and-update-auth-type-query"); + + d_AddDomainKeyQuery = getArg("add-domain-key-query"); + d_GetLastInsertedKeyIdQuery = getArg("get-last-inserted-key-id-query"); + d_ListDomainKeysQuery = getArg("list-domain-keys-query"); + + d_GetAllDomainMetadataQuery = getArg("get-all-domain-metadata-query"); + d_GetDomainMetadataQuery = getArg("get-domain-metadata-query"); + d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query"); + d_ClearDomainAllMetadataQuery = getArg("clear-domain-all-metadata-query"); + d_SetDomainMetadataQuery = getArg("set-domain-metadata-query"); + + d_ActivateDomainKeyQuery = getArg("activate-domain-key-query"); + d_DeactivateDomainKeyQuery = getArg("deactivate-domain-key-query"); + d_RemoveDomainKeyQuery = getArg("remove-domain-key-query"); + d_ClearDomainAllKeysQuery = getArg("clear-domain-all-keys-query"); + + d_getTSIGKeyQuery = getArg("get-tsig-key-query"); + d_setTSIGKeyQuery = getArg("set-tsig-key-query"); + d_deleteTSIGKeyQuery = getArg("delete-tsig-key-query"); + d_getTSIGKeysQuery = getArg("get-tsig-keys-query"); + + d_SearchRecordsQuery = getArg("search-records-query"); + d_SearchCommentsQuery = getArg("search-comments-query"); + + d_query_stmt = NULL; + d_NoIdQuery_stmt = NULL; + d_IdQuery_stmt = NULL; + d_ANYNoIdQuery_stmt = NULL; + d_ANYIdQuery_stmt = NULL; + d_listQuery_stmt = NULL; + d_listSubZoneQuery_stmt = NULL; + d_InfoOfDomainsZoneQuery_stmt = NULL; + d_InfoOfAllSlaveDomainsQuery_stmt = NULL; + d_SuperMasterInfoQuery_stmt = NULL; + d_GetSuperMasterIPs_stmt = NULL; + d_InsertZoneQuery_stmt = NULL; + d_InsertRecordQuery_stmt = NULL; + d_InsertEmptyNonTerminalOrderQuery_stmt = NULL; + d_UpdateMasterOfZoneQuery_stmt = NULL; + d_UpdateKindOfZoneQuery_stmt = NULL; + d_UpdateSerialOfZoneQuery_stmt = NULL; + d_UpdateLastCheckofZoneQuery_stmt = NULL; + d_UpdateAccountOfZoneQuery_stmt = NULL; + d_InfoOfAllMasterDomainsQuery_stmt = NULL; + d_DeleteDomainQuery_stmt = NULL; + d_DeleteZoneQuery_stmt = NULL; + d_DeleteRRSetQuery_stmt = NULL; + d_DeleteNamesQuery_stmt = NULL; + d_firstOrderQuery_stmt = NULL; + d_beforeOrderQuery_stmt = NULL; + d_afterOrderQuery_stmt = NULL; + d_lastOrderQuery_stmt = NULL; + d_updateOrderNameAndAuthQuery_stmt = NULL; + d_updateOrderNameAndAuthTypeQuery_stmt = NULL; + d_nullifyOrderNameAndUpdateAuthQuery_stmt = NULL; + d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt = NULL; + d_RemoveEmptyNonTerminalsFromZoneQuery_stmt = NULL; + d_DeleteEmptyNonTerminalQuery_stmt = NULL; + d_AddDomainKeyQuery_stmt = NULL; + d_GetLastInsertedKeyIdQuery_stmt = NULL; + d_ListDomainKeysQuery_stmt = NULL; + d_GetAllDomainMetadataQuery_stmt = NULL; + d_GetDomainMetadataQuery_stmt = NULL; + d_ClearDomainMetadataQuery_stmt = NULL; + d_ClearDomainAllMetadataQuery_stmt = NULL; + d_SetDomainMetadataQuery_stmt = NULL; + d_RemoveDomainKeyQuery_stmt = NULL; + d_ActivateDomainKeyQuery_stmt = NULL; + d_DeactivateDomainKeyQuery_stmt = NULL; + d_ClearDomainAllKeysQuery_stmt = NULL; + d_getTSIGKeyQuery_stmt = NULL; + d_setTSIGKeyQuery_stmt = NULL; + d_deleteTSIGKeyQuery_stmt = NULL; + d_getTSIGKeysQuery_stmt = NULL; + d_getAllDomainsQuery_stmt = NULL; + d_ListCommentsQuery_stmt = NULL; + d_InsertCommentQuery_stmt = NULL; + d_DeleteCommentRRsetQuery_stmt = NULL; + d_DeleteCommentsQuery_stmt = NULL; + d_SearchRecordsQuery_stmt = NULL; + d_SearchCommentsQuery_stmt = NULL; +} + +void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial) +{ + try { + reconnectIfNeeded(); + + d_UpdateSerialOfZoneQuery_stmt-> + bind("serial", serial)-> + bind("domain_id", domain_id)-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason()); + } +} + +void GSQLBackend::setFresh(uint32_t domain_id) +{ + try { + reconnectIfNeeded(); + + d_UpdateLastCheckofZoneQuery_stmt-> + bind("last_check", time(0))-> + bind("domain_id", domain_id)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason()); + } +} + +bool GSQLBackend::setMaster(const DNSName &domain, const string &ip) +{ + try { + reconnectIfNeeded(); + + d_UpdateMasterOfZoneQuery_stmt-> + bind("master", ip)-> + bind("domain", domain)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to set master of domain '"+domain.toLogString()+"' to IP address " + ip + ": "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind) +{ + try { + reconnectIfNeeded(); + + d_UpdateKindOfZoneQuery_stmt-> + bind("kind", toUpper(DomainInfo::getKindString(kind)))-> + bind("domain", domain)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to set kind of domain '"+domain.toLogString()+"' to " + toUpper(DomainInfo::getKindString(kind)) + ": "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::setAccount(const DNSName &domain, const string &account) +{ + try { + reconnectIfNeeded(); + + d_UpdateAccountOfZoneQuery_stmt-> + bind("account", account)-> + bind("domain", domain)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to set account of domain '"+domain.toLogString()+"' to '" + account + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial) +{ + /* fill DomainInfo from database info: + id,name,master IP(s),last_check,notified_serial,type,account */ + try { + reconnectIfNeeded(); + + d_InfoOfDomainsZoneQuery_stmt-> + bind("domain", domain)-> + execute()-> + getResult(d_result)-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to retrieve information about domain '" + domain.toLogString() + "': "+e.txtReason()); + } + + int numanswers=d_result.size(); + if(!numanswers) + return false; + + ASSERT_ROW_COLUMNS("info-zone-query", d_result[0], 7); + + di.id=pdns_stou(d_result[0][0]); + try { + di.zone=DNSName(d_result[0][1]); + } catch (...) { + return false; + } + string type=d_result[0][5]; + di.account=d_result[0][6]; + di.kind = DomainInfo::stringToKind(type); + + vector masters; + stringtok(masters, d_result[0][2], " ,\t"); + for(const auto& m : masters) + di.masters.emplace_back(m, 53); + di.last_check=pdns_stou(d_result[0][3]); + di.notified_serial = pdns_stou(d_result[0][4]); + di.backend=this; + + di.serial = 0; + if(getSerial) { + try { + SOAData sd; + if(!getSOA(domain, sd)) + g_log< *unfreshDomains) +{ + /* list all domains that need refreshing for which we are slave, and insert into SlaveDomain: + id,name,master IP,serial */ + try { + reconnectIfNeeded(); + + d_InfoOfAllSlaveDomainsQuery_stmt-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to retrieve list of slave domains: "+e.txtReason()); + } + + vector allSlaves; + + bool loggedAssertRowColumns = false; + for(const auto& row : d_result) { // id,name,master,last_check + DomainInfo sd; + try { + ASSERT_ROW_COLUMNS("info-all-slaves-query", row, 4); + } catch(const PDNSException &e) { + if (!loggedAssertRowColumns) { + g_log< masters; + stringtok(masters, row[2], ", \t"); + for(const auto& m : masters) { + try { + sd.masters.emplace_back(m, 53); + } catch(const PDNSException &e) { + g_log<(slave.last_check + sdata.refresh) < time(nullptr)) { + slave.serial=sdata.serial; + unfreshDomains->push_back(slave); + } + } + catch(const std::exception& exp) { + g_log< *updatedDomains) +{ + /* list all domains that need notifications for which we are master, and insert into updatedDomains + id, name, notified_serial, serial */ + try { + reconnectIfNeeded(); + + d_InfoOfAllMasterDomainsQuery_stmt-> + execute()-> + getResult(d_result)-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason()); + } + + size_t numanswers=d_result.size(); + vectorparts; + DomainInfo di; + + di.backend = this; + di.kind = DomainInfo::Master; + + for( size_t n = 0; n < numanswers; ++n ) { // id, name, notified_serial, content + ASSERT_ROW_COLUMNS( "info-all-master-query", d_result[n], 4 ); + + parts.clear(); + stringtok( parts, d_result[n][3] ); + + try { + uint32_t serial = parts.size() > 2 ? pdns_stou(parts[2]) : 0; + uint32_t notified_serial = pdns_stou( d_result[n][2] ); + + if( serial != notified_serial ) { + di.id = pdns_stou( d_result[n][0] ); + di.zone = DNSName( d_result[n][1] ); + di.serial = serial; + di.notified_serial = notified_serial; + + updatedDomains->emplace_back(di); + } + } catch ( ... ) { + continue; + } + } +} + +bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype) +{ + if(!d_dnssecQueries) + return false; + + if (!ordername.empty()) { + if (qtype == QType::ANY) { + try { + reconnectIfNeeded(); + + d_updateOrderNameAndAuthQuery_stmt-> + bind("ordername", ordername.labelReverse().toString(" ", false))-> + bind("auth", auth)-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to update ordername and auth for " + qname.toLogString() + " for domain_id "+itoa(domain_id)+", domain name '" + qname.toLogString() + "': "+e.txtReason()); + } + } else { + try { + reconnectIfNeeded(); + + d_updateOrderNameAndAuthTypeQuery_stmt-> + bind("ordername", ordername.labelReverse().toString(" ", false))-> + bind("auth", auth)-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + bind("qtype", QType(qtype).getName())-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to update ordername and auth for " + qname.toLogString() + "|" + QType(qtype).getName() + " for domain_id "+itoa(domain_id)+": "+e.txtReason()); + } + } + } else { + if (qtype == QType::ANY) { + reconnectIfNeeded(); + + try { + d_nullifyOrderNameAndUpdateAuthQuery_stmt-> + bind("auth", auth)-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to nullify ordername and update auth for " + qname.toLogString() + " for domain_id "+itoa(domain_id)+": "+e.txtReason()); + } + } else { + try { + reconnectIfNeeded(); + + d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt-> + bind("auth", auth)-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + bind("qtype", QType(qtype).getName())-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to nullify ordername and update auth for " + qname.toLogString() + "|" + QType(qtype).getName() + " for domain_id "+itoa(domain_id)+": "+e.txtReason()); + } + } + } + return true; +} + +bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) +{ + if(remove) { + try { + reconnectIfNeeded(); + + d_RemoveEmptyNonTerminalsFromZoneQuery_stmt-> + bind("domain_id", domain_id)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete empty non-terminal records from domain_id "+itoa(domain_id)+": "+e.txtReason()); + return false; + } + } + else + { + for(const auto& qname: erase) { + try { + reconnectIfNeeded(); + + d_DeleteEmptyNonTerminalQuery_stmt-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete empty non-terminal rr '"+qname.toLogString()+"' from domain_id "+itoa(domain_id)+": "+e.txtReason()); + return false; + } + } + } + + for(const auto& qname: insert) { + try { + reconnectIfNeeded(); + + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + bindNull("ordername")-> + bind("auth", true)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to insert empty non-terminal rr '"+qname.toLogString()+"' in domain_id "+itoa(domain_id)+": "+e.txtReason()); + return false; + } + } + + return true; +} + +bool GSQLBackend::doesDNSSEC() +{ + return d_dnssecQueries; +} + +bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) +{ + if(!d_dnssecQueries) + return false; + after.clear(); + + SSqlStatement::row_t row; + try { + reconnectIfNeeded(); + + d_afterOrderQuery_stmt-> + bind("ordername", qname.labelReverse().toString(" ", false))-> + bind("domain_id", id)-> + execute(); + while(d_afterOrderQuery_stmt->hasNextRow()) { + d_afterOrderQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-order-after-query", row, 1); + if(! row[0].empty()) { // Hack because NULL values are passed on as empty strings + after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); + } + } + d_afterOrderQuery_stmt->reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to find before/after (after) for domain_id "+itoa(id)+" and qname '"+ qname.toLogString() +"': "+e.txtReason()); + } + + if(after.empty()) { + try { + reconnectIfNeeded(); + + d_firstOrderQuery_stmt-> + bind("domain_id", id)-> + execute(); + while(d_firstOrderQuery_stmt->hasNextRow()) { + d_firstOrderQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-order-first-query", row, 1); + after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); + } + d_firstOrderQuery_stmt->reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to find before/after (first) for domain_id "+itoa(id)+" and qname '"+ qname.toLogString() + "': "+e.txtReason()); + } + } + + if (before.empty()) { + unhashed.clear(); + + try { + reconnectIfNeeded(); + + d_beforeOrderQuery_stmt-> + bind("ordername", qname.labelReverse().toString(" ", false))-> + bind("domain_id", id)-> + execute(); + while(d_beforeOrderQuery_stmt->hasNextRow()) { + d_beforeOrderQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-order-before-query", row, 2); + before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); + try { + unhashed=DNSName(row[1]); + } catch (...) { + continue; + } + } + d_beforeOrderQuery_stmt->reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to find before/after (before) for domain_id "+itoa(id)+" and qname '"+ qname.toLogString() + ": "+e.txtReason()); + } + + if(! unhashed.empty()) + { + // cerr<<"unhashed="< + execute(); + while(d_lastOrderQuery_stmt->hasNextRow()) { + d_lastOrderQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-order-last-query", row, 2); + before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); + try { + unhashed=DNSName(row[1]); + } catch (...) { + continue; + } + } + d_lastOrderQuery_stmt->reset(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to find before/after (last) for domain_id "+itoa(id)+" and qname '"+ qname.toLogString() + ": "+e.txtReason()); + } + } else { + before=qname; + } + + return true; +} + +bool GSQLBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) +{ + if(!d_dnssecQueries) + return false; + + try { + reconnectIfNeeded(); + + d_AddDomainKeyQuery_stmt-> + bind("flags", key.flags)-> + bind("active", key.active)-> + bind("content", key.content)-> + bind("domain", name)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to store key for domain '"+ name.toLogString() + "': "+e.txtReason()); + } + + try { + reconnectIfNeeded(); + + d_GetLastInsertedKeyIdQuery_stmt->execute(); + if (!d_GetLastInsertedKeyIdQuery_stmt->hasNextRow()) { + id = -2; + return true; + } + SSqlStatement::row_t row; + d_GetLastInsertedKeyIdQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-last-inserted-key-id-query", row, 1); + id = std::stoi(row[0]); + d_GetLastInsertedKeyIdQuery_stmt->reset(); + return true; + } + catch (SSqlException &e) { + id = -2; + return true; + } + + return false; +} + +bool GSQLBackend::activateDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecQueries) + return false; + + try { + reconnectIfNeeded(); + + d_ActivateDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to activate key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::deactivateDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecQueries) + return false; + + try { + reconnectIfNeeded(); + + d_DeactivateDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to deactivate key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::removeDomainKey(const DNSName& name, unsigned int id) +{ + if(!d_dnssecQueries) + return false; + + try { + reconnectIfNeeded(); + + d_RemoveDomainKeyQuery_stmt-> + bind("domain", name)-> + bind("key_id", id)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to remove key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) +{ + try { + reconnectIfNeeded(); + + d_getTSIGKeyQuery_stmt-> + bind("key_name", name)-> + execute(); + + SSqlStatement::row_t row; + + content->clear(); + while(d_getTSIGKeyQuery_stmt->hasNextRow()) { + d_getTSIGKeyQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-tsig-key-query", row, 2); + try{ + if(algorithm->empty() || *algorithm==DNSName(row[0])) { + *algorithm = DNSName(row[0]); + *content = row[1]; + } + } catch (...) {} + } + + d_getTSIGKeyQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to retrieve TSIG key with name '" + name.toLogString() + "': "+e.txtReason()); + } + + return !content->empty(); +} + +bool GSQLBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ + try { + reconnectIfNeeded(); + + d_setTSIGKeyQuery_stmt-> + bind("key_name", name)-> + bind("algorithm", algorithm)-> + bind("content", content)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to store TSIG key with name '" + name.toLogString() + "' and algorithm '" + algorithm.toString() + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::deleteTSIGKey(const DNSName& name) +{ + try { + reconnectIfNeeded(); + + d_deleteTSIGKeyQuery_stmt-> + bind("key_name", name)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete TSIG key with name '" + name.toLogString() + "': "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +{ + try { + reconnectIfNeeded(); + + d_getTSIGKeysQuery_stmt-> + execute(); + + SSqlStatement::row_t row; + + while(d_getTSIGKeysQuery_stmt->hasNextRow()) { + d_getTSIGKeysQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-tsig-keys-query", row, 3); + struct TSIGKey key; + try { + key.name = DNSName(row[0]); + key.algorithm = DNSName(row[1]); + } catch (...) { + continue; + } + key.key = row[2]; + keys.push_back(key); + } + + d_getTSIGKeysQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to retrieve TSIG keys: "+e.txtReason()); + } + + return keys.empty(); +} + +bool GSQLBackend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + if(!d_dnssecQueries) + return false; + + try { + reconnectIfNeeded(); + + d_ListDomainKeysQuery_stmt-> + bind("domain", name)-> + execute(); + + SSqlStatement::row_t row; + KeyData kd; + while(d_ListDomainKeysQuery_stmt->hasNextRow()) { + d_ListDomainKeysQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("list-domain-keys-query", row, 4); + //~ for(const auto& val: row) { + //~ cerr<<"'"<reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to list keys: "+e.txtReason()); + } + + return true; +} + +void GSQLBackend::alsoNotifies(const DNSName &domain, set *ips) +{ + vector meta; + getDomainMetadata(domain, "ALSO-NOTIFY", meta); + for(const auto& str: meta) { + ips->insert(str); + } +} + +bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) +{ + try { + reconnectIfNeeded(); + + d_GetAllDomainMetadataQuery_stmt-> + bind("domain", name)-> + execute(); + + SSqlStatement::row_t row; + + while(d_GetAllDomainMetadataQuery_stmt->hasNextRow()) { + d_GetAllDomainMetadataQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-all-domain-metadata-query", row, 2); + + if (d_dnssecQueries || !isDnssecDomainMetadata(row[0])) + meta[row[0]].push_back(row[1]); + } + + d_GetAllDomainMetadataQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to list metadata for domain '" + name.toLogString() + "': "+e.txtReason()); + } + + return true; +} + + +bool GSQLBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ + if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) + return false; + + try { + reconnectIfNeeded(); + + d_GetDomainMetadataQuery_stmt-> + bind("domain", name)-> + bind("kind", kind)-> + execute(); + + SSqlStatement::row_t row; + + while(d_GetDomainMetadataQuery_stmt->hasNextRow()) { + d_GetDomainMetadataQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-domain-metadata-query", row, 1); + meta.push_back(row[0]); + } + + d_GetDomainMetadataQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to get metadata kind '" + kind + "' for domain '" + name.toLogString() + "': "+e.txtReason()); + } + + return true; +} + +bool GSQLBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ + if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) + return false; + + try { + reconnectIfNeeded(); + + d_ClearDomainMetadataQuery_stmt-> + bind("domain", name)-> + bind("kind", kind)-> + execute()-> + reset(); + if(!meta.empty()) { + for(const auto& value: meta) { + d_SetDomainMetadataQuery_stmt-> + bind("kind", kind)-> + bind("content", value)-> + bind("domain", name)-> + execute()-> + reset(); + } + } + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to set metadata kind '" + kind + "' for domain '" + name.toLogString() + "': "+e.txtReason()); + } + + return true; +} + +void GSQLBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int domain_id) +{ + try { + reconnectIfNeeded(); + + if(qtype.getCode()!=QType::ANY) { + if(domain_id < 0) { + d_query_name = "basic-query"; + d_query_stmt = &d_NoIdQuery_stmt; + (*d_query_stmt)-> + bind("qtype", qtype.getName())-> + bind("qname", qname); + } else { + d_query_name = "id-query"; + d_query_stmt = &d_IdQuery_stmt; + (*d_query_stmt)-> + bind("qtype", qtype.getName())-> + bind("qname", qname)-> + bind("domain_id", domain_id); + } + } else { + // qtype==ANY + if(domain_id < 0) { + d_query_name = "any-query"; + d_query_stmt = &d_ANYNoIdQuery_stmt; + (*d_query_stmt)-> + bind("qname", qname); + } else { + d_query_name = "any-id-query"; + d_query_stmt = &d_ANYIdQuery_stmt; + (*d_query_stmt)-> + bind("qname", qname)-> + bind("domain_id", domain_id); + } + } + + (*d_query_stmt)-> + execute(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to lookup '" + qname.toLogString() + "|" + qtype.getName() + "':"+e.txtReason()); + } + + d_qname=qname; +} + +bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabled) +{ + DLOG(g_log<<"GSQLBackend constructing handle for list of domain id '"< + bind("include_disabled", (int)include_disabled)-> + bind("domain_id", domain_id)-> + execute(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to list domain '" + target.toLogString() + "': "+e.txtReason()); + } + + d_qname.clear(); + return true; +} + +bool GSQLBackend::listSubZone(const DNSName &zone, int domain_id) { + + string wildzone = "%." + zone.makeLowerCase().toStringNoDot(); + + try { + reconnectIfNeeded(); + + d_query_name = "list-subzone-query"; + d_query_stmt = &d_listSubZoneQuery_stmt; + (*d_query_stmt)-> + bind("zone", zone)-> + bind("wildzone", wildzone)-> + bind("domain_id", domain_id)-> + execute(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to list SubZones for domain '" + zone.toLogString() + "': "+e.txtReason()); + } + d_qname.clear(); + return true; +} + +bool GSQLBackend::get(DNSResourceRecord &r) +{ + // g_log << "GSQLBackend get() was called for "<hasNextRow()) { + try { + (*d_query_stmt)->nextRow(row); + ASSERT_ROW_COLUMNS(d_query_name, row, 8); + } catch (SSqlException &e) { + throw PDNSException("GSQLBackend get: "+e.txtReason()); + } + try { + extractRecord(row, r); + } catch (...) { + goto skiprow; + } + return true; + } + + try { + (*d_query_stmt)->reset(); + } catch (SSqlException &e) { + throw PDNSException("GSQLBackend get: "+e.txtReason()); + } + d_query_stmt = NULL; + return false; +} + +bool GSQLBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **ddb) +{ + // check if we know the ip/ns couple in the database + for(vector::const_iterator i=nsset.begin();i!=nsset.end();++i) { + try { + reconnectIfNeeded(); + + d_SuperMasterInfoQuery_stmt-> + bind("ip", ip)-> + bind("nameserver", i->content)-> + execute()-> + getResult(d_result)-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to search for a supermaster with IP " + ip + " and nameserver name '" + i->content + "' for domain '" + domain.toLogString() + "': "+e.txtReason()); + } + if(!d_result.empty()) { + ASSERT_ROW_COLUMNS("supermaster-query", d_result[0], 1); + *nameserver=i->content; + *account=d_result[0][0]; + *ddb=this; + return true; + } + } + return false; +} + +bool GSQLBackend::createDomain(const DNSName &domain, const string &type, const string &masters, const string &account) +{ + try { + reconnectIfNeeded(); + + d_InsertZoneQuery_stmt-> + bind("type", type)-> + bind("domain", domain)-> + bind("masters", masters)-> + bind("account", account)-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("Database error trying to insert new domain '"+domain.toLogString()+"': "+ e.txtReason()); + } + return true; +} + +bool GSQLBackend::createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) +{ + string name; + string masters(ip); + try { + if (!nameserver.empty()) { + // figure out all IP addresses for the master + reconnectIfNeeded(); + + d_GetSuperMasterIPs_stmt-> + bind("nameserver", nameserver)-> + bind("account", account)-> + execute()-> + getResult(d_result)-> + reset(); + if (!d_result.empty()) { + // collect all IP addresses + vector tmp; + for(const auto& row: d_result) { + if (account == row[1]) + tmp.push_back(row[0]); + } + // set them as domain's masters, comma separated + masters = boost::join(tmp, ", "); + } + } + createDomain(domain, "SLAVE", masters, account); + } + catch(SSqlException &e) { + throw PDNSException("Database error trying to insert new slave domain '"+domain.toLogString()+"': "+ e.txtReason()); + } + return true; +} + +bool GSQLBackend::deleteDomain(const DNSName &domain) +{ + DomainInfo di; + if (!getDomainInfo(domain, di)) { + return false; + } + + try { + reconnectIfNeeded(); + + d_DeleteZoneQuery_stmt-> + bind("domain_id", di.id)-> + execute()-> + reset(); + d_ClearDomainAllMetadataQuery_stmt-> + bind("domain", domain)-> + execute()-> + reset(); + d_ClearDomainAllKeysQuery_stmt-> + bind("domain", domain)-> + execute()-> + reset(); + d_DeleteCommentsQuery_stmt-> + bind("domain_id", di.id)-> + execute()-> + reset(); + d_DeleteDomainQuery_stmt-> + bind("domain", domain)-> + execute()-> + reset(); + } + catch(SSqlException &e) { + throw PDNSException("Database error trying to delete domain '"+domain.toLogString()+"': "+ e.txtReason()); + } + return true; +} + +void GSQLBackend::getAllDomains(vector *domains, bool include_disabled) +{ + DLOG(g_log<<"GSQLBackend retrieving all domains."< + bind("include_disabled", (int)include_disabled)-> + execute(); + + SSqlStatement::row_t row; + while (d_getAllDomainsQuery_stmt->hasNextRow()) { + d_getAllDomainsQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("get-all-domains-query", row, 8); + DomainInfo di; + di.id = pdns_stou(row[0]); + try { + di.zone = DNSName(row[1]); + } catch (...) { + continue; + } + + if (pdns_iequals(row[3], "MASTER")) { + di.kind = DomainInfo::Master; + } else if (pdns_iequals(row[3], "SLAVE")) { + di.kind = DomainInfo::Slave; + } else if (pdns_iequals(row[3], "NATIVE")) { + di.kind = DomainInfo::Native; + } else { + g_log< masters; + stringtok(masters, row[4], " ,\t"); + for(const auto& m : masters) { + try { + di.masters.emplace_back(m, 53); + } catch(const PDNSException &e) { + g_log<push_back(di); + } + d_getAllDomainsQuery_stmt->reset(); + } + catch (SSqlException &e) { + throw PDNSException("Database error trying to retrieve all domains:" + e.txtReason()); + } +} + +bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) +{ + try { + reconnectIfNeeded(); + + if (!d_inTransaction) { + throw PDNSException("replaceRRSet called outside of transaction"); + } + + if (qt != QType::ANY) { + d_DeleteRRSetQuery_stmt-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + bind("qtype", qt.getName())-> + execute()-> + reset(); + } else { + d_DeleteNamesQuery_stmt-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + execute()-> + reset(); + } + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete RRSet " + qname.toLogString() + "|" + qt.getName() + ": "+e.txtReason()); + } + + if (rrset.empty()) { + try { + reconnectIfNeeded(); + + d_DeleteCommentRRsetQuery_stmt-> + bind("domain_id", domain_id)-> + bind("qname", qname)-> + bind("qtype", qt.getName())-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete comment for RRSet " + qname.toLogString() + "|" + qt.getName() + ": "+e.txtReason()); + } + } + for(const auto& rr: rrset) { + feedRecord(rr, DNSName()); + } + + return true; +} + +bool GSQLBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3) +{ + int prio=0; + string content(r.content); + if (r.qtype == QType::MX || r.qtype == QType::SRV) { + string::size_type pos = content.find_first_not_of("0123456789"); + if (pos != string::npos) { + prio=pdns_stou(content.substr(0,pos)); + boost::erase_head(content, pos); + } + trim_left(content); + } + + try { + reconnectIfNeeded(); + + d_InsertRecordQuery_stmt-> + bind("content",content)-> + bind("ttl",r.ttl)-> + bind("priority",prio)-> + bind("qtype",r.qtype.getName())-> + bind("domain_id",r.domain_id)-> + bind("disabled",r.disabled)-> + bind("qname",r.qname); + + if (!ordername.empty()) + d_InsertRecordQuery_stmt->bind("ordername", ordername.labelReverse().makeLowerCase().toString(" ", false)); + else + d_InsertRecordQuery_stmt->bindNull("ordername"); + + if (d_dnssecQueries) + d_InsertRecordQuery_stmt->bind("auth", r.auth); + else + d_InsertRecordQuery_stmt->bind("auth", true); + + d_InsertRecordQuery_stmt-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to feed record " + r.qname.toLogString() + "|" + r.qtype.getName() + ": "+e.txtReason()); + } + return true; // XXX FIXME this API should not return 'true' I think -ahu +} + +bool GSQLBackend::feedEnts(int domain_id, map& nonterm) +{ + for(const auto& nt: nonterm) { + try { + reconnectIfNeeded(); + + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bind("domain_id",domain_id)-> + bind("qname", nt.first)-> + bindNull("ordername")-> + bind("auth",(nt.second || !d_dnssecQueries))-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to feed empty non-terminal with name '" + nt.first.toLogString() + "': "+e.txtReason()); + } + } + return true; +} + +bool GSQLBackend::feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) +{ + if(!d_dnssecQueries) + return false; + + string ordername; + + for(const auto& nt: nonterm) { + try { + reconnectIfNeeded(); + + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bind("domain_id",domain_id)-> + bind("qname", nt.first); + if (narrow || !nt.second) { + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bindNull("ordername"); + } else { + ordername=toBase32Hex(hashQNameWithSalt(ns3prc, nt.first)); + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bind("ordername", ordername); + } + d_InsertEmptyNonTerminalOrderQuery_stmt-> + bind("auth",nt.second)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to feed empty non-terminal with name '" + nt.first.toLogString() + "' (hashed name '"+ toBase32Hex(hashQNameWithSalt(ns3prc, nt.first)) + "') : "+e.txtReason()); + } + } + return true; +} + +bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id) +{ + try { + reconnectIfNeeded(); + + if (inTransaction()) { + throw PDNSException("Attempted to start transaction while one was already active (domain '" + domain.toLogString() + "')"); + } + d_db->startTransaction(); + d_inTransaction = true; + if(domain_id >= 0) { + d_DeleteZoneQuery_stmt-> + bind("domain_id", domain_id)-> + execute()-> + reset(); + } + } + catch (SSqlException &e) { + d_inTransaction = false; + throw PDNSException("Database failed to start transaction for domain '" + domain.toLogString() + "': "+e.txtReason()); + } + + return true; +} + +bool GSQLBackend::commitTransaction() +{ + try { + d_db->commit(); + d_inTransaction = false; + } + catch (SSqlException &e) { + d_inTransaction = false; + throw PDNSException("Database failed to commit transaction: "+e.txtReason()); + } + return true; +} + +bool GSQLBackend::abortTransaction() +{ + try { + d_db->rollback(); + d_inTransaction = false; + } + catch(SSqlException &e) { + d_inTransaction = false; + throw PDNSException("Database failed to abort transaction: "+string(e.txtReason())); + } + return true; +} + +bool GSQLBackend::listComments(const uint32_t domain_id) +{ + try { + reconnectIfNeeded(); + + d_query_name = "list-comments-query"; + d_query_stmt = &d_ListCommentsQuery_stmt; + (*d_query_stmt)-> + bind("domain_id", domain_id)-> + execute(); + } + catch(SSqlException &e) { + throw PDNSException("GSQLBackend unable to list comments for domain id " + std::to_string(domain_id) + ": "+e.txtReason()); + } + + return true; +} + +bool GSQLBackend::getComment(Comment& comment) +{ + SSqlStatement::row_t row; + + for(;;) { + if (!(*d_query_stmt)->hasNextRow()) { + try { + (*d_query_stmt)->reset(); + } catch(SSqlException &e) { + throw PDNSException("GSQLBackend comment get: "+e.txtReason()); + } + d_query_stmt = NULL; + return false; + } + + try { + (*d_query_stmt)->nextRow(row); + ASSERT_ROW_COLUMNS(d_query_name, row, 6); + } catch(SSqlException &e) { + throw PDNSException("GSQLBackend comment get: "+e.txtReason()); + } + try { + extractComment(row, comment); + } catch (...) { + continue; + } + return true; + } +} + +void GSQLBackend::feedComment(const Comment& comment) +{ + try { + reconnectIfNeeded(); + + d_InsertCommentQuery_stmt-> + bind("domain_id",comment.domain_id)-> + bind("qname",comment.qname)-> + bind("qtype",comment.qtype.getName())-> + bind("modified_at",comment.modified_at)-> + bind("account",comment.account)-> + bind("content",comment.content)-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to feed comment for RRSet '" + comment.qname.toLogString() + "|" + comment.qtype.getName() + "': "+e.txtReason()); + } +} + +bool GSQLBackend::replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& comments) +{ + try { + reconnectIfNeeded(); + + if (!d_inTransaction) { + throw PDNSException("replaceComments called outside of transaction"); + } + + d_DeleteCommentRRsetQuery_stmt-> + bind("domain_id",domain_id)-> + bind("qname", qname)-> + bind("qtype",qt.getName())-> + execute()-> + reset(); + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to delete comment for RRSet '" + qname.toLogString() + "|" + qt.getName() + "': "+e.txtReason()); + } + + for(const auto& comment: comments) { + feedComment(comment); + } + + return true; +} + +string GSQLBackend::directBackendCmd(const string &query) +{ + try { + ostringstream out; + + auto stmt = d_db->prepare(query,0); + + reconnectIfNeeded(); + + stmt->execute(); + + SSqlStatement::row_t row; + + while(stmt->hasNextRow()) { + stmt->nextRow(row); + for(const auto& col: row) + out<<"\'"<& result) +{ + d_qname.clear(); + string escaped_pattern = pattern2SQLPattern(pattern); + try { + reconnectIfNeeded(); + + d_SearchRecordsQuery_stmt-> + bind("value", escaped_pattern)-> + bind("value2", escaped_pattern)-> + bind("limit", maxResults)-> + execute(); + + while(d_SearchRecordsQuery_stmt->hasNextRow()) + { + SSqlStatement::row_t row; + DNSResourceRecord r; + d_SearchRecordsQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("search-records-query", row, 8); + try { + extractRecord(row, r); + } catch (...) { + continue; + } + result.push_back(r); + } + + d_SearchRecordsQuery_stmt->reset(); + + return true; + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to search for records with pattern '" + pattern + "' (escaped pattern '" + escaped_pattern + "'): "+e.txtReason()); + } + + return false; +} + +bool GSQLBackend::searchComments(const string &pattern, int maxResults, vector& result) +{ + Comment c; + string escaped_pattern = pattern2SQLPattern(pattern); + try { + reconnectIfNeeded(); + + d_SearchCommentsQuery_stmt-> + bind("value", escaped_pattern)-> + bind("value2", escaped_pattern)-> + bind("limit", maxResults)-> + execute(); + + while(d_SearchCommentsQuery_stmt->hasNextRow()) { + SSqlStatement::row_t row; + d_SearchCommentsQuery_stmt->nextRow(row); + ASSERT_ROW_COLUMNS("search-comments-query", row, 6); + Comment comment; + extractComment(row, comment); + result.push_back(comment); + } + + d_SearchCommentsQuery_stmt->reset(); + + return true; + } + catch (SSqlException &e) { + throw PDNSException("GSQLBackend unable to search for comments with pattern '" + pattern + "' (escaped pattern '" + escaped_pattern + "'): "+e.txtReason()); + } + + return false; +} + +void GSQLBackend::extractRecord(const SSqlStatement::row_t& row, DNSResourceRecord& r) +{ + if (row[1].empty()) + r.ttl = ::arg().asNum( "default-ttl" ); + else + r.ttl=pdns_stou(row[1]); + if(!d_qname.empty()) + r.qname=d_qname; + else + r.qname=DNSName(row[6]); + + r.qtype=row[3]; + + if (r.qtype==QType::MX || r.qtype==QType::SRV) + r.content=row[2]+" "+row[0]; + else + r.content=row[0]; + + r.last_modified=0; + + if(d_dnssecQueries) + r.auth = !row[7].empty() && row[7][0]=='1'; + else + r.auth = 1; + + r.disabled = !row[5].empty() && row[5][0]=='1'; + + r.domain_id=pdns_stou(row[4]); +} + +void GSQLBackend::extractComment(const SSqlStatement::row_t& row, Comment& comment) +{ + comment.domain_id = pdns_stou(row[0]); + comment.qname = DNSName(row[1]); + comment.qtype = row[2]; + comment.modified_at = pdns_stou(row[3]); + comment.account = row[4]; + comment.content = row[5]; +} + +SSqlStatement::~SSqlStatement() { +// make sure vtable won't break +} diff --git a/pdns/backends/gsql/gsqlbackend.hh b/pdns/backends/gsql/gsqlbackend.hh new file mode 100644 index 0000000..be25db1 --- /dev/null +++ b/pdns/backends/gsql/gsqlbackend.hh @@ -0,0 +1,407 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_GSQLBACKEND_HH +#define PDNS_GSQLBACKEND_HH + +#include +#include +#include "ssql.hh" +#include "pdns/arguments.hh" + +#include "pdns/namespaces.hh" + +bool isDnssecDomainMetadata (const string& name); + +/* +GSQLBackend is a generic backend used by other sql backends +*/ +class GSQLBackend : public DNSBackend +{ +public: + GSQLBackend(const string &mode, const string &suffix); //!< Makes our connection to the database. Throws an exception if it fails. + virtual ~GSQLBackend() + { + freeStatements(); + if(d_db) + delete d_db; + } + + void setDB(SSql *db) + { + freeStatements(); + delete d_db; + d_db=db; + if (d_db) { + d_db->setLog(::arg().mustDo("query-logging")); + allocateStatements(); + } + } + + void allocateStatements() + { + if (d_db) { + d_NoIdQuery_stmt = d_db->prepare(d_NoIdQuery, 2); + d_IdQuery_stmt = d_db->prepare(d_IdQuery, 3); + d_ANYNoIdQuery_stmt = d_db->prepare(d_ANYNoIdQuery, 1); + d_ANYIdQuery_stmt = d_db->prepare(d_ANYIdQuery, 2); + d_listQuery_stmt = d_db->prepare(d_listQuery, 2); + d_listSubZoneQuery_stmt = d_db->prepare(d_listSubZoneQuery, 3); + d_MasterOfDomainsZoneQuery_stmt = d_db->prepare(d_MasterOfDomainsZoneQuery, 1); + d_InfoOfDomainsZoneQuery_stmt = d_db->prepare(d_InfoOfDomainsZoneQuery, 1); + d_InfoOfAllSlaveDomainsQuery_stmt = d_db->prepare(d_InfoOfAllSlaveDomainsQuery, 0); + d_SuperMasterInfoQuery_stmt = d_db->prepare(d_SuperMasterInfoQuery, 2); + d_GetSuperMasterIPs_stmt = d_db->prepare(d_GetSuperMasterIPs, 2); + d_InsertZoneQuery_stmt = d_db->prepare(d_InsertZoneQuery, 4); + d_InsertRecordQuery_stmt = d_db->prepare(d_InsertRecordQuery, 9); + d_InsertEmptyNonTerminalOrderQuery_stmt = d_db->prepare(d_InsertEmptyNonTerminalOrderQuery, 4); + d_UpdateMasterOfZoneQuery_stmt = d_db->prepare(d_UpdateMasterOfZoneQuery, 2); + d_UpdateKindOfZoneQuery_stmt = d_db->prepare(d_UpdateKindOfZoneQuery, 2); + d_UpdateAccountOfZoneQuery_stmt = d_db->prepare(d_UpdateAccountOfZoneQuery, 2); + d_UpdateSerialOfZoneQuery_stmt = d_db->prepare(d_UpdateSerialOfZoneQuery, 2); + d_UpdateLastCheckofZoneQuery_stmt = d_db->prepare(d_UpdateLastCheckofZoneQuery, 2); + d_InfoOfAllMasterDomainsQuery_stmt = d_db->prepare(d_InfoOfAllMasterDomainsQuery, 0); + d_DeleteDomainQuery_stmt = d_db->prepare(d_DeleteDomainQuery, 1); + d_DeleteZoneQuery_stmt = d_db->prepare(d_DeleteZoneQuery, 1); + d_DeleteRRSetQuery_stmt = d_db->prepare(d_DeleteRRSetQuery, 3); + d_DeleteNamesQuery_stmt = d_db->prepare(d_DeleteNamesQuery, 2); + d_firstOrderQuery_stmt = d_db->prepare(d_firstOrderQuery, 1); + d_beforeOrderQuery_stmt = d_db->prepare(d_beforeOrderQuery, 2); + d_afterOrderQuery_stmt = d_db->prepare(d_afterOrderQuery, 2); + d_lastOrderQuery_stmt = d_db->prepare(d_lastOrderQuery, 1); + d_updateOrderNameAndAuthQuery_stmt = d_db->prepare(d_updateOrderNameAndAuthQuery, 4); + d_updateOrderNameAndAuthTypeQuery_stmt = d_db->prepare(d_updateOrderNameAndAuthTypeQuery, 5); + d_nullifyOrderNameAndUpdateAuthQuery_stmt = d_db->prepare(d_nullifyOrderNameAndUpdateAuthQuery, 3); + d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt = d_db->prepare(d_nullifyOrderNameAndUpdateAuthTypeQuery, 4); + d_RemoveEmptyNonTerminalsFromZoneQuery_stmt = d_db->prepare(d_RemoveEmptyNonTerminalsFromZoneQuery, 1); + d_DeleteEmptyNonTerminalQuery_stmt = d_db->prepare(d_DeleteEmptyNonTerminalQuery, 2); + d_AddDomainKeyQuery_stmt = d_db->prepare(d_AddDomainKeyQuery, 4); + d_GetLastInsertedKeyIdQuery_stmt = d_db->prepare(d_GetLastInsertedKeyIdQuery, 0); + d_ListDomainKeysQuery_stmt = d_db->prepare(d_ListDomainKeysQuery, 1); + d_GetAllDomainMetadataQuery_stmt = d_db->prepare(d_GetAllDomainMetadataQuery, 1); + d_GetDomainMetadataQuery_stmt = d_db->prepare(d_GetDomainMetadataQuery, 2); + d_ClearDomainMetadataQuery_stmt = d_db->prepare(d_ClearDomainMetadataQuery, 2); + d_ClearDomainAllMetadataQuery_stmt = d_db->prepare(d_ClearDomainAllMetadataQuery, 1); + d_SetDomainMetadataQuery_stmt = d_db->prepare(d_SetDomainMetadataQuery, 3); + d_RemoveDomainKeyQuery_stmt = d_db->prepare(d_RemoveDomainKeyQuery, 2); + d_ActivateDomainKeyQuery_stmt = d_db->prepare(d_ActivateDomainKeyQuery, 2); + d_DeactivateDomainKeyQuery_stmt = d_db->prepare(d_DeactivateDomainKeyQuery, 2); + d_ClearDomainAllKeysQuery_stmt = d_db->prepare(d_ClearDomainAllKeysQuery, 1); + d_getTSIGKeyQuery_stmt = d_db->prepare(d_getTSIGKeyQuery, 1); + d_setTSIGKeyQuery_stmt = d_db->prepare(d_setTSIGKeyQuery, 3); + d_deleteTSIGKeyQuery_stmt = d_db->prepare(d_deleteTSIGKeyQuery, 1); + d_getTSIGKeysQuery_stmt = d_db->prepare(d_getTSIGKeysQuery, 0); + d_getAllDomainsQuery_stmt = d_db->prepare(d_getAllDomainsQuery, 1); + d_ListCommentsQuery_stmt = d_db->prepare(d_ListCommentsQuery, 1); + d_InsertCommentQuery_stmt = d_db->prepare(d_InsertCommentQuery, 6); + d_DeleteCommentRRsetQuery_stmt = d_db->prepare(d_DeleteCommentRRsetQuery, 3); + d_DeleteCommentsQuery_stmt = d_db->prepare(d_DeleteCommentsQuery, 1); + d_SearchRecordsQuery_stmt = d_db->prepare(d_SearchRecordsQuery, 3); + d_SearchCommentsQuery_stmt = d_db->prepare(d_SearchCommentsQuery, 3); + } + } + + void freeStatements() { + d_NoIdQuery_stmt.reset(); + d_IdQuery_stmt.reset(); + d_ANYNoIdQuery_stmt.reset(); + d_ANYIdQuery_stmt.reset(); + d_listQuery_stmt.reset(); + d_listSubZoneQuery_stmt.reset(); + d_MasterOfDomainsZoneQuery_stmt.reset(); + d_InfoOfDomainsZoneQuery_stmt.reset(); + d_InfoOfAllSlaveDomainsQuery_stmt.reset(); + d_SuperMasterInfoQuery_stmt.reset(); + d_GetSuperMasterIPs_stmt.reset(); + d_InsertZoneQuery_stmt.reset(); + d_InsertRecordQuery_stmt.reset(); + d_InsertEmptyNonTerminalOrderQuery_stmt.reset(); + d_UpdateMasterOfZoneQuery_stmt.reset(); + d_UpdateKindOfZoneQuery_stmt.reset(); + d_UpdateAccountOfZoneQuery_stmt.reset(); + d_UpdateSerialOfZoneQuery_stmt.reset(); + d_UpdateLastCheckofZoneQuery_stmt.reset(); + d_InfoOfAllMasterDomainsQuery_stmt.reset(); + d_DeleteDomainQuery_stmt.reset(); + d_DeleteZoneQuery_stmt.reset(); + d_DeleteRRSetQuery_stmt.reset(); + d_DeleteNamesQuery_stmt.reset(); + d_firstOrderQuery_stmt.reset(); + d_beforeOrderQuery_stmt.reset(); + d_afterOrderQuery_stmt.reset(); + d_lastOrderQuery_stmt.reset(); + d_updateOrderNameAndAuthQuery_stmt.reset(); + d_updateOrderNameAndAuthTypeQuery_stmt.reset(); + d_nullifyOrderNameAndUpdateAuthQuery_stmt.reset(); + d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt.reset(); + d_RemoveEmptyNonTerminalsFromZoneQuery_stmt.reset(); + d_DeleteEmptyNonTerminalQuery_stmt.reset(); + d_AddDomainKeyQuery_stmt.reset(); + d_GetLastInsertedKeyIdQuery_stmt.reset(); + d_ListDomainKeysQuery_stmt.reset(); + d_GetAllDomainMetadataQuery_stmt.reset(); + d_GetDomainMetadataQuery_stmt.reset(); + d_ClearDomainMetadataQuery_stmt.reset(); + d_ClearDomainAllMetadataQuery_stmt.reset(); + d_SetDomainMetadataQuery_stmt.reset(); + d_RemoveDomainKeyQuery_stmt.reset(); + d_ActivateDomainKeyQuery_stmt.reset(); + d_DeactivateDomainKeyQuery_stmt.reset(); + d_ClearDomainAllKeysQuery_stmt.reset(); + d_getTSIGKeyQuery_stmt.reset(); + d_setTSIGKeyQuery_stmt.reset(); + d_deleteTSIGKeyQuery_stmt.reset(); + d_getTSIGKeysQuery_stmt.reset(); + d_getAllDomainsQuery_stmt.reset(); + d_ListCommentsQuery_stmt.reset(); + d_InsertCommentQuery_stmt.reset(); + d_DeleteCommentRRsetQuery_stmt.reset(); + d_DeleteCommentsQuery_stmt.reset(); + d_SearchRecordsQuery_stmt.reset(); + d_SearchCommentsQuery_stmt.reset(); + } + + void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1) override; + bool list(const DNSName &target, int domain_id, bool include_disabled=false) override; + bool get(DNSResourceRecord &r) override; + void getAllDomains(vector *domains, bool include_disabled=false) override; + void alsoNotifies(const DNSName &domain, set *ips) override; + bool startTransaction(const DNSName &domain, int domain_id=-1) override; + bool commitTransaction() override; + bool abortTransaction() override; + bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + bool feedEnts(int domain_id, map& nonterm) override; + bool feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; + bool createDomain(const DNSName &domain) override { + return createDomain(domain, "NATIVE", "", ""); + }; + bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) override; + bool deleteDomain(const DNSName &domain) override; + bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) override; + void setFresh(uint32_t domain_id) override; + void getUnfreshSlaveInfos(vector *domains) override; + void getUpdatedMasters(vector *updatedDomains) override; + bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true) override; + void setNotified(uint32_t domain_id, uint32_t serial) override; + bool setMaster(const DNSName &domain, const string &ip) override; + bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) override; + bool setAccount(const DNSName &domain, const string &account) override; + + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; + bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t=QType::ANY) override; + + bool updateEmptyNonTerminals(uint32_t domain_id, set& insert ,set& erase, bool remove) override; + bool doesDNSSEC() override; + + bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; + bool listSubZone(const DNSName &zone, int domain_id) override; + bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; + bool getDomainKeys(const DNSName& name, std::vector& keys) override; + bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; + + bool removeDomainKey(const DNSName& name, unsigned int id) override; + bool activateDomainKey(const DNSName& name, unsigned int id) override; + bool deactivateDomainKey(const DNSName& name, unsigned int id) override; + + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; + bool deleteTSIGKey(const DNSName& name) override; + bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + + bool listComments(const uint32_t domain_id) override; + bool getComment(Comment& comment) override; + void feedComment(const Comment& comment) override; + bool replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& comments) override; + string directBackendCmd(const string &query) override; + bool searchRecords(const string &pattern, int maxResults, vector& result) override; + bool searchComments(const string &pattern, int maxResults, vector& result) override; + +protected: + bool createDomain(const DNSName &domain, const string &type, const string &masters, const string &account); + string pattern2SQLPattern(const string& pattern); + void extractRecord(const SSqlStatement::row_t& row, DNSResourceRecord& rr); + void extractComment(const SSqlStatement::row_t& row, Comment& c); + bool isConnectionUsable() { + if (d_db) { + return d_db->isConnectionUsable(); + } + return false; + } + void reconnectIfNeeded() + { + if (inTransaction() || isConnectionUsable()) { + return; + } + + reconnect(); + } + virtual void reconnect() { } + virtual bool inTransaction() + { + return d_inTransaction; + } + +private: + string d_query_name; + DNSName d_qname; + SSqlStatement::result_t d_result; + + string d_NoIdQuery; + string d_IdQuery; + string d_ANYNoIdQuery; + string d_ANYIdQuery; + + string d_listQuery; + string d_listSubZoneQuery; + string d_logprefix; + + string d_MasterOfDomainsZoneQuery; + string d_InfoOfDomainsZoneQuery; + string d_InfoOfAllSlaveDomainsQuery; + string d_SuperMasterInfoQuery; + string d_GetSuperMasterName; + string d_GetSuperMasterIPs; + + string d_InsertZoneQuery; + string d_InsertRecordQuery; + string d_InsertEmptyNonTerminalOrderQuery; + string d_UpdateMasterOfZoneQuery; + string d_UpdateKindOfZoneQuery; + string d_UpdateAccountOfZoneQuery; + string d_UpdateSerialOfZoneQuery; + string d_UpdateLastCheckofZoneQuery; + string d_InfoOfAllMasterDomainsQuery; + string d_DeleteDomainQuery; + string d_DeleteZoneQuery; + string d_DeleteRRSetQuery; + string d_DeleteNamesQuery; + + string d_firstOrderQuery; + string d_beforeOrderQuery; + string d_afterOrderQuery; + string d_lastOrderQuery; + + string d_updateOrderNameAndAuthQuery; + string d_updateOrderNameAndAuthTypeQuery; + string d_nullifyOrderNameAndUpdateAuthQuery; + string d_nullifyOrderNameAndUpdateAuthTypeQuery; + + string d_RemoveEmptyNonTerminalsFromZoneQuery; + string d_DeleteEmptyNonTerminalQuery; + + string d_AddDomainKeyQuery; + string d_GetLastInsertedKeyIdQuery; + string d_ListDomainKeysQuery; + string d_GetAllDomainMetadataQuery; + string d_GetDomainMetadataQuery; + string d_ClearDomainMetadataQuery; + string d_ClearDomainAllMetadataQuery; + string d_SetDomainMetadataQuery; + + string d_RemoveDomainKeyQuery; + string d_ActivateDomainKeyQuery; + string d_DeactivateDomainKeyQuery; + string d_ClearDomainAllKeysQuery; + + string d_getTSIGKeyQuery; + string d_setTSIGKeyQuery; + string d_deleteTSIGKeyQuery; + string d_getTSIGKeysQuery; + + string d_getAllDomainsQuery; + + string d_ListCommentsQuery; + string d_InsertCommentQuery; + string d_DeleteCommentRRsetQuery; + string d_DeleteCommentsQuery; + + string d_SearchRecordsQuery; + string d_SearchCommentsQuery; + + unique_ptr* d_query_stmt; + + unique_ptr d_NoIdQuery_stmt; + unique_ptr d_IdQuery_stmt; + unique_ptr d_ANYNoIdQuery_stmt; + unique_ptr d_ANYIdQuery_stmt; + unique_ptr d_listQuery_stmt; + unique_ptr d_listSubZoneQuery_stmt; + unique_ptr d_MasterOfDomainsZoneQuery_stmt; + unique_ptr d_InfoOfDomainsZoneQuery_stmt; + unique_ptr d_InfoOfAllSlaveDomainsQuery_stmt; + unique_ptr d_SuperMasterInfoQuery_stmt; + unique_ptr d_GetSuperMasterIPs_stmt; + unique_ptr d_InsertZoneQuery_stmt; + unique_ptr d_InsertRecordQuery_stmt; + unique_ptr d_InsertEmptyNonTerminalOrderQuery_stmt; + unique_ptr d_UpdateMasterOfZoneQuery_stmt; + unique_ptr d_UpdateKindOfZoneQuery_stmt; + unique_ptr d_UpdateAccountOfZoneQuery_stmt; + unique_ptr d_UpdateSerialOfZoneQuery_stmt; + unique_ptr d_UpdateLastCheckofZoneQuery_stmt; + unique_ptr d_InfoOfAllMasterDomainsQuery_stmt; + unique_ptr d_DeleteDomainQuery_stmt; + unique_ptr d_DeleteZoneQuery_stmt; + unique_ptr d_DeleteRRSetQuery_stmt; + unique_ptr d_DeleteNamesQuery_stmt; + unique_ptr d_firstOrderQuery_stmt; + unique_ptr d_beforeOrderQuery_stmt; + unique_ptr d_afterOrderQuery_stmt; + unique_ptr d_lastOrderQuery_stmt; + unique_ptr d_updateOrderNameAndAuthQuery_stmt; + unique_ptr d_updateOrderNameAndAuthTypeQuery_stmt; + unique_ptr d_nullifyOrderNameAndUpdateAuthQuery_stmt; + unique_ptr d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt; + unique_ptr d_RemoveEmptyNonTerminalsFromZoneQuery_stmt; + unique_ptr d_DeleteEmptyNonTerminalQuery_stmt; + unique_ptr d_AddDomainKeyQuery_stmt; + unique_ptr d_GetLastInsertedKeyIdQuery_stmt; + unique_ptr d_ListDomainKeysQuery_stmt; + unique_ptr d_GetAllDomainMetadataQuery_stmt; + unique_ptr d_GetDomainMetadataQuery_stmt; + unique_ptr d_ClearDomainMetadataQuery_stmt; + unique_ptr d_ClearDomainAllMetadataQuery_stmt; + unique_ptr d_SetDomainMetadataQuery_stmt; + unique_ptr d_RemoveDomainKeyQuery_stmt; + unique_ptr d_ActivateDomainKeyQuery_stmt; + unique_ptr d_DeactivateDomainKeyQuery_stmt; + unique_ptr d_ClearDomainAllKeysQuery_stmt; + unique_ptr d_getTSIGKeyQuery_stmt; + unique_ptr d_setTSIGKeyQuery_stmt; + unique_ptr d_deleteTSIGKeyQuery_stmt; + unique_ptr d_getTSIGKeysQuery_stmt; + unique_ptr d_getAllDomainsQuery_stmt; + unique_ptr d_ListCommentsQuery_stmt; + unique_ptr d_InsertCommentQuery_stmt; + unique_ptr d_DeleteCommentRRsetQuery_stmt; + unique_ptr d_DeleteCommentsQuery_stmt; + unique_ptr d_SearchRecordsQuery_stmt; + unique_ptr d_SearchCommentsQuery_stmt; + +protected: + SSql *d_db{nullptr}; + bool d_dnssecQueries; + bool d_inTransaction{false}; +}; + +#endif /* PDNS_GSQLBACKEND_HH */ diff --git a/pdns/backends/gsql/ssql.hh b/pdns/backends/gsql/ssql.hh new file mode 100644 index 0000000..df71eb9 --- /dev/null +++ b/pdns/backends/gsql/ssql.hh @@ -0,0 +1,92 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef SSQL_HH +#define SSQL_HH + +#include +#include +#include +#include "../../dnsname.hh" +#include "../../namespaces.hh" +#include "../../misc.hh" + +class SSqlException +{ +public: + SSqlException(const string &reason) : d_reason(reason) + { + } + + string txtReason() + { + return d_reason; + } +private: + string d_reason; +}; + +class SSqlStatement +{ +public: + typedef vector row_t; + typedef vector result_t; + + virtual SSqlStatement* bind(const string& name, bool value)=0; + virtual SSqlStatement* bind(const string& name, int value)=0; + virtual SSqlStatement* bind(const string& name, uint32_t value)=0; + virtual SSqlStatement* bind(const string& name, long value)=0; + virtual SSqlStatement* bind(const string& name, unsigned long value)=0; + virtual SSqlStatement* bind(const string& name, long long value)=0;; + virtual SSqlStatement* bind(const string& name, unsigned long long value)=0; + virtual SSqlStatement* bind(const string& name, const std::string& value)=0; + SSqlStatement* bind(const string& name, const DNSName& value) { + return bind(name, value.makeLowerCase().toStringRootDot()); + } + virtual SSqlStatement* bindNull(const string& name)=0; + virtual SSqlStatement* execute()=0;; + virtual bool hasNextRow()=0; + virtual SSqlStatement* nextRow(row_t& row)=0; + virtual SSqlStatement* getResult(result_t& result)=0; + virtual SSqlStatement* reset()=0; + virtual const std::string& getQuery()=0; + virtual ~SSqlStatement(); +}; + +class SSql +{ +public: + virtual SSqlException sPerrorException(const string &reason)=0; + virtual std::unique_ptr prepare(const string& query, int nparams)=0; + virtual void execute(const string& query)=0; + virtual void startTransaction()=0; + virtual void rollback()=0; + virtual void commit()=0; + virtual void setLog(bool state){} + virtual bool isConnectionUsable() + { + return true; + } + virtual void reconnect() {}; + virtual ~SSql(){}; +}; + +#endif /* SSQL_HH */ diff --git a/pdns/base32.cc b/pdns/base32.cc new file mode 100644 index 0000000..16d9d4b --- /dev/null +++ b/pdns/base32.cc @@ -0,0 +1,167 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "base32.hh" +#include "namespaces.hh" + +/* based on freebsd:src/contrib/opie/libopie/btoe.c extract: get bit ranges from a char* */ +/* NOTE: length should not exceed 8; all callers inside PowerDNS only pass length=5 though */ +unsigned char extract_bits(const char *s, int start, int length) +{ + uint16_t x; + unsigned char cl, cc; + + if(!length) + return 0; + + cl = s[start / 8]; + if(start / 8 < (start + length-1)/8) + cc = s[start / 8 + 1]; + else + cc = 0; + + x = (uint16_t) (cl << 8 | cc); + x = x >> (16 - (length + (start % 8))); + x = (x & (0xffff >> (16 - length))); + return (x); +} + +/* same, set bit ranges in a char* */ +static void set_bits(char* s, int x, int start, int length) +{ + unsigned char cl, cc, cr; + uint32_t y; + int shift; + + shift = ((8 - ((start + length) % 8)) % 8); + y = (uint32_t) x << shift; + cl = (y >> 16) & 0xff; + cc = (y >> 8) & 0xff; + cr = y & 0xff; + if (shift + length > 16) { + s[start / 8] |= cl; + s[start / 8 + 1] |= cc; + s[start / 8 + 2] |= cr; + } + else { + if (shift + length > 8) { + s[start / 8] |= cc; + s[start / 8 + 1] |= cr; + } else { + s[start / 8] |= cr; + } + } +} + +/* convert a base32 hex character to its decoded equivalent */ +static int unbase32hex(char c) +{ + if(c >= '0' && c<='9') + return c-'0'; + if(c >= 'a' && c<='z') + return 10 + (c-'a'); + if(c >= 'A' && c<='Z') + return 10 + (c-'A'); + if(c=='=') + return '='; + return -1; +} + +/* convert a binary string to base32hex */ +string toBase32Hex(const std::string& input) +{ + static const char base32hex[] = "0123456789abcdefghijklmnopqrstuv="; + string ret; + ret.reserve(4+ 8*input.length()/5); // optimization + // process input in groups of 5 8-bit chunks, emit 8 5-bit chunks + for(string::size_type offset = 0 ; offset < input.length(); offset+=5) { + int todo = input.length() - offset; + int stuffing; // how much '=' to add at the end + + switch(todo) { + case 1: + stuffing = 6; break; + case 2: + stuffing = 4; break; + case 3: + stuffing = 3; break; + case 4: + stuffing = 1; break; + default: // -> 0 or more than 5, no stuffing + stuffing = 0; break; + } + + for(int n=0; n < 8 - stuffing; ++n) + ret.append(1, base32hex[extract_bits(input.c_str()+offset, n*5, 5)]); + ret.append(stuffing, '='); + } + + return ret; +} + +// convert base32hex encoded string to normal string +string fromBase32Hex(const std::string& input) +{ + string ret; + char block[5]={0,0,0,0,0}; // we process 5 8-bit chunks at a time + string::size_type n, toWrite=0; + for(n = 0; n < input.length(); ++n) { + int c=unbase32hex(input[n]); + if(c == '=' || c < 0) // stop at stuffing or error + break; + set_bits(block, c , (n % 8) * 5, 5); + if(++toWrite == 8) { + ret.append(block, sizeof(block)); + memset(block, 0, sizeof(block)); + toWrite = 0; + } + } + ret.append(block, (toWrite*5)/8); + + return ret; +} + +#if 0 +int main(int argc, char **argv) +{ + if(argc!=3 || (argc==3 && strcmp(argv[1],"from") && strcmp(argv[1],"to"))) { + printf("syntax: base32 from|to string\n"); + exit(0); + } + if(!strcmp(argv[1],"to")) { + printf("input: '%s'\noutput: '%s'\n", + argv[2], + toBase32Hex(argv[2]).c_str()); + } + else { + cout<<"input: '"< + +std::string toBase32Hex(const std::string& input); +std::string fromBase32Hex(const std::string& input); + +#endif diff --git a/pdns/base64.cc b/pdns/base64.cc new file mode 100644 index 0000000..6dbb904 --- /dev/null +++ b/pdns/base64.cc @@ -0,0 +1,103 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "base64.hh" +#include +#include +#include +#include + +int B64Decode(const std::string& src, std::string& dst) +{ + if (src.empty() ) { + dst.clear(); + return 0; + } + int dlen = ( src.length() * 6 + 7 ) / 8 ; + ssize_t olen = 0; + boost::scoped_array d( new unsigned char[dlen] ); + BIO *bio, *b64; + bio = BIO_new(BIO_s_mem()); + BIO_write(bio, src.c_str(), src.length()); + b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + olen = BIO_read(b64, d.get(), dlen); + if ((olen == 0 || olen == -1) && BIO_should_retry(bio)) { + BIO_free_all(bio); + throw std::runtime_error("BIO_read failed to read all data from memory buffer"); + } + BIO_free_all(bio); + if (olen > 0) { + dst = std::string( reinterpret_cast(d.get()), olen ); + return 0; + } + return -1; +} + +std::string Base64Encode(const std::string& src) +{ + if (!src.empty()) { + size_t olen = 0; + BIO *bio, *b64; + b64 = BIO_new(BIO_f_base64()); + bio = BIO_new(BIO_s_mem()); + bio = BIO_push(b64, bio); + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + int bioWriteRet = BIO_write(bio, src.c_str(), src.length()); + if (bioWriteRet < 0 || (size_t) bioWriteRet != src.length()) { + BIO_free_all(bio); + throw std::runtime_error("BIO_write failed to write all data to memory buffer"); + } + (void)BIO_flush(bio); + char* pp; + std::string out; + olen = BIO_get_mem_data(bio, &pp); + if (olen > 0) { + out = std::string(pp, olen); + } + BIO_free_all(bio); + return out; + } + return ""; +} + +#if 0 +#include +int main() { + std::string in = "PowerDNS Test String 1"; + std::string out = Base64Encode(in); + std::cout << out << std::endl; + if (out != "UG93ZXJETlMgVGVzdCBTdHJpbmcgMQ==") { + std::cerr << "output did not match expected data" << std::endl; + } + std::string roundtrip; + B64Decode(out, roundtrip); + std::cout << roundtrip << std::endl; + if (roundtrip != in) { + std::cerr << "roundtripped data did not match input data" << std::endl; + } + return 0; +} +#endif diff --git a/pdns/base64.hh b/pdns/base64.hh new file mode 100644 index 0000000..37ab35b --- /dev/null +++ b/pdns/base64.hh @@ -0,0 +1,30 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_BASE64_HH +#define PDNS_BASE64_HH + +#include + +int B64Decode(const std::string& src, std::string& dst); +std::string Base64Encode (const std::string& src); + +#endif diff --git a/pdns/bind-dnssec.schema.sqlite3.sql b/pdns/bind-dnssec.schema.sqlite3.sql new file mode 100644 index 0000000..e4f75d6 --- /dev/null +++ b/pdns/bind-dnssec.schema.sqlite3.sql @@ -0,0 +1,27 @@ +create table domainmetadata ( + id INTEGER PRIMARY KEY, + domain VARCHAR(255) COLLATE NOCASE, + kind VARCHAR(32) COLLATE NOCASE, + content TEXT +); + +create index domainmetanameindex on domainmetadata(domain); + +create table cryptokeys ( + id INTEGER PRIMARY KEY, + domain VARCHAR(255) COLLATE NOCASE, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +create index domainnameindex on cryptokeys(domain); + +create table tsigkeys ( + id INTEGER PRIMARY KEY, + name VARCHAR(255) COLLATE NOCASE, + algorithm VARCHAR(50) COLLATE NOCASE, + secret VARCHAR(255) +); + +create unique index namealgoindex on tsigkeys(name, algorithm); diff --git a/pdns/bind-dnssec.schema.sqlite3.sql.h b/pdns/bind-dnssec.schema.sqlite3.sql.h new file mode 100644 index 0000000..0cbdd9a --- /dev/null +++ b/pdns/bind-dnssec.schema.sqlite3.sql.h @@ -0,0 +1,29 @@ +static char sqlCreate[] __attribute__((unused))= +"create table domainmetadata (" +" id INTEGER PRIMARY KEY," +" domain VARCHAR(255) COLLATE NOCASE," +" kind VARCHAR(32) COLLATE NOCASE," +" content TEXT" +");" +"" +"create index domainmetanameindex on domainmetadata(domain);" +"" +"create table cryptokeys (" +" id INTEGER PRIMARY KEY," +" domain VARCHAR(255) COLLATE NOCASE," +" flags INT NOT NULL," +" active BOOL," +" content TEXT" +");" +"" +"create index domainnameindex on cryptokeys(domain);" +"" +"create table tsigkeys (" +" id INTEGER PRIMARY KEY," +" name VARCHAR(255) COLLATE NOCASE," +" algorithm VARCHAR(50) COLLATE NOCASE," +" secret VARCHAR(255)" +");" +"" +"create unique index namealgoindex on tsigkeys(name, algorithm);" +; diff --git a/pdns/bindlexer.c b/pdns/bindlexer.c new file mode 100644 index 0000000..8cc227a --- /dev/null +++ b/pdns/bindlexer.c @@ -0,0 +1,2090 @@ + +#line 2 "bindlexer.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = NULL; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart ( FILE *input_file ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); +void yy_delete_buffer ( YY_BUFFER_STATE b ); +void yy_flush_buffer ( YY_BUFFER_STATE b ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state ( void ); + +static void yyensure_buffer_stack ( void ); +static void yy_load_buffer_state ( void ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); + +void *yyalloc ( yy_size_t ); +void *yyrealloc ( void *, yy_size_t ); +void yyfree ( void * ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ +typedef flex_uint8_t YY_CHAR; + +FILE *yyin = NULL, *yyout = NULL; + +typedef int yy_state_type; + +extern int yylineno; +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state ( void ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); +static int yy_get_next_buffer ( void ); +static void yynoreturn yy_fatal_error ( const char* msg ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; +#define YY_NUM_RULES 29 +#define YY_END_OF_BUFFER 30 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[109] = + { 0, + 21, 21, 2, 2, 7, 7, 19, 19, 30, 21, + 26, 25, 18, 21, 21, 24, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 22, 23, 2, 4, 3, + 29, 7, 29, 19, 20, 21, 26, 21, 0, 28, + 1, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 2, 3, 3, 5, 7, 0, 19, 21, + 0, 27, 13, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 0, 21, 21, 10, 21, 21, 21, 21, + 17, 9, 8, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 6, 14, 16, + + 11, 21, 21, 21, 15, 21, 12, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, + 1, 6, 1, 1, 7, 1, 8, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, + 1, 1, 1, 1, 10, 1, 11, 12, 13, 14, + 15, 1, 16, 1, 1, 17, 18, 19, 20, 21, + 1, 22, 23, 24, 25, 1, 1, 1, 26, 27, + 1, 1, 1, 1, 1, 1, 28, 1, 29, 30, + + 31, 32, 33, 1, 34, 1, 1, 35, 36, 37, + 38, 39, 1, 40, 41, 42, 43, 1, 1, 1, + 44, 45, 46, 1, 47, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[48] = + { 0, + 1, 2, 3, 4, 1, 5, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 6, 6 + } ; + +static const flex_int16_t yy_base[121] = + { 0, + 0, 0, 45, 46, 51, 52, 192, 165, 131, 0, + 119, 285, 285, 55, 57, 285, 51, 50, 51, 50, + 50, 61, 51, 47, 54, 285, 285, 0, 285, 69, + 285, 74, 0, 0, 285, 0, 118, 91, 116, 285, + 0, 94, 64, 81, 83, 89, 96, 93, 86, 86, + 90, 93, 0, 107, 108, 285, 130, 78, 0, 140, + 76, 285, 0, 97, 105, 120, 117, 130, 122, 131, + 135, 137, 69, 43, 142, 0, 129, 139, 143, 137, + 0, 0, 285, 139, 135, 148, 142, 140, 148, 150, + 161, 169, 168, 161, 166, 166, 169, 0, 0, 0, + + 0, 176, 167, 180, 0, 169, 0, 285, 213, 219, + 225, 231, 236, 242, 248, 254, 260, 266, 272, 278 + } ; + +static const flex_int16_t yy_def[121] = + { 0, + 108, 1, 109, 109, 110, 110, 111, 111, 108, 112, + 108, 108, 108, 113, 112, 108, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 108, 108, 114, 108, 115, + 108, 108, 116, 117, 108, 112, 108, 113, 118, 108, + 112, 119, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 114, 115, 115, 108, 108, 116, 117, 119, + 120, 108, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 108, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 108, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + + 112, 112, 112, 112, 112, 112, 112, 0, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108 + } ; + +static const flex_int16_t yy_nxt[333] = + { 0, + 10, 11, 12, 13, 14, 10, 10, 15, 16, 17, + 10, 18, 10, 19, 10, 20, 21, 22, 10, 23, + 10, 10, 10, 24, 10, 10, 25, 17, 10, 18, + 10, 19, 10, 20, 21, 22, 10, 23, 10, 10, + 10, 24, 10, 10, 25, 26, 27, 29, 29, 84, + 30, 30, 32, 32, 33, 33, 39, 40, 39, 32, + 32, 43, 41, 39, 42, 45, 46, 44, 47, 48, + 49, 50, 51, 52, 55, 57, 56, 83, 62, 43, + 63, 73, 57, 45, 46, 44, 47, 48, 49, 50, + 51, 52, 39, 40, 39, 61, 62, 61, 63, 39, + + 39, 39, 61, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 108, 55, 108, 56, 74, 75, 40, 37, + 37, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 108, 57, 76, 77, 74, 75, 39, 39, 57, 61, + 61, 61, 62, 61, 78, 79, 80, 81, 61, 82, + 76, 77, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 78, 79, 80, 81, 95, 82, 35, 96, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 97, 98, 99, 100, 95, 61, 61, 96, 101, 102, + 103, 104, 105, 106, 107, 35, 108, 108, 97, 98, + + 99, 100, 108, 108, 108, 108, 101, 102, 103, 104, + 105, 106, 107, 28, 28, 28, 28, 28, 28, 31, + 31, 31, 31, 31, 31, 34, 34, 34, 34, 34, + 34, 36, 108, 108, 108, 36, 38, 38, 38, 38, + 38, 38, 53, 53, 108, 53, 108, 53, 54, 54, + 108, 54, 54, 54, 58, 108, 108, 108, 58, 58, + 59, 59, 59, 108, 59, 59, 39, 39, 39, 39, + 39, 39, 60, 60, 60, 60, 60, 60, 61, 61, + 61, 61, 61, 61, 9, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108 + } ; + +static const flex_int16_t yy_chk[333] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 4, 74, + 3, 4, 5, 6, 5, 6, 14, 14, 14, 5, + 6, 17, 15, 14, 15, 18, 19, 17, 20, 21, + 22, 23, 24, 25, 30, 32, 30, 73, 61, 17, + 43, 58, 32, 18, 19, 17, 20, 21, 22, 23, + 24, 25, 38, 38, 38, 42, 42, 42, 43, 38, + + 14, 14, 42, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 54, 55, 54, 55, 64, 65, 39, 37, + 11, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 9, 57, 66, 67, 64, 65, 38, 38, 57, 42, + 42, 60, 60, 60, 68, 69, 70, 71, 60, 72, + 66, 67, 75, 77, 78, 79, 80, 84, 85, 86, + 87, 88, 68, 69, 70, 71, 89, 72, 8, 90, + 75, 77, 78, 79, 80, 84, 85, 86, 87, 88, + 91, 92, 93, 94, 89, 60, 60, 90, 95, 96, + 97, 102, 103, 104, 106, 7, 0, 0, 91, 92, + + 93, 94, 0, 0, 0, 0, 95, 96, 97, 102, + 103, 104, 106, 109, 109, 109, 109, 109, 109, 110, + 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, + 111, 112, 0, 0, 0, 112, 113, 113, 113, 113, + 113, 113, 114, 114, 0, 114, 0, 114, 115, 115, + 0, 115, 115, 115, 116, 0, 0, 0, 116, 116, + 117, 117, 117, 0, 117, 117, 118, 118, 118, 118, + 118, 118, 119, 119, 119, 119, 119, 119, 120, 120, + 120, 120, 120, 120, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "bindlexer.l" +#line 2 "bindlexer.l" +#include +#include +#include +#include + +#define YY_NO_INPUT 1 +#define YYSTYPE char * + +#include "bindparser.h" + +int linenumber; +#define MAX_INCLUDE_DEPTH 10 +YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; +int include_stack_ln[MAX_INCLUDE_DEPTH]; +char *include_stack_name[MAX_INCLUDE_DEPTH]; +char *current_filename; +char *original_filename; +int include_stack_ptr = 0; +extern const char *bind_directory; + +#line 572 "bindlexer.c" + +#define YY_NO_INPUT 1 +#line 575 "bindlexer.c" + +#define INITIAL 0 +#define comment 1 +#define incl 2 +#define quoted 3 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals ( void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( void ); + +int yyget_debug ( void ); + +void yyset_debug ( int debug_flag ); + +YY_EXTRA_TYPE yyget_extra ( void ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in ( void ); + +void yyset_in ( FILE * _in_str ); + +FILE *yyget_out ( void ); + +void yyset_out ( FILE * _out_str ); + + int yyget_leng ( void ); + +char *yyget_text ( void ); + +int yyget_lineno ( void ); + +void yyset_lineno ( int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( void ); +#else +extern int yywrap ( void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * ); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( void ); +#else +static int input ( void ); +#endif + +#endif + + static int yy_start_stack_ptr = 0; + static int yy_start_stack_depth = 0; + static int *yy_start_stack = NULL; + + static void yy_push_state ( int _new_state ); + + static void yy_pop_state ( void ); + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 32 "bindlexer.l" + + + +#line 805 "bindlexer.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 109 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 285 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 35 "bindlexer.l" +BEGIN(comment); + YY_BREAK +case 2: +YY_RULE_SETUP +#line 36 "bindlexer.l" +/* eat anything that's not a '*' */ + YY_BREAK +case 3: +YY_RULE_SETUP +#line 37 "bindlexer.l" +/* eat up '*'s not followed by '/'s */ + YY_BREAK +case 4: +/* rule 4 can match eol */ +YY_RULE_SETUP +#line 38 "bindlexer.l" +++linenumber; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 39 "bindlexer.l" +BEGIN(INITIAL); + YY_BREAK +case 6: +YY_RULE_SETUP +#line 41 "bindlexer.l" +BEGIN(incl); + YY_BREAK +case 7: +YY_RULE_SETUP +#line 42 "bindlexer.l" +/* eat the whitespace */ + YY_BREAK +case 8: +YY_RULE_SETUP +#line 43 "bindlexer.l" +{ /* got the include file name */ + char filename[1024]; + if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) + { + fprintf( stderr, "Includes nested too deeply\n" ); + exit( 1 ); + } + + if (strlen(yytext) <= 2) { + fprintf( stderr, "Empty include directive\n" ); + exit( 1 ); + } + + yytext[strlen(yytext)-2]=0; + + include_stack[include_stack_ptr]=YY_CURRENT_BUFFER; + include_stack_name[include_stack_ptr]=current_filename=strdup(yytext+1); + include_stack_ln[include_stack_ptr++]=linenumber; + linenumber=1; + + int ret; + if(*(yytext+1)=='/') { + ret = snprintf(filename, sizeof(filename), "%s", yytext+1); + } + else { + ret = snprintf(filename, sizeof(filename), "%s/%s", bind_directory, yytext+1); + } + if (ret == -1 || ret >= sizeof(filename)) { + fprintf( stderr, "Filename '%s' is too long\n",yytext+1); + exit( 1 ); + } + + if (!(yyin=fopen(filename,"r"))) { + fprintf( stderr, "Unable to open '%s': %s\n",filename,strerror(errno)); + exit( 1 ); + } + + BEGIN(INITIAL); + yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); + + } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(comment): +case YY_STATE_EOF(incl): +case YY_STATE_EOF(quoted): +#line 86 "bindlexer.l" +{ + if ( --include_stack_ptr < 0 ) + { + yyterminate(); + } + + else + { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(include_stack[include_stack_ptr]); + linenumber=include_stack_ln[include_stack_ptr]; + free(include_stack_name[include_stack_ptr]); + if(include_stack_ptr) + current_filename=include_stack_name[include_stack_ptr-1]; + else + current_filename=original_filename; + } + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 109 "bindlexer.l" +return ZONETOK; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 111 "bindlexer.l" +return FILETOK; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 112 "bindlexer.l" +return OPTIONSTOK; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 113 "bindlexer.l" +return ALSONOTIFYTOK; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 114 "bindlexer.l" +return ACLTOK; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 115 "bindlexer.l" +return LOGGINGTOK; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 116 "bindlexer.l" +return DIRECTORYTOK; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 117 "bindlexer.l" +return MASTERTOK; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 118 "bindlexer.l" +return TYPETOK; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 119 "bindlexer.l" +yy_push_state(quoted); + YY_BREAK +case 19: +/* rule 19 can match eol */ +YY_RULE_SETUP +#line 120 "bindlexer.l" +yylval=strdup(yytext); return QUOTEDWORD; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 121 "bindlexer.l" +yy_pop_state(); + YY_BREAK +case 21: +YY_RULE_SETUP +#line 122 "bindlexer.l" +yylval=strdup(yytext);return AWORD; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 123 "bindlexer.l" +return OBRACE; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 124 "bindlexer.l" +return EBRACE; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 125 "bindlexer.l" +return SEMICOLON; + YY_BREAK +case 25: +/* rule 25 can match eol */ +YY_RULE_SETUP +#line 126 "bindlexer.l" +linenumber++; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 127 "bindlexer.l" +; + YY_BREAK +case 27: +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 128 "bindlexer.l" +; + YY_BREAK +case 28: +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 129 "bindlexer.l" +; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 130 "bindlexer.l" +ECHO; + YY_BREAK +#line 1081 "bindlexer.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 109 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 109 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 108); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return 0; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf ); + + yyfree( (void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr ) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + + static void yy_push_state (int _new_state ) +{ + if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) + { + yy_size_t new_size; + + (yy_start_stack_depth) += YY_START_STACK_INCR; + new_size = (yy_size_t) (yy_start_stack_depth) * sizeof( int ); + + if ( ! (yy_start_stack) ) + (yy_start_stack) = (int *) yyalloc( new_size ); + + else + (yy_start_stack) = (int *) yyrealloc( + (void *) (yy_start_stack), new_size ); + + if ( ! (yy_start_stack) ) + YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); + } + + (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; + + BEGIN(_new_state); +} + + static void yy_pop_state (void) +{ + if ( --(yy_start_stack_ptr) < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg ) +{ + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = NULL; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = NULL; + (yy_init) = 0; + (yy_start) = 0; + + (yy_start_stack_ptr) = 0; + (yy_start_stack_depth) = 0; + (yy_start_stack) = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Destroy the start condition stack. */ + yyfree( (yy_start_stack) ); + (yy_start_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 130 "bindlexer.l" + + diff --git a/pdns/bindlexer.l b/pdns/bindlexer.l new file mode 100644 index 0000000..370dbff --- /dev/null +++ b/pdns/bindlexer.l @@ -0,0 +1,130 @@ +%{ +#include +#include +#include +#include + +#define YY_NO_INPUT 1 +#define YYSTYPE char * + +#include "bindparser.h" + +int linenumber; +#define MAX_INCLUDE_DEPTH 10 +YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; +int include_stack_ln[MAX_INCLUDE_DEPTH]; +char *include_stack_name[MAX_INCLUDE_DEPTH]; +char *current_filename; +char *original_filename; +int include_stack_ptr = 0; +extern const char *bind_directory; + +%} + +%x comment +%x incl +%x quoted +%option stack +%option nounput +%option noyy_top_state +%option noinput + +%% + + +"/*" BEGIN(comment); +[^*\n]* /* eat anything that's not a '*' */ +"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ +\n ++linenumber; +"*"+"/" BEGIN(INITIAL); + +include BEGIN(incl); +[ \t;]* /* eat the whitespace */ +\"[^ \t\n";]+\"; { /* got the include file name */ + char filename[1024]; + if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) + { + fprintf( stderr, "Includes nested too deeply\n" ); + exit( 1 ); + } + + if (strlen(yytext) <= 2) { + fprintf( stderr, "Empty include directive\n" ); + exit( 1 ); + } + + yytext[strlen(yytext)-2]=0; + + include_stack[include_stack_ptr]=YY_CURRENT_BUFFER; + include_stack_name[include_stack_ptr]=current_filename=strdup(yytext+1); + include_stack_ln[include_stack_ptr++]=linenumber; + linenumber=1; + + int ret; + if(*(yytext+1)=='/') { + ret = snprintf(filename, sizeof(filename), "%s", yytext+1); + } + else { + ret = snprintf(filename, sizeof(filename), "%s/%s", bind_directory, yytext+1); + } + if (ret == -1 || ret >= sizeof(filename)) { + fprintf( stderr, "Filename '%s' is too long\n",yytext+1); + exit( 1 ); + } + + if (!(yyin=fopen(filename,"r"))) { + fprintf( stderr, "Unable to open '%s': %s\n",filename,strerror(errno)); + exit( 1 ); + } + + BEGIN(INITIAL); + yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); + + } + + +<> { + if ( --include_stack_ptr < 0 ) + { + yyterminate(); + } + + else + { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(include_stack[include_stack_ptr]); + linenumber=include_stack_ln[include_stack_ptr]; + free(include_stack_name[include_stack_ptr]); + if(include_stack_ptr) + current_filename=include_stack_name[include_stack_ptr-1]; + else + current_filename=original_filename; + } + } + + + + +zone return ZONETOK; + +file return FILETOK; +options return OPTIONSTOK; +also-notify return ALSONOTIFYTOK; +acl return ACLTOK; +logging return LOGGINGTOK; +directory return DIRECTORYTOK; +masters return MASTERTOK; +type return TYPETOK; +\" yy_push_state(quoted); +[^\"]* yylval=strdup(yytext); return QUOTEDWORD; +\" yy_pop_state(); +[^\" \t\n{};]* yylval=strdup(yytext);return AWORD; +\{ return OBRACE; +\} return EBRACE; +; return SEMICOLON; +\n linenumber++; +[ \t]* ; +\/\/.*$ ; +\#.*$ ; +%% diff --git a/pdns/bindparser.cc b/pdns/bindparser.cc new file mode 100644 index 0000000..fbd72f6 --- /dev/null +++ b/pdns/bindparser.cc @@ -0,0 +1,1705 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +#line 1 "bindparser.yy" /* yacc.c:339 */ + + +#include +#include +#include +#include +#include +#include +#include +#include "misc.hh" +#include "pdnsexception.hh" +#include "namespaces.hh" +#include "iputils.hh" +#define YYDEBUG 1 +extern int yydebug; +#include "bindparserclasses.hh" + +#define YYSTYPE char * + +extern "C" +{ + int yyparse(void); + int yylex(void); + void yyrestart(FILE *); + int yywrap() + { + return 1; + } +} + + +extern int yydebug; +const char *bind_directory; +extern int linenumber; +static void yyerror(const char *str) +{ + extern char *current_filename; + throw PDNSException("Error in bind configuration '"+string(current_filename)+"' on line "+itoa(linenumber)+": "+str); +} + +extern FILE *yyin; +static BindParser *parent; +BindDomainInfo s_di; + +void BindParser::parse(const string &fname) +{ + yydebug=0; + yyin=fopen(fname.c_str(),"r"); + yyrestart(yyin); + if(!yyin) + throw PDNSException("Unable to open '"+fname+"': "+strerror(errno)); + + linenumber=1; + parent=this; + extern char *current_filename; + extern char *original_filename; + + current_filename=original_filename=(char*)fname.c_str(); + + yyparse(); + +// cerr<<"Need to parse "<& BindParser::getDomains() +{ + return d_zonedomains; +} + +void BindParser::setVerbose(bool verbose) +{ + d_verbose=verbose; +} + +void BindParser::commit(BindDomainInfo DI) +{ + DI.hadFileDirective = (DI.filename != ""); + + if(DI.filename[0]!='/') + DI.filename=d_dir+"/"+DI.filename; + + if(d_verbose) + cerr<<"Domain "< /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 72 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 18 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 33 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 58 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 93 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 272 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 111, 111, 113, 116, 116, 116, 116, 119, 121, + 125, 129, 137, 148, 150, 155, 155, 158, 161, 163, + 167, 170, 172, 175, 175, 178, 178, 181, 188, 191, + 193, 196, 202, 204, 207, 207, 207, 210, 214, 217, + 219, 225, 225, 225, 229, 229, 229, 232, 235, 238, + 240, 243, 250, 252, 255, 263, 272, 281, 287 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "AWORD", "QUOTEDWORD", "OBRACE", + "EBRACE", "SEMICOLON", "ZONETOK", "FILETOK", "OPTIONSTOK", + "DIRECTORYTOK", "ACLTOK", "LOGGINGTOK", "CLASSTOK", "TYPETOK", + "MASTERTOK", "ALSONOTIFYTOK", "$accept", "root_commands", "root_command", + "commands", "command", "global_zone_command", "global_options_command", + "acl_command", "acl_block", "acls", "acl", "options_commands", + "options_command", "options_directory_command", "also_notify_command", + "also_notify_list", "also_notify", "terms", "term", "block", + "zone_block", "zone_commands", "zone_command", "zone_masters_command", + "zone_also_notify_command", "zone_also_notify_list", "zone_also_notify", + "masters", "master", "zone_file_command", "zone_type_command", + "quotedname", "filename", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272 +}; +# endif + +#define YYPACT_NINF -31 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-31))) + +#define YYTABLE_NINF -22 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -31, 2, -31, 5, 5, 11, 5, 32, 24, 34, + 35, 37, -3, -31, -31, -31, -31, -31, -31, 23, + -31, -31, -31, -31, 18, -31, 28, -31, -31, 38, + 38, 28, -31, -31, 41, -31, -31, -31, -31, -31, + -31, 42, -31, -31, -31, -31, 40, 43, 45, -31, + -31, 46, 0, -31, 47, 44, 48, -31, 16, -31, + 28, -31, 50, 51, -31, -31, -31, 52, -31, 41, + -31, 53, -31, 56, -31, -31, 55, -31, -31, -31, + 45, -31, -31, -31, 60, -31, -31, -31, 58, 59, + -31, 60, -31 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 32, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 6, 7, 5, 25, 26, 10, + 46, 44, 45, 57, 0, 55, 32, 27, 58, 0, + 0, 32, 56, 52, 29, 3, 34, 8, 33, 35, + 36, 0, 39, 11, 23, 24, 0, 0, 18, 15, + 16, 0, 0, 31, 0, 0, 32, 12, 32, 13, + 32, 20, 0, 0, 14, 54, 47, 0, 28, 29, + 37, 0, 38, 0, 41, 42, 0, 43, 22, 17, + 18, 53, 30, 9, 49, 40, 19, 51, 0, 0, + 48, 49, 50 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -31, -31, -31, -31, -1, -9, 64, -31, 39, -13, + -31, -30, -31, -31, -31, 3, -31, -31, -31, -31, + 27, -31, -31, -31, -31, -21, -31, -31, -31, -31, + -31, 1, -31 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 1, 12, 56, 44, 14, 45, 16, 49, 62, + 63, 46, 47, 17, 18, 54, 55, 19, 38, 39, + 43, 58, 76, 20, 77, 88, 89, 52, 67, 21, + 22, 24, 30 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + 13, 51, 2, 65, 35, 25, 66, 27, 29, 23, + 3, 4, 5, 6, 7, 8, 26, 9, 10, 11, + 40, 41, 72, 42, 3, 4, 36, 23, 37, 31, + 78, 9, 10, 73, -21, 28, 23, 32, 5, 6, + 33, 8, 34, 48, 53, 11, 59, 42, 61, 75, + 60, 69, 64, 68, 70, 71, 79, 74, 80, 81, + 83, 84, 85, 87, 90, 15, 91, 86, 57, 50, + 92, 0, 82 +}; + +static const yytype_int8 yycheck[] = +{ + 1, 31, 0, 3, 7, 4, 6, 6, 7, 4, + 8, 9, 10, 11, 12, 13, 5, 15, 16, 17, + 19, 3, 6, 5, 8, 9, 3, 4, 5, 5, + 60, 15, 16, 17, 6, 3, 4, 3, 10, 11, + 5, 13, 5, 5, 3, 17, 6, 5, 3, 58, + 7, 7, 6, 6, 6, 56, 6, 58, 7, 7, + 7, 5, 7, 3, 6, 1, 7, 80, 41, 30, + 91, -1, 69 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 19, 0, 8, 9, 10, 11, 12, 13, 15, + 16, 17, 20, 22, 23, 24, 25, 31, 32, 35, + 41, 47, 48, 4, 49, 49, 5, 49, 3, 49, + 50, 5, 3, 5, 5, 7, 3, 5, 36, 37, + 49, 3, 5, 38, 22, 24, 29, 30, 5, 26, + 26, 29, 45, 3, 33, 34, 21, 38, 39, 6, + 7, 3, 27, 28, 6, 3, 6, 46, 6, 7, + 6, 22, 6, 17, 22, 23, 40, 42, 29, 6, + 7, 7, 33, 7, 5, 7, 27, 3, 43, 44, + 6, 7, 43 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 18, 19, 19, 20, 20, 20, 20, 21, 21, + 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, + 28, 29, 29, 30, 30, 24, 24, 31, 32, 33, + 33, 34, 35, 35, 36, 36, 36, 37, 38, 39, + 39, 40, 40, 40, 23, 23, 23, 41, 42, 43, + 43, 44, 45, 45, 46, 47, 48, 49, 50 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 3, 1, 1, 1, 1, 0, 3, + 1, 3, 4, 4, 4, 3, 3, 3, 0, 3, + 1, 0, 3, 1, 1, 1, 1, 2, 4, 0, + 3, 1, 0, 2, 1, 1, 1, 3, 3, 0, + 3, 1, 1, 1, 1, 1, 1, 4, 4, 0, + 3, 1, 0, 3, 1, 2, 2, 1, 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 11: +#line 130 "bindparser.yy" /* yacc.c:1646 */ + { + s_di.name=DNSName((yyvsp[-1])); + free((yyvsp[-1])); + parent->commit(s_di); + s_di.clear(); + } +#line 1401 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 12: +#line 138 "bindparser.yy" /* yacc.c:1646 */ + { + s_di.name=DNSName((yyvsp[-2])); + free((yyvsp[-2])); + parent->commit(s_di); + s_di.clear(); + } +#line 1412 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 27: +#line 182 "bindparser.yy" /* yacc.c:1646 */ + { + parent->setDirectory((yyvsp[0])); + free((yyvsp[0])); + } +#line 1421 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 31: +#line 197 "bindparser.yy" /* yacc.c:1646 */ + { + parent->addAlsoNotify((yyvsp[0])); + free((yyvsp[0])); + } +#line 1430 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 51: +#line 244 "bindparser.yy" /* yacc.c:1646 */ + { + s_di.alsoNotify.insert((yyvsp[0])); + free((yyvsp[0])); + } +#line 1439 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 54: +#line 256 "bindparser.yy" /* yacc.c:1646 */ + { + s_di.masters.push_back(ComboAddress((yyvsp[0]), 53)); + free((yyvsp[0])); + } +#line 1448 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 55: +#line 264 "bindparser.yy" /* yacc.c:1646 */ + { + // printf("Found a filename: '%s'\n",$2); + s_di.filename=(yyvsp[0]); + free((yyvsp[0])); + } +#line 1458 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 56: +#line 273 "bindparser.yy" /* yacc.c:1646 */ + { + s_di.type=(yyvsp[0]); + free((yyvsp[0])); + } +#line 1467 "bindparser.cc" /* yacc.c:1646 */ + break; + + case 57: +#line 282 "bindparser.yy" /* yacc.c:1646 */ + { + (yyval)=(yyvsp[0]); + } +#line 1475 "bindparser.cc" /* yacc.c:1646 */ + break; + + +#line 1479 "bindparser.cc" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} diff --git a/pdns/bindparser.h b/pdns/bindparser.h new file mode 100644 index 0000000..a90353f --- /dev/null +++ b/pdns/bindparser.h @@ -0,0 +1,94 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_BINDPARSER_HH_INCLUDED +# define YY_YY_BINDPARSER_HH_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + AWORD = 258, + QUOTEDWORD = 259, + OBRACE = 260, + EBRACE = 261, + SEMICOLON = 262, + ZONETOK = 263, + FILETOK = 264, + OPTIONSTOK = 265, + DIRECTORYTOK = 266, + ACLTOK = 267, + LOGGINGTOK = 268, + CLASSTOK = 269, + TYPETOK = 270, + MASTERTOK = 271, + ALSONOTIFYTOK = 272 + }; +#endif +/* Tokens. */ +#define AWORD 258 +#define QUOTEDWORD 259 +#define OBRACE 260 +#define EBRACE 261 +#define SEMICOLON 262 +#define ZONETOK 263 +#define FILETOK 264 +#define OPTIONSTOK 265 +#define DIRECTORYTOK 266 +#define ACLTOK 267 +#define LOGGINGTOK 268 +#define CLASSTOK 269 +#define TYPETOK 270 +#define MASTERTOK 271 +#define ALSONOTIFYTOK 272 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_BINDPARSER_HH_INCLUDED */ diff --git a/pdns/bindparser.hh b/pdns/bindparser.hh new file mode 100644 index 0000000..a90353f --- /dev/null +++ b/pdns/bindparser.hh @@ -0,0 +1,94 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_BINDPARSER_HH_INCLUDED +# define YY_YY_BINDPARSER_HH_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + AWORD = 258, + QUOTEDWORD = 259, + OBRACE = 260, + EBRACE = 261, + SEMICOLON = 262, + ZONETOK = 263, + FILETOK = 264, + OPTIONSTOK = 265, + DIRECTORYTOK = 266, + ACLTOK = 267, + LOGGINGTOK = 268, + CLASSTOK = 269, + TYPETOK = 270, + MASTERTOK = 271, + ALSONOTIFYTOK = 272 + }; +#endif +/* Tokens. */ +#define AWORD 258 +#define QUOTEDWORD 259 +#define OBRACE 260 +#define EBRACE 261 +#define SEMICOLON 262 +#define ZONETOK 263 +#define FILETOK 264 +#define OPTIONSTOK 265 +#define DIRECTORYTOK 266 +#define ACLTOK 267 +#define LOGGINGTOK 268 +#define CLASSTOK 269 +#define TYPETOK 270 +#define MASTERTOK 271 +#define ALSONOTIFYTOK 272 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_BINDPARSER_HH_INCLUDED */ diff --git a/pdns/bindparser.yy b/pdns/bindparser.yy new file mode 100644 index 0000000..df05341 --- /dev/null +++ b/pdns/bindparser.yy @@ -0,0 +1,288 @@ +%{ + +#include +#include +#include +#include +#include +#include +#include +#include "misc.hh" +#include "pdnsexception.hh" +#include "namespaces.hh" +#include "iputils.hh" +#define YYDEBUG 1 +extern int yydebug; +#include "bindparserclasses.hh" + +#define YYSTYPE char * + +extern "C" +{ + int yyparse(void); + int yylex(void); + void yyrestart(FILE *); + int yywrap() + { + return 1; + } +} + + +extern int yydebug; +const char *bind_directory; +extern int linenumber; +static void yyerror(const char *str) +{ + extern char *current_filename; + throw PDNSException("Error in bind configuration '"+string(current_filename)+"' on line "+itoa(linenumber)+": "+str); +} + +extern FILE *yyin; +static BindParser *parent; +BindDomainInfo s_di; + +void BindParser::parse(const string &fname) +{ + yydebug=0; + yyin=fopen(fname.c_str(),"r"); + yyrestart(yyin); + if(!yyin) + throw PDNSException("Unable to open '"+fname+"': "+strerror(errno)); + + linenumber=1; + parent=this; + extern char *current_filename; + extern char *original_filename; + + current_filename=original_filename=(char*)fname.c_str(); + + yyparse(); + +// cerr<<"Need to parse "<& BindParser::getDomains() +{ + return d_zonedomains; +} + +void BindParser::setVerbose(bool verbose) +{ + d_verbose=verbose; +} + +void BindParser::commit(BindDomainInfo DI) +{ + DI.hadFileDirective = (DI.filename != ""); + + if(DI.filename[0]!='/') + DI.filename=d_dir+"/"+DI.filename; + + if(d_verbose) + cerr<<"Domain "<commit(s_di); + s_di.clear(); + } + | + ZONETOK quotedname AWORD zone_block + { + s_di.name=DNSName($2); + free($2); + parent->commit(s_di); + s_di.clear(); + } + ; + + +global_options_command: + OPTIONSTOK OBRACE options_commands EBRACE + | + LOGGINGTOK OBRACE options_commands EBRACE + ; + + +acl_command: + ACLTOK quotedname acl_block | ACLTOK filename acl_block + ; + +acl_block: OBRACE acls EBRACE + ; + +acls: + | + acl SEMICOLON acls + ; + +acl: + AWORD + ; + +options_commands: + | + options_command SEMICOLON options_commands + ; + +options_command: command | global_options_command + ; + +global_options_command: options_directory_command | also_notify_command + ; + +options_directory_command: DIRECTORYTOK quotedname + { + parent->setDirectory($2); + free($2); + } + ; + +also_notify_command: ALSONOTIFYTOK OBRACE also_notify_list EBRACE + ; + +also_notify_list: + | + also_notify SEMICOLON also_notify_list + ; + +also_notify: AWORD + { + parent->addAlsoNotify($1); + free($1); + } + ; +terms: /* empty */ + | + terms term + ; + +term: AWORD | block | quotedname + ; +block: + OBRACE commands EBRACE + ; + +zone_block: + OBRACE zone_commands EBRACE + ; + +zone_commands: + | + zone_commands zone_command SEMICOLON + ; + +/* commands in zone + * in global scope also_notify_command is used instead of zone_also_notify_command + */ +zone_command: command | global_zone_command | zone_also_notify_command + ; + +/* zone commands that also are available at global scope */ +global_zone_command: zone_file_command | zone_type_command | zone_masters_command + ; + +zone_masters_command: MASTERTOK OBRACE masters EBRACE + ; + +zone_also_notify_command: ALSONOTIFYTOK OBRACE zone_also_notify_list EBRACE + ; + +zone_also_notify_list: + | + zone_also_notify SEMICOLON zone_also_notify_list + ; + +zone_also_notify: AWORD + { + s_di.alsoNotify.insert($1); + free($1); + } + ; + +masters: /* empty */ + | + masters master SEMICOLON + ; + +master: AWORD + { + s_di.masters.push_back(ComboAddress($1, 53)); + free($1); + } + ; + +zone_file_command: + FILETOK quotedname + { + // printf("Found a filename: '%s'\n",$2); + s_di.filename=$2; + free($2); + } + ; + +zone_type_command: +TYPETOK AWORD + { + s_di.type=$2; + free($2); + } + ; + + +quotedname: + QUOTEDWORD + { + $$=$1; + } + ; + +filename: AWORD + ; diff --git a/pdns/bindparserclasses.hh b/pdns/bindparserclasses.hh new file mode 100644 index 0000000..12e60c2 --- /dev/null +++ b/pdns/bindparserclasses.hh @@ -0,0 +1,101 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef BINDPARSER_HH +#define BINDPARSER_HH +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" + +class BindDomainInfo +{ +public: + BindDomainInfo() : hadFileDirective(false), d_dev(0), d_ino(0) + {} + + void clear() + { + name=DNSName(); + filename=type=""; + masters.clear(); + alsoNotify.clear(); + d_dev=0; + d_ino=0; + } + DNSName name; + string viewName; + string filename; + vector masters; + set alsoNotify; + string type; + bool hadFileDirective; + + dev_t d_dev; + ino_t d_ino; + + bool operator<(const BindDomainInfo& b) const + { + return make_pair(d_dev, d_ino) < make_pair(b.d_dev, b.d_ino); + } +}; + +extern const char *bind_directory; +extern FILE *yyin; +class BindParser +{ + public: + BindParser() : d_dir("."), d_verbose(false) + { + yyin=0; + extern int include_stack_ptr; + include_stack_ptr=0; + + bind_directory=d_dir.c_str(); + } + ~BindParser() + { + if(yyin) { + fclose(yyin); + yyin=0; + } + } + void parse(const string &fname); + void commit(BindDomainInfo DI); + void setDirectory(const string &dir); + const string &getDirectory(); + const vector& getDomains(); + void setVerbose(bool verbose); + void addAlsoNotify(const string &host); + set & getAlsoNotify() { return this->alsoNotify; } +private: + string d_dir; + typedef map zonedomain_t; + set alsoNotify; + vector d_zonedomains; + bool d_verbose; +}; + +#endif /* BINDPARSER_HH */ diff --git a/pdns/cachecleaner.hh b/pdns/cachecleaner.hh new file mode 100644 index 0000000..8840298 --- /dev/null +++ b/pdns/cachecleaner.hh @@ -0,0 +1,215 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include "lock.hh" + +// this function can clean any cache that has a getTTD() method on its entries, a preRemoval() method and a 'sequence' index as its second index +// the ritual is that the oldest entries are in *front* of the sequence collection, so on a hit, move an item to the end +// on a miss, move it to the beginning +template void pruneCollection(C& container, T& collection, unsigned int maxCached, unsigned int scanFraction=1000) +{ + time_t now=time(0); + unsigned int toTrim=0; + + unsigned int cacheSize=collection.size(); + + if(cacheSize > maxCached) { + toTrim = cacheSize - maxCached; + } + +// cout<<"Need to trim "<::type sequence_t; + sequence_t& sidx=collection.template get<1>(); + + unsigned int tried=0, lookAt, erased=0; + + // two modes - if toTrim is 0, just look through 1/scanFraction of all records + // and nuke everything that is expired + // otherwise, scan first 5*toTrim records, and stop once we've nuked enough + if(toTrim) + lookAt=5*toTrim; + else + lookAt=cacheSize/scanFraction; + + typename sequence_t::iterator iter=sidx.begin(), eiter; + for(; iter != sidx.end() && tried < lookAt ; ++tried) { + if(iter->getTTD() < now) { + container.preRemoval(*iter); + sidx.erase(iter++); + erased++; + } + else + ++iter; + + if(toTrim && erased >= toTrim) + break; + } + + //cout<<"erased "<= toTrim) // done + return; + + toTrim -= erased; + + //if(toTrim) + // cout<<"Still have "< void moveCacheItemToFrontOrBack(T& collection, typename T::iterator& iter, bool front) +{ + typedef typename T::template nth_index<1>::type sequence_t; + sequence_t& sidx=collection.template get<1>(); + typename sequence_t::iterator si=collection.template project<1>(iter); + if(front) + sidx.relocate(sidx.begin(), si); // at the beginning of the delete queue + else + sidx.relocate(sidx.end(), si); // back +} + +template void moveCacheItemToFront(T& collection, typename T::iterator& iter) +{ + moveCacheItemToFrontOrBack(collection, iter, true); +} + +template void moveCacheItemToBack(T& collection, typename T::iterator& iter) +{ + moveCacheItemToFrontOrBack(collection, iter, false); +} + +template uint64_t pruneLockedCollectionsVector(vector& maps, uint64_t maxCached, uint64_t cacheSize) +{ + time_t now = time(nullptr); + uint64_t totErased = 0; + uint64_t toTrim = 0; + uint64_t lookAt = 0; + + // two modes - if toTrim is 0, just look through 10% of the cache and nuke everything that is expired + // otherwise, scan first 5*toTrim records, and stop once we've nuked enough + if (maxCached && cacheSize > maxCached) { + toTrim = cacheSize - maxCached; + lookAt = 5 * toTrim; + } else { + lookAt = cacheSize / 10; + } + + for(auto& mc : maps) { + WriteLock wl(&mc.d_mut); + auto& sidx = boost::multi_index::get<2>(mc.d_map); + uint64_t erased = 0, lookedAt = 0; + for(auto i = sidx.begin(); i != sidx.end(); lookedAt++) { + if(i->ttd < now) { + i = sidx.erase(i); + erased++; + } else { + ++i; + } + + if(toTrim && erased > toTrim / maps.size()) + break; + + if(lookedAt > lookAt / maps.size()) + break; + } + totErased += erased; + } + + return totErased; +} + +template uint64_t purgeLockedCollectionsVector(vector& maps) +{ + uint64_t delcount=0; + + for(auto& mc : maps) { + WriteLock wl(&mc.d_mut); + delcount += mc.d_map.size(); + mc.d_map.clear(); + } + + return delcount; +} + +template uint64_t purgeLockedCollectionsVector(vector& maps, const std::string& match) +{ + uint64_t delcount=0; + string prefix(match); + prefix.resize(prefix.size()-1); + DNSName dprefix(prefix); + for(auto& mc : maps) { + WriteLock wl(&mc.d_mut); + auto& idx = boost::multi_index::get<1>(mc.d_map); + auto iter = idx.lower_bound(dprefix); + auto start = iter; + + for(; iter != idx.end(); ++iter) { + if(!iter->qname.isPartOf(dprefix)) { + break; + } + delcount++; + } + idx.erase(start, iter); + } + + return delcount; +} + +template uint64_t purgeExactLockedCollection(T& mc, const DNSName& qname) +{ + uint64_t delcount=0; + WriteLock wl(&mc.d_mut); + auto& idx = boost::multi_index::get<1>(mc.d_map); + auto range = idx.equal_range(qname); + if(range.first != range.second) { + delcount += distance(range.first, range.second); + idx.erase(range.first, range.second); + } + + return delcount; +} + +template +std::pair +lruReplacingInsert(Index& i,const typename Index::value_type& x) +{ + std::pair res = i.insert(x); + if (!res.second) { + moveCacheItemToBack(i, res.first); + res.second = i.replace(res.first, x); + } + return res; +} diff --git a/pdns/calidns.cc b/pdns/calidns.cc new file mode 100644 index 0000000..0f11e79 --- /dev/null +++ b/pdns/calidns.cc @@ -0,0 +1,536 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "dns_random.hh" +#include "dnsparser.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "ednsoptions.hh" +#include "ednssubnet.hh" +#include "misc.hh" +#include "sstuff.hh" +#include "statbag.hh" + +using std::thread; +using std::unique_ptr; + +StatBag S; + +static std::atomic g_recvcounter, g_recvbytes; +static volatile bool g_done; + +namespace po = boost::program_options; +static po::variables_map g_vm; + +static bool g_quiet; + +static void* recvThread(const vector* sockets) +{ + vector rfds, fds; + for(const auto& s : *sockets) { + struct pollfd pfd; + pfd.fd = s->getHandle(); + pfd.events = POLLIN; + pfd.revents = 0; + rfds.push_back(pfd); + } + + int err; + +#if HAVE_RECVMMSG + vector buf(100); + for(auto& m : buf) { + fillMSGHdr(&m.msg_hdr, new struct iovec, new char[512], 512, new char[1500], 1500, new ComboAddress("127.0.0.1")); + } +#else + struct msghdr buf; + fillMSGHdr(&buf, new struct iovec, new char[512], 512, new char[1500], 1500, new ComboAddress("127.0.0.1")); +#endif + + while(!g_done) { + fds=rfds; + + err = poll(&fds[0], fds.size(), -1); + if (err < 0) { + if (errno == EINTR) + continue; + unixDie("Unable to poll for new UDP events"); + } + + for(auto &pfd : fds) { + if (pfd.revents & POLLIN) { +#if HAVE_RECVMMSG + if ((err=recvmmsg(pfd.fd, &buf[0], buf.size(), MSG_WAITFORONE, 0)) < 0 ) { + if(errno != EAGAIN) + unixDie("recvmmsg"); + continue; + } + g_recvcounter+=err; + for(int n=0; n < err; ++n) + g_recvbytes += buf[n].msg_len; +#else + if ((err = recvmsg(pfd.fd, &buf, 0)) < 0) { + if (errno != EAGAIN) + unixDie("recvmsg"); + continue; + } + g_recvcounter++; + for (int i = 0; i < buf.msg_iovlen; i++) + g_recvbytes += buf.msg_iov[i].iov_len; +#endif + } + } + } + return 0; +} + +static void setSocketBuffer(int fd, int optname, uint32_t size) +{ + uint32_t psize=0; + socklen_t len=sizeof(psize); + + if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) { + if (!g_quiet) { + cerr<<"Not decreasing socket buffer size from "<* packet, const Netmask& ecsRange) +{ + /* the last 4 bytes of the packet are the IPv4 address */ + ComboAddress rnd = getRandomAddressFromRange(ecsRange); + uint32_t addr = rnd.sin4.sin_addr.s_addr; + + const auto packetSize = packet->size(); + if (packetSize < sizeof(addr)) { + return; + } + + memcpy(&packet->at(packetSize - sizeof(addr)), &addr, sizeof(addr)); +} + +static void sendPackets(const vector* sockets, const vector* >& packets, int qps, ComboAddress dest, const Netmask& ecsRange) +{ + unsigned int burst=100; + const auto nsecPerBurst=1*(unsigned long)(burst*1000000000.0/qps); + struct timespec nsec; + nsec.tv_sec=0; + nsec.tv_nsec=0; + int count=0; + unsigned int nBursts=0; + DTime dt; + dt.set(); + + struct Unit { + struct msghdr msgh; + struct iovec iov; + char cbuf[256]; + }; + vector > units; + int ret; + + for(const auto& p : packets) { + count++; + + Unit u; + + if (!ecsRange.empty()) { + replaceEDNSClientSubnet(p, ecsRange); + } + + fillMSGHdr(&u.msgh, &u.iov, nullptr, 0, (char*)&(*p)[0], p->size(), &dest); + if((ret=sendmsg((*sockets)[count % sockets->size()]->getHandle(), + &u.msgh, 0))) + if(ret < 0) + unixDie("sendmsg"); + + + if(!(count%burst)) { + nBursts++; + // Calculate the time in nsec we need to sleep to the next burst. + // If this is negative, it means that we are not achieving the requested + // target rate, in which case we skip the sleep. + int toSleep = nBursts*nsecPerBurst - 1000*dt.udiffNoReset(); + if (toSleep > 0) { + nsec.tv_nsec = toSleep; + nanosleep(&nsec, 0); + } + } + } +} + +static void usage(po::options_description &desc) { + cerr<<"Syntax: calidns [OPTIONS] QUERY_FILE DESTINATION INITIAL_QPS HITRATE"<(), "Add EDNS Client Subnet option to outgoing queries using random addresses from the specified range (IPv4 only)") + ("ecs-from-file", "Read IP or subnet values from the query file and add them as EDNS Client Subnet options to outgoing queries") + ("increment", po::value()->default_value(1.1), "Set the factor to increase the QPS load per run") + ("maximum-qps", po::value(), "Stop incrementing once this rate has been reached, to provide a stable load") + ("minimum-success-rate", po::value()->default_value(0), "Stop the test as soon as the success rate drops below this value, in percent") + ("plot-file", po::value(), "Write results to the specific file") + ("quiet", "Whether to run quietly, outputting only the maximum QPS reached. This option is mostly useful when used with --minimum-success-rate") + ("want-recursion", "Set the Recursion Desired flag on queries"); + po::options_description alloptions; + po::options_description hidden("hidden options"); + hidden.add_options() + ("query-file", po::value(), "File with queries") + ("destination", po::value(), "Destination address") + ("initial-qps", po::value(), "Initial number of queries per second") + ("hitrate", po::value(), "Aim this percent cache hitrate"); + + alloptions.add(desc).add(hidden); + po::positional_options_description p; + p.add("query-file", 1); + p.add("destination", 1); + p.add("initial-qps", 1); + p.add("hitrate", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + if (g_vm.count("help")) { + usage(desc); + return EXIT_SUCCESS; + } + + if (g_vm.count("version")) { + cerr<<"calidns "<(); + } + catch(...) { + } + + bool wantRecursion = g_vm.count("want-recursion"); + bool useECSFromFile = g_vm.count("ecs-from-file"); + g_quiet = g_vm.count("quiet"); + + double hitrate = g_vm["hitrate"].as(); + if (hitrate > 100 || hitrate < 0) { + cerr<<"hitrate must be between 0 and 100, not "<(); + + uint32_t maximumQps = std::numeric_limits::max(); + if (g_vm.count("maximum-qps")) { + maximumQps = g_vm["maximum-qps"].as(); + } + + double minimumSuccessRate = g_vm["minimum-success-rate"].as(); + if (minimumSuccessRate > 100.0 || minimumSuccessRate < 0.0) { + cerr<<"Minimum success rate must be between 0 and 100, not "<()); + if (!ecsRange.empty()) { + + if (!ecsRange.isIpv4()) { + cerr<<"Only IPv4 ranges are supported for ECS at the moment!"<()); + string line; + reportAllTypes(); + vector > > unknown, known; + std::vector fields; + fields.reserve(3); + + while(getline(ifs, line)) { + vector packet; + DNSPacketWriter::optvect_t ednsOptions; + boost::trim(line); + if (line.empty() || line.at(0) == '#') { + continue; + } + + fields.clear(); + stringtok(fields, line, "\t "); + if ((useECSFromFile && fields.size() < 3) || fields.size() < 2) { + cerr<<"Skipping invalid line '"<rd=wantRecursion; + pw.getHeader()->id=dns_random(UINT16_MAX); + + if(!subnet.empty() || !ecsRange.empty()) { + EDNSSubnetOpts opt; + opt.source = Netmask(subnet.empty() ? "0.0.0.0/32" : subnet); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + } + + if(!ednsOptions.empty() || pw.getHeader()->id % 2) { + pw.addOpt(1500, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw.commit(); + } + unknown.emplace_back(std::make_shared>(packet)); + } + random_shuffle(unknown.begin(), unknown.end()); + if (!g_quiet) { + cout<<"Generated "< sockets; + ComboAddress dest; + try { + dest = ComboAddress(g_vm["destination"].as(), 53); + } + catch (PDNSException &e) { + cerr<connect(dest); + setSocketSendBuffer(sock->getHandle(), 2000000); + setSocketReceiveBuffer(sock->getHandle(), 2000000); + sockets.push_back(sock); + } + new thread(recvThread, &sockets); + uint32_t qps; + + ofstream plot; + if (g_vm.count("plot-file")) { + plot.open(g_vm["plot-file"].as()); + if (!plot) { + cerr<<"Error opening "<()<<" for writing: "< unknown.size()) { + cerr<<"Not enough queries remaining (need at least "<*> toSend; + unsigned int n; + for(n=0; n < misses; ++n) { + auto ptr=unknown.back(); + unknown.pop_back(); + toSend.push_back(ptr.get()); + known.push_back(ptr); + } + for(;n < total; ++n) { + toSend.push_back(known[dns_random(known.size())].get()); + } + random_shuffle(toSend.begin(), toSend.end()); + g_recvcounter.store(0); + g_recvbytes=0; + DTime dt; + dt.set(); + + sendPackets(&sockets, toSend, qps, dest, ecsRange); + + const auto udiff = dt.udiffNoReset(); + const auto realqps=toSend.size()/(udiff/1000000.0); + if (!g_quiet) { + cout<<"Achieved "< 0.0 && perc < minimumSuccessRate) { + if (g_quiet) { + cout<= 100.0) { + bestPerfectQPS = std::max(bestPerfectQPS, realReceivedQPS); + } + } + + if (plot) { + plot.flush(); + } + + // t1.detach(); +} + catch(std::exception& e) +{ + cerr<<"Fatal error: "<= 1.62 +#ifndef BOOST_CB_ENABLE_DEBUG +#define BOOST_CB_ENABLE_DEBUG 0 +#endif + +#if BOOST_CB_ENABLE_DEBUG +// https://github.com/boostorg/circular_buffer/pull/9 +// https://svn.boost.org/trac10/ticket/6277 +#error Building with BOOST_CB_ENABLE_DEBUG prevents accessing a boost::circular_buffer from more than one thread at once +#endif /* BOOST_CB_ENABLE_DEBUG */ + +#include diff --git a/pdns/comfun.cc b/pdns/comfun.cc new file mode 100644 index 0000000..c78ebd8 --- /dev/null +++ b/pdns/comfun.cc @@ -0,0 +1,545 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "statbag.hh" +#include "zoneparser-tng.hh" +#include "namespaces.hh" +#include "dnsrecords.hh" +#include +#include +#include +#include +#include "inflighter.cc" +//#include "malloctrace.hh" +StatBag S; +bool g_quiet; +std::unique_ptr g_powerdns; +std::atomic g_count; +std::atomic g_stop; + + +struct namecount { + set names; + unsigned int count; + bool isPowerDNS{false}; +}; + +struct DNSResult +{ + string content; + int ttl{0}; + uint16_t qclass; +}; + +struct NSQuery +{ + ComboAddress a; + set nsnames; + DNSName qname; + unsigned int count; +}; + +struct SendReceive +{ + typedef int Identifier; + typedef DNSResult Answer; // ip + int d_socket; + deque d_idqueue; + + SendReceive(map& res) : d_res(res) + { + d_socket = socket(AF_INET, SOCK_DGRAM, 0); + int val=1; + setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + + for(unsigned int id =0 ; id < std::numeric_limits::max(); ++id) + d_idqueue.push_back(id); + } + + ~SendReceive() + { + close(d_socket); + } + + Identifier send(NSQuery& domain) + { + //cerr<<"Sending query for '"< packet; + + DNSPacketWriter pw(packet, domain.qname, QType::TXT, 3); + + if(d_idqueue.empty()) { + cerr<<"Exhausted ids!"<id = d_idqueue.front(); + d_idqueue.pop_front(); + pw.getHeader()->rd = 0; + pw.getHeader()->qr = 0; + + if(::sendto(d_socket, &*packet.begin(), packet.size(), 0, (struct sockaddr*)&domain.a, domain.a.getSocklen()) < 0) + d_senderrors++; + + return pw.getHeader()->id; + } + + bool receive(Identifier& id, DNSResult& dr) + { + if(waitForData(d_socket, 0, 500000) > 0) { + char buf[512]; + ComboAddress from; + from.sin4.sin_family = AF_INET; + socklen_t socklen=from.getSocklen(); + int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); + if(len < 0) { + d_receiveerrors++; + return 0; + } + else { + d_receiveds++; + } + // parse packet, set 'id', fill out 'ip' + + MOADNSParser mdp(false, string(buf, len)); + if(!g_quiet) { + cout<<"Reply to question for qname='"<getZoneRepresentation(); + dr.ttl=a.first.d_ttl; + } + } + if(dr.content.empty()) + dr.content="RCode: "+RCode::to_s(mdp.d_header.rcode); + return 1; + } + return 0; + } + + void deliverTimeout(const Identifier& id) + { + if(!g_quiet) { + cout<<"Timeout for id "<second.isPowerDNS) { + (*g_powerdns)<second.isPowerDNS=true; + } + + } + + } + unsigned int d_errors, d_nxdomains, d_nodatas, d_oks, d_unknowns; + unsigned int d_receiveds, d_receiveerrors, d_senderrors; + map& d_res; +}; + + +struct RESResult +{ + vector addrs; + uint16_t rcode; +}; + +typedef DNSName RESQuery; + +struct SendReceiveRes +{ + typedef int Identifier; + typedef RESResult Answer; // ip + int d_socket; + deque d_idqueue; + map>& d_out; + SendReceiveRes(const ComboAddress& remote, map>& out) : d_out(out) + { + d_socket = socket(AF_INET, SOCK_DGRAM, 0); + int val=1; + setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + connect(d_socket, (struct sockaddr*)&remote, remote.getSocklen()); + for(unsigned int id =0 ; id < std::numeric_limits::max(); ++id) + d_idqueue.push_back(id); + } + + ~SendReceiveRes() + { + close(d_socket); + } + + Identifier send(RESQuery& domain) + { + //cerr<<"Sending query for '"< packet; + + DNSPacketWriter pw(packet, domain, QType::A); + + if(d_idqueue.empty()) { + cerr<<"Exhausted ids!"<id = d_idqueue.front(); + d_idqueue.pop_front(); + pw.getHeader()->rd = 1; + pw.getHeader()->qr = 0; + + if(::send(d_socket, &*packet.begin(), packet.size(), 0) < 0) { + cout<<"Error sending: "<id; + } + + bool receive(Identifier& id, RESResult& dr) + { + if(waitForData(d_socket, 0, 500000) > 0) { + char buf[512]; + ComboAddress from; + from.sin4.sin_family = AF_INET; + socklen_t socklen=from.getSocklen(); + int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); + if(len < 0) { + d_receiveerrors++; + return 0; + } + else { + d_receiveds++; + } + // parse packet, set 'id', fill out 'ip' + + MOADNSParser mdp(false, string(buf, len)); + if(!g_quiet) { + cout<<"Reply to question for qname='"<getZoneRepresentation()< nsnames; + map > addresses; + + + while(zpt.get(rr)) { + if(rr.qtype.getCode() == QType::NS) + nsnames[DNSName(rr.content)]++; + else if(rr.qtype.getCode() == QType::A || rr.qtype.getCode() == QType::AAAA) { + DNSRecord dr(rr); + addresses[rr.qname].insert(getAddr(dr, 53)); + } + ++g_count; + if(g_count == limit) + break; + } + g_stop=true; + stats.join(); + + cout<<"Got "< tores; + while(getline(needres,line)) { + tores.push_back(DNSName(line)); + } + cerr<<"Going to resolve "<> output; + SendReceiveRes sr(ComboAddress("192.168.1.2", 53), output); + Inflighter, SendReceiveRes> inflighter(tores, sr); + inflighter.d_maxInFlight = 1000; + inflighter.d_timeoutSeconds = 3; + inflighter.d_burst = 100; + for(;;) { + try { + inflighter.run(); + break; + } + catch(std::exception& e) { + cerr<<"Caught exception: "<>& addrs) +{ + ifstream ifs(fname); + if(!ifs) + unixDie("Reading resolved names from "+fname+": "+string(strerror(errno))); + vector parts; + string line; + addrs.clear(); + while(getline(ifs, line)) { + parts.clear(); + stringtok(parts, line,"\t"); + for(unsigned int n=2; n < parts.size(); ++n) + addrs[DNSName(parts[0])].push_back(ComboAddress(parts[n], 53)); + } + //EARTH.DOMAINS.SHELTEK.CA. 0 67.15.253.219 67.15.47.188 67.15.253.252 67.15.253.251 67.15.47.189 67.15.253.220 + cerr<<"Got "< 3) + limit = atoi(argv[3]); + + return parseZone(argv[2], limit); + } + else if(mode=="resolve-ns") { + return resolveNS(string(argv[2])+".needres"); + } + else if(mode=="scan-ns") { + ifstream ns(string(argv[2])+".nameservers"); + g_powerdns = make_unique(string(argv[2])+".powerdns"); + string line; + int count=0; + vector parts; + + struct NSCount + { + unsigned int count{0}; + vector addrs; + }; + map stats; + NSCount nscount; + // NS1.IHOST2000.COM. 9 162.251.82.122 162.251.82.123 162.251.82.250 162.251.82.251 + while(getline(ns, line)) { + ++count; + parts.clear(); + stringtok(parts, line,"\t"); + nscount.count=atoi(parts[1].c_str()); + nscount.addrs.clear(); + for(unsigned int n = 2; n < parts.size(); ++n) + nscount.addrs.push_back(ComboAddress(parts[n], 53)); + stats.insert({DNSName(parts[0]), nscount}); + } + cerr<<"Had "<> lookedup; + readRESNames(argv[2]+string(".resolved"), lookedup); + + map pure; + + unsigned int noaddrs=0; + for(const auto& s : stats) { + auto ptr = &s.second.addrs; + if(ptr->empty()) { + if(lookedup.count(s.first)) { + ptr = &lookedup[s.first]; + } + else { + //cout<<"Have no address for "< domains; + + Inflighter, SendReceive> inflighter(domains, sr); + inflighter.d_maxInFlight = 1000; + inflighter.d_timeoutSeconds = 3; + inflighter.d_burst = 100; + + for(const auto& p : pure) { + NSQuery nsq; + nsq.a=p.first; + nsq.nsnames = p.second.names; + nsq.count = p.second.count; + + nsq.qname=DNSName("version.bind"); + domains.push_back(nsq); + nsq.qname=DNSName("id.server"); + domains.push_back(nsq); + nsq.qname=DNSName("bind.version"); + domains.push_back(nsq); + } + + sort(domains.begin(), domains.end(), [](const NSQuery& a, const NSQuery& b) { return b.count < a.count; }); + for(;;) { + try { + inflighter.run(); + break; + } + catch(std::exception& e) { + cerr<<"Caught exception: "< powerdns; + ifstream ifs(string(argv[2])+".powerdns"); + string line; + vector parts; + while(getline(ifs,line)) { + // 64.96.240.53 1234 NS1.UNIREGISTRYMARKET.LINK. NS1.INTERNETTRAFFIC.COM. BUY.INTERNETTRAFFIC.COM. NS3.SECUREDOFFERS.COM. NS3.GI.NET. NS3.IT.GI.NET. NS3.EASILY.NET. + parts.clear(); + stringtok(parts, line); + for(unsigned int n=2; n < parts.size(); ++n) + powerdns.insert(DNSName(parts[n])); + } + cerr<<"Have "< seen, pdnsdomains; + int count=0; + while(zpt.get(rr)) { + if(!seen.count(rr.qname)) { + seen.insert(rr.qname); + } + if(rr.qtype.getCode() == QType::NS && powerdns.count(DNSName(rr.content)) && !pdnsdomains.count(DNSName(rr.qname))) { + pdnsdomains.insert(DNSName(rr.qname)); + } + if(!(count%100000)) { + cerr<<"\rUnique domains: "<topAllocatorsString(20)< + +class Comment +{ +public: + Comment() : modified_at(0), domain_id(0) {}; + ~Comment() {}; + + // data + DNSName qname; //!< the name of the associated RRset, for example: www.powerdns.com + time_t modified_at; + string account; //!< account last updating this comment + string content; //!< The actual comment. Example: blah blah + + int domain_id; + QType qtype; //!< qtype of the associated RRset, ie A, CNAME, MX etc +}; + +#endif /* PDNS_COMMENT_HH */ diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc new file mode 100644 index 0000000..e6439cf --- /dev/null +++ b/pdns/common_startup.cc @@ -0,0 +1,646 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "common_startup.hh" +#include "ws-auth.hh" +#include "secpoll-auth.hh" +#include +#include +#include "dynhandler.hh" +#include "dnsseckeeper.hh" +#include "threadname.hh" + +#ifdef HAVE_SYSTEMD +#include +#endif + +bool g_anyToTcp; +bool g_8bitDNS; +#ifdef HAVE_LUA_RECORDS +bool g_doLuaRecord; +int g_luaRecordExecLimit; +#endif +typedef Distributor DNSDistributor; + +ArgvMap theArg; +StatBag S; //!< Statistics are gathered across PDNS via the StatBag class S +AuthPacketCache PC; //!< This is the main PacketCache, shared across all threads +AuthQueryCache QC; +DNSProxy *DP; +DynListener *dl; +CommunicatorClass Communicator; +shared_ptr N; +int avg_latency; +unique_ptr TN; +static vector g_distributors; +vector > g_udpReceivers; + +ArgvMap &arg() +{ + return theArg; +} + +void declareArguments() +{ + ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR; + ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; + ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )=""; + ::arg().set("module-dir","Default directory for modules")=PKGLIBDIR; + ::arg().set("chroot","If set, chroot to this directory for more security")=""; + ::arg().set("logging-facility","Log under a specific facility")=""; + ::arg().set("daemon","Operate as a daemon")="no"; + + ::arg().set("local-port","The port on which we listen")="53"; + ::arg().setSwitch("dnsupdate","Enable/Disable DNS update (RFC2136) support. Default is no.")="no"; + ::arg().setSwitch("write-pid","Write a PID file")="yes"; + ::arg().set("allow-dnsupdate-from","A global setting to allow DNS updates from these IP ranges.")="127.0.0.0/8,::1"; + ::arg().setSwitch("send-signed-notify","Send TSIG secured NOTIFY if TSIG key is configured for a domain")="yes"; + ::arg().set("allow-unsigned-notify","Allow unsigned notifications for TSIG secured domains")="yes"; //FIXME: change to 'no' later + ::arg().set("allow-unsigned-supermaster", "Allow supermasters to create zones without TSIG signed NOTIFY")="yes"; + ::arg().setSwitch("forward-dnsupdate","A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master.")="yes"; + ::arg().setSwitch("log-dns-details","If PDNS should log DNS non-erroneous details")="no"; + ::arg().setSwitch("log-dns-queries","If PDNS should log all incoming DNS queries")="no"; + ::arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0"; + ::arg().setSwitch("local-address-nonexist-fail","Fail to start if one or more of the local-address's do not exist on this server")="yes"; + ::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no"; + ::arg().set("local-ipv6","Local IP address to which we bind")="::"; + ::arg().setSwitch("reuseport","Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket")="no"; + ::arg().setSwitch("local-ipv6-nonexist-fail","Fail to start if one or more of the local-ipv6 addresses do not exist on this server")="yes"; + ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0"; + ::arg().set("query-local-address6","Source IPv6 address for sending queries")="::"; + ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0"; + ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000"; + + ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2"; + ::arg().setSwitch("api", "Enable/disable the REST API (including HTTP listener)")="no"; + ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API")=""; + ::arg().setSwitch("default-api-rectify","Default API-RECTIFY value for zones")="yes"; + ::arg().setSwitch("dname-processing", "If we should support DNAME records")="no"; + + ::arg().setCmd("help","Provide a helpful message"); + ::arg().setCmd("version","Output version and compilation date"); + ::arg().setCmd("config","Provide configuration file on standard output"); + ::arg().setCmd("list-modules","Lists all modules available"); + ::arg().setCmd("no-config","Don't parse configuration file"); + + ::arg().set("version-string","PowerDNS version in packets - full, anonymous, powerdns or custom")="full"; + ::arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will! + ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4"; + ::arg().set("disable-syslog","Disable logging to syslog, useful when running inside a supervisor that logs stdout")="no"; + ::arg().set("log-timestamp","Print timestamps in log lines")="yes"; + ::arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server"; + ::arg().set("default-soa-mail","mail address to insert in the SOA record if none set in the backend")=""; + ::arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3"; + ::arg().set("signing-threads","Default number of signer threads to start")="3"; + ::arg().set("receiver-threads","Default number of receiver threads to start")="1"; + ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; + ::arg().set("resolver","Use this resolver for ALIAS and the internal stub resolver")="no"; + ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1232"; + + ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; + + ::arg().set("load-modules","Load this module - supply absolute or relative path")=""; + ::arg().set("launch","Which backends to launch and order to query them in")=""; + ::arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no"; + ::arg().set("allow-axfr-ips","Allow zonetransfers only to these subnets")="127.0.0.0/8,::1"; + ::arg().set("only-notify", "Only send AXFR NOTIFY to these IP addresses or netmasks")="0.0.0.0/0,::/0"; + ::arg().set("also-notify", "When notifying a domain, also notify these nameservers")=""; + ::arg().set("allow-notify-from","Allow AXFR NOTIFY from these IP ranges. If empty, drop all incoming notifies.")="0.0.0.0/0,::/0"; + ::arg().set("slave-cycle-interval","Schedule slave freshness checks once every .. seconds")="60"; + + ::arg().set("tcp-control-address","If set, PowerDNS can be controlled over TCP on this address")=""; + ::arg().set("tcp-control-port","If set, PowerDNS can be controlled over TCP on this address")="53000"; + ::arg().set("tcp-control-secret","If set, PowerDNS can be controlled over TCP after passing this secret")=""; + ::arg().set("tcp-control-range","If set, remote control of PowerDNS is possible over these networks only")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10"; + + ::arg().setSwitch("slave","Act as a slave")="no"; + ::arg().setSwitch("master","Act as a master")="no"; + ::arg().setSwitch("superslave", "Act as a superslave")="no"; + ::arg().setSwitch("disable-axfr-rectify","Disable the rectify step during an outgoing AXFR. Only required for regression testing.")="no"; + ::arg().setSwitch("guardian","Run within a guardian process")="no"; + ::arg().setSwitch("prevent-self-notification","Don't send notifications to what we think is ourself")="yes"; + ::arg().setSwitch("any-to-tcp","Answer ANY queries with tc=1, shunting to TCP")="yes"; + ::arg().setSwitch("edns-subnet-processing","If we should act on EDNS Subnet options")="no"; + + ::arg().setSwitch("webserver","Start a webserver for monitoring (api=yes also enables the HTTP listener)")="no"; + ::arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no"; + ::arg().set("webserver-address","IP Address of webserver/API to listen on")="127.0.0.1"; + ::arg().set("webserver-port","Port of webserver/API to listen on")="8081"; + ::arg().set("webserver-password","Password required for accessing the webserver")=""; + ::arg().set("webserver-allow-from","Webserver/API access is only allowed from these subnets")="127.0.0.1,::1"; + ::arg().set("webserver-loglevel", "Amount of logging in the webserver (none, normal, detailed)") = "normal"; + ::arg().set("webserver-max-bodysize","Webserver/API maximum request/response body size in megabytes")="2"; + + ::arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="yes"; + ::arg().setSwitch("query-logging","Hint backends that queries should be logged")="no"; + + ::arg().set("carbon-namespace", "If set overwrites the first part of the carbon string")="pdns"; + ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")=""; + ::arg().set("carbon-instance", "If set overwrites the the instance name default")="auth"; + ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server IP address")=""; + ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30"; + + ::arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20"; + ::arg().set("negquery-cache-ttl","Seconds to store negative query results in the QueryCache")="60"; + ::arg().set("query-cache-ttl","Seconds to store query results in the QueryCache")="20"; + ::arg().set("soa-minimum-ttl","Default SOA minimum ttl")="3600"; + ::arg().set("server-id", "Returned when queried for 'id.server' TXT or NSID, defaults to hostname - disabled or custom")=""; + ::arg().set("soa-refresh-default","Default SOA refresh")="10800"; + ::arg().set("soa-retry-default","Default SOA retry")="3600"; + ::arg().set("soa-expire-default","Default SOA expire")="604800"; + ::arg().set("default-soa-edit","Default SOA-EDIT value")=""; + ::arg().set("default-soa-edit-signed","Default SOA-EDIT value for signed zones")=""; + ::arg().set("dnssec-key-cache-ttl","Seconds to cache DNSSEC keys from the database")="30"; + ::arg().set("domain-metadata-cache-ttl","Seconds to cache domain metadata from the database")="60"; + + ::arg().set("trusted-notification-proxy", "IP address of incoming notification proxy")=""; + ::arg().set("slave-renotify", "If we should send out notifications for slaved updates")="no"; + ::arg().set("forward-notify", "IP addresses to forward received notifications to regardless of master or slave settings")=""; + + ::arg().set("default-ttl","Seconds a result is valid if not set otherwise")="3600"; + ::arg().set("max-tcp-connections","Maximum number of TCP connections")="20"; + ::arg().set("max-tcp-connections-per-client","Maximum number of simultaneous TCP connections per client")="0"; + ::arg().set("max-tcp-transactions-per-conn","Maximum number of subsequent queries per TCP connection")="0"; + ::arg().set("max-tcp-connection-duration","Maximum time in seconds that a TCP DNS connection is allowed to stay open.")="0"; + ::arg().set("tcp-idle-timeout","Maximum time in seconds that a TCP DNS connection is allowed to stay open while being idle")="5"; + + ::arg().setSwitch("no-shuffle","Set this to prevent random shuffling of answers - for regression testing")="off"; + + ::arg().set("setuid","If set, change user id to this uid for more security")=""; + ::arg().set("setgid","If set, change group id to this gid for more security")=""; + + ::arg().set("max-cache-entries", "Maximum number of entries in the query cache")="1000000"; + ::arg().set("max-packet-cache-entries", "Maximum number of entries in the packet cache")="1000000"; + ::arg().set("max-signature-cache-entries", "Maximum number of signatures cache entries")=""; + ::arg().set("max-ent-entries", "Maximum number of empty non-terminals in a zone")="100000"; + ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom"; + + ::arg().set("lua-prequery-script", "Lua script with prequery handler (DO NOT USE)")=""; + ::arg().set("lua-dnsupdate-policy-script", "Lua script with DNS update policy handler")=""; + + ::arg().setSwitch("traceback-handler","Enable the traceback handler (Linux only)")="yes"; + ::arg().setSwitch("direct-dnskey","Fetch DNSKEY, CDS and CDNSKEY RRs from backend during DNSKEY or CDS/CDNSKEY synthesis")="no"; + ::arg().set("default-ksk-algorithm","Default KSK algorithm")="ecdsa256"; + ::arg().set("default-ksk-size","Default KSK size (0 means default)")="0"; + ::arg().set("default-zsk-algorithm","Default ZSK algorithm")=""; + ::arg().set("default-zsk-size","Default ZSK size (0 means default)")="0"; + ::arg().set("max-nsec3-iterations","Limit the number of NSEC3 hash iterations")="500"; // RFC5155 10.3 + + ::arg().set("include-dir","Include *.conf files from this directory"); + ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com."; + + ::arg().setSwitch("expand-alias", "Expand ALIAS records")="no"; + ::arg().setSwitch("outgoing-axfr-expand-alias", "Expand ALIAS records during outgoing AXFR")="no"; + ::arg().setSwitch("8bit-dns", "Allow 8bit dns queries")="no"; +#ifdef HAVE_LUA_RECORDS + ::arg().setSwitch("enable-lua-records", "Process LUA records for all zones (metadata overrides this)")="no"; + ::arg().set("lua-records-exec-limit", "LUA records scripts execution limit (instructions count). Values <= 0 mean no limit")="1000"; +#endif + ::arg().setSwitch("axfr-lower-serial", "Also AXFR a zone from a master with a lower serial")="no"; + + ::arg().set("lua-axfr-script", "Script to be used to edit incoming AXFRs")=""; + ::arg().set("xfr-max-received-mbytes", "Maximum number of megabytes received from an incoming XFR")="100"; + ::arg().set("axfr-fetch-timeout", "Maximum time in seconds for inbound AXFR to start or be idle after starting")="10"; + + ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0"; + + ::arg().set("rng", "Specify the random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto"; +} + +static time_t s_start=time(0); +static uint64_t uptimeOfProcess(const std::string& str) +{ + return time(0) - s_start; +} + +static uint64_t getSysUserTimeMsec(const std::string& str) +{ + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + + if(str=="sys-msec") { + return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000); + } + else + return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000); + +} + +static uint64_t getTCPConnectionCount(const std::string& str) +{ + return TN->numTCPConnections(); +} + +static uint64_t getQCount(const std::string& str) +try +{ + int totcount=0; + for(DNSDistributor* d : g_distributors) { + if(!d) + continue; + totcount += d->getQueueSize(); // this does locking and other things, so don't get smart + } + return totcount; +} +catch(std::exception& e) +{ + g_log<send(a); + + int diff=a->d_dt.udiff(); + avg_latency=(int)(0.999*avg_latency+0.001*diff); + delete a; +} + +//! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for further processing +void *qthread(void *number) +try +{ + setThreadName("pdns/receiver"); + + DNSPacket *P; + DNSDistributor *distributor = DNSDistributor::Create(::arg().asNum("distributor-threads", 1)); // the big dispatcher! + int num = (int)(unsigned long)number; + g_distributors[num] = distributor; + DNSPacket question(true); + DNSPacket cached(false); + + AtomicCounter &numreceived=*S.getPointer("udp-queries"); + AtomicCounter &numreceiveddo=*S.getPointer("udp-do-queries"); + + AtomicCounter &numreceived4=*S.getPointer("udp4-queries"); + + AtomicCounter &numreceived6=*S.getPointer("udp6-queries"); + AtomicCounter &overloadDrops=*S.getPointer("overload-drops"); + + int diff; + bool logDNSQueries = ::arg().mustDo("log-dns-queries"); + shared_ptr NS; + std::string buffer; + buffer.resize(DNSPacket::s_udpTruncationThreshold); + + // If we have SO_REUSEPORT then create a new port for all receiver threads + // other than the first one. + if( number != NULL && N->canReusePort() ) { + NS = g_udpReceivers[num]; + if (NS == nullptr) { + NS = N; + } + } else { + NS = N; + } + + for(;;) { + if(!(P=NS->receive(&question, buffer))) { // receive a packet inline + continue; // packet was broken, try again + } + + numreceived++; + + if(P->d_remote.getSocklen()==sizeof(sockaddr_in)) + numreceived4++; + else + numreceived6++; + + if(P->d_dnssecOk) + numreceiveddo++; + + if(P->d.qr) + continue; + + S.ringAccount("queries", P->qdomain, P->qtype); + S.ringAccount("remotes",P->d_remote); + if(logDNSQueries) { + string remote; + if(P->hasEDNSSubnet()) + remote = P->getRemote().toString() + "<-" + P->getRealRemote().toString(); + else + remote = P->getRemote().toString(); + g_log << Logger::Notice<<"Remote "<< remote <<" wants '" << P->qdomain<<"|"<qtype.getName() << + "', do = " <d_dnssecOk <<", bufsize = "<< P->getMaxReplyLen(); + if(P->d_ednsRawPacketSizeLimit > 0 && P->getMaxReplyLen() != (unsigned int)P->d_ednsRawPacketSizeLimit) + g_log<<" ("<d_ednsRawPacketSizeLimit<<")"; + g_log<<": "; + } + + if(PC.enabled() && (P->d.opcode != Opcode::Notify && P->d.opcode != Opcode::Update) && P->couldBeCached()) { + bool haveSomething=PC.get(P, &cached); // does the PacketCache recognize this question? + if (haveSomething) { + if(logDNSQueries) + g_log<<"packetcache HIT"<d_remote); // inlined + cached.setSocket(P->getSocket()); // inlined + cached.d_anyLocal = P->d_anyLocal; + cached.setMaxReplyLen(P->getMaxReplyLen()); + cached.d.rd=P->d.rd; // copy in recursion desired bit + cached.d.id=P->d.id; + cached.commitD(); // commit d to the packet inlined + NS->send(&cached); // answer it then inlined + diff=P->d_dt.udiff(); + avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA' + continue; + } + } + + if(distributor->isOverloaded()) { + if(logDNSQueries) + g_log<<"Dropped query, backends are overloaded"<question(P, &sendout); // otherwise, give to the distributor + } + catch(DistributorFatal& df) { // when this happens, we have leaked loads of memory. Bailing out time. + _exit(1); + } + } + return 0; +} +catch(PDNSException& pe) +{ + g_log<go(); + } + + try { + doSecPoll(true); + } + catch(...) {} + + { + // Some sanity checking on default key settings + bool hadKeyError = false; + int kskAlgo{0}, zskAlgo{0}; + for (const string& algotype : {"ksk", "zsk"}) { + int algo, size; + if (::arg()["default-"+algotype+"-algorithm"].empty()) + continue; + algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-"+algotype+"-algorithm"]); + size = ::arg().asNum("default-"+algotype+"-size"); + if (algo == -1) { + g_log<go(); + + pthread_t qtid; + + if(::arg().mustDo("webserver") || ::arg().mustDo("api")) + webserver.go(); + + if(::arg().mustDo("slave") || ::arg().mustDo("master") || !::arg()["forward-notify"].empty()) + Communicator.go(); + + TN->go(); // tcp nameserver launch + + // fork(); (this worked :-)) + unsigned int max_rthreads= ::arg().asNum("receiver-threads", 1); + g_distributors.resize(max_rthreads); + for(unsigned int n=0; n < max_rthreads; ++n) + pthread_create(&qtid,0,qthread, reinterpret_cast(n)); // receives packets + + pthread_create(&qtid,0,carbonDumpThread, 0); // runs even w/o carbon, might change @ runtime + +#ifdef HAVE_SYSTEMD + /* If we are here, notify systemd that we are ay-ok! This might have some + * timing issues with the backend-threads. e.g. if the initial MySQL connection + * is slow and times out (leading to process termination through the backend) + * We probably have told systemd already that we have started correctly. + */ + sd_notify(0, "READY=1"); +#endif + + for(;;) { + sleep(1800); + try { + doSecPoll(false); + } + catch(...){} + } + + g_log< N; +extern vector > g_udpReceivers; +extern int avg_latency; +extern std::unique_ptr TN; +extern ArgvMap & arg( void ); +extern void declareArguments(); +extern void declareStats(); +extern void mainthread(); +extern int isGuarded( char ** ); +void* carbonDumpThread(void*); +extern bool g_anyToTcp; +extern bool g_8bitDNS; +#ifdef HAVE_LUA_RECORDS +extern bool g_doLuaRecord; +extern bool g_LuaRecordSharedState; +#endif // HAVE_LUA_RECORDS + +#endif // COMMON_STARTUP_HH diff --git a/pdns/communicator.cc b/pdns/communicator.cc new file mode 100644 index 0000000..fedf38b --- /dev/null +++ b/pdns/communicator.cc @@ -0,0 +1,168 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "packetcache.hh" +#include "utility.hh" +#include +#include "communicator.hh" +#include +#include +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "packethandler.hh" +#include "resolver.hh" +#include "logger.hh" +#include "dns.hh" +#include "arguments.hh" +#include "packetcache.hh" +#include "threadname.hh" + +// there can be MANY OF THESE +void CommunicatorClass::retrievalLoopThread(void) +{ + setThreadName("pdns/comm-retre"); + for(;;) { + d_suck_sem.wait(); + SuckRequest sr; + { + Lock l(&d_lock); + if(d_suckdomains.empty()) + continue; + + sr=d_suckdomains.front(); + d_suckdomains.pop_front(); + } + suck(sr.domain, sr.master); + } +} + +void CommunicatorClass::loadArgsIntoSet(const char *listname, set &listset) +{ + vector parts; + stringtok(parts, ::arg()[listname], ", \t"); + for (vector::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) { + try { + ComboAddress caIp(*iter, 53); + listset.insert(caIp.toStringWithPort()); + } + catch(PDNSException &e) { + g_log< +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace boost::multi_index; + +#include +#include +#include + +#include "lock.hh" +#include "packethandler.hh" + +#include "namespaces.hh" +#include "dns_random.hh" + +struct SuckRequest +{ + DNSName domain; + ComboAddress master; + bool operator<(const SuckRequest& b) const + { + return tie(domain, master) < tie(b.domain, b.master); + } +}; + +struct IDTag{}; + +typedef multi_index_container< + SuckRequest, + indexed_by< + sequenced<>, + ordered_unique, identity > + > +> UniQueue; +typedef UniQueue::index::type domains_by_name_t; + +class NotificationQueue +{ +public: + void add(const DNSName &domain, const string &ip) + { + const ComboAddress caIp(ip); + + NotificationRequest nr; + nr.domain = domain; + nr.ip = caIp.toStringWithPort(); + nr.attempts = 0; + nr.id = dns_random(0xffff); + nr.next = time(0); + + d_nqueue.push_back(nr); + } + + bool removeIf(const string &remote, uint16_t id, const DNSName &domain) + { + ServiceTuple stRemote, stQueued; + parseService(remote, stRemote); + + for(d_nqueue_t::iterator i=d_nqueue.begin(); i!=d_nqueue.end(); ++i) { + parseService(i->ip, stQueued); + if(i->id==id && stQueued.host == stRemote.host && i->domain==domain) { + d_nqueue.erase(i); + return true; + } + } + return false; + } + + bool getOne(DNSName &domain, string &ip, uint16_t *id, bool &purged) + { + for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) + if(i->next <= time(0)) { + i->attempts++; + purged=false; + i->next=time(0)+1+(1<attempts); + domain=i->domain; + ip=i->ip; + *id=i->id; + purged=false; + if(i->attempts>4) { + purged=true; + d_nqueue.erase(i); + } + return true; + } + return false; + } + + time_t earliest() + { + time_t early=std::numeric_limits::max() - 1; + for(d_nqueue_t::const_iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) + early=min(early,i->next); + return early-time(0); + } + + void dump(); + +private: + struct NotificationRequest + { + DNSName domain; + string ip; + time_t next; + int attempts; + uint16_t id; + }; + + typedef std::list d_nqueue_t; + d_nqueue_t d_nqueue; + +}; + +struct ZoneStatus; + +/** this class contains a thread that communicates with other nameserver and does housekeeping. + Initially, it is notified only of zones that need to be pulled in because they have been updated. */ + +class CommunicatorClass +{ +public: + CommunicatorClass() + { + pthread_mutex_init(&d_lock,0); + pthread_mutex_init(&d_holelock,0); + + d_tickinterval=60; + d_masterschanged=d_slaveschanged=true; + d_nsock4 = -1; + d_nsock6 = -1; + d_preventSelfNotification = false; + } + time_t doNotifications(PacketHandler *P); + void go(); + + + void drillHole(const DNSName &domain, const string &ip); + bool justNotified(const DNSName &domain, const string &ip); + void addSuckRequest(const DNSName &domain, const ComboAddress& master); + void addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote); + void addTrySuperMasterRequest(DNSPacket *p); + void notify(const DNSName &domain, const string &ip); + void mainloop(); + void retrievalLoopThread(); + void sendNotification(int sock, const DNSName &domain, const ComboAddress& remote, uint16_t id, UeberBackend* B); + + static void *launchhelper(void *p) + { + static_cast(p)->mainloop(); + return 0; + } + static void *retrieveLaunchhelper(void *p) + { + static_cast(p)->retrievalLoopThread(); + return 0; + } + bool notifyDomain(const DNSName &domain, UeberBackend* B); +private: + void loadArgsIntoSet(const char *listname, set &listset); + void makeNotifySockets(); + void queueNotifyDomain(const DomainInfo& di, UeberBackend* B); + int d_nsock4, d_nsock6; + map,time_t>d_holes; + pthread_mutex_t d_holelock; + void suck(const DNSName &domain, const ComboAddress& remote); + void ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, boost::scoped_ptr& pdl, + ZoneStatus& zs, vector* axfr); + + void slaveRefresh(PacketHandler *P); + void masterUpdateCheck(PacketHandler *P); + pthread_mutex_t d_lock; + + UniQueue d_suckdomains; + set d_inprogress; + + Semaphore d_suck_sem; + Semaphore d_any_sem; + time_t d_tickinterval; + set d_tocheck; + struct cmp { + bool operator()(const DNSPacket& a, const DNSPacket& b) const { + return a.qdomain < b.qdomain; + }; + }; + + std::set d_potentialsupermasters; + + set d_alsoNotify; + NotificationQueue d_nq; + NetmaskGroup d_onlyNotify; + bool d_masterschanged, d_slaveschanged; + bool d_preventSelfNotification; + + // Used to keep some state on domains that failed their freshness checks. + // uint64_t == counter of the number of failures (increased by 1 every consecutive slave-cycle-interval that the domain fails) + // time_t == wait at least until this time before attempting a new check + map > d_failedSlaveRefresh; + + struct RemoveSentinel + { + explicit RemoveSentinel(const DNSName& dn, CommunicatorClass* cc) : d_dn(dn), d_cc(cc) + {} + + ~RemoveSentinel() + { + try { + Lock l(&d_cc->d_lock); + d_cc->d_inprogress.erase(d_dn); + } + catch(...) { + } + } + DNSName d_dn; + CommunicatorClass* d_cc; +}; + +}; + +// class that one day might be more than a function to help you get IP addresses for a nameserver +class FindNS +{ +public: + vector lookup(const DNSName &name, UeberBackend *b) + { + vector addresses; + + this->resolve_name(&addresses, name); + + if(b) { + b->lookup(QType(QType::ANY),name); + DNSZoneRecord rr; + while(b->get(rr)) + if(rr.dr.d_type == QType::A || rr.dr.d_type==QType::AAAA) + addresses.push_back(rr.dr.d_content->getZoneRepresentation()); // SOL if you have a CNAME for an NS + } + return addresses; + } + +private: + void resolve_name(vector* addresses, const DNSName& name) + { + struct addrinfo* res; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; // otherwise we get everything in triplicate (!) + for(int n = 0; n < 2; ++n) { + hints.ai_family = n ? AF_INET : AF_INET6; + ComboAddress remote; + remote.sin4.sin_family = AF_INET6; + if(!getaddrinfo(name.toString().c_str(), 0, &hints, &res)) { + struct addrinfo* address = res; + do { + if (address->ai_addrlen <= sizeof(remote)) { + remote.setSockaddr(address->ai_addr, address->ai_addrlen); + addresses->push_back(remote.toString()); + } + } while((address = address->ai_next)); + freeaddrinfo(res); + } + } + } +}; + + +#endif diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc new file mode 100644 index 0000000..4af7410 --- /dev/null +++ b/pdns/dbdnsseckeeper.cc @@ -0,0 +1,843 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnsseckeeper.hh" +#include "dnssecinfra.hh" +#include "ueberbackend.hh" +#include "statbag.hh" +#include + +#include +#include +#include +#include +#include +#include // for 'operator+=()' +#include +#include "base32.hh" +#include "base64.hh" +#include "cachecleaner.hh" +#include "arguments.hh" + + +using namespace boost::assign; +#include "namespaces.hh" + + +DNSSECKeeper::keycache_t DNSSECKeeper::s_keycache; +DNSSECKeeper::metacache_t DNSSECKeeper::s_metacache; +pthread_rwlock_t DNSSECKeeper::s_metacachelock = PTHREAD_RWLOCK_INITIALIZER; +pthread_rwlock_t DNSSECKeeper::s_keycachelock = PTHREAD_RWLOCK_INITIALIZER; +AtomicCounter DNSSECKeeper::s_ops; +time_t DNSSECKeeper::s_last_prune; + +bool DNSSECKeeper::doesDNSSEC() +{ + return d_keymetadb->doesDNSSEC(); +} + +bool DNSSECKeeper::isSecuredZone(const DNSName& zone) +{ + if(isPresigned(zone)) + return true; + + keyset_t keys = getKeys(zone); // does the cache + + for(keyset_t::value_type& val : keys) { + if(val.second.active) { + return true; + } + } + return false; +} + +bool DNSSECKeeper::isPresigned(const DNSName& name) +{ + string meta; + getFromMeta(name, "PRESIGNED", meta); + return meta=="1"; +} + +bool DNSSECKeeper::addKey(const DNSName& name, bool setSEPBit, int algorithm, int64_t& id, int bits, bool active) +{ + if(!bits) { + if(algorithm <= 10) + throw runtime_error("Creating an algorithm " +std::to_string(algorithm)+" ("+algorithm2name(algorithm)+") key requires the size (in bits) to be passed."); + else { + if(algorithm == DNSSECKeeper::ECCGOST || algorithm == DNSSECKeeper::ECDSA256 || algorithm == DNSSECKeeper::ED25519) + bits = 256; + else if(algorithm == DNSSECKeeper::ECDSA384) + bits = 384; + else if(algorithm == DNSSECKeeper::ED448) + bits = 456; + else { + throw runtime_error("Can not guess key size for algorithm "+std::to_string(algorithm)); + } + } + } + DNSSECPrivateKey dspk; + shared_ptr dpk(DNSCryptoKeyEngine::make(algorithm)); + try{ + dpk->create(bits); + } catch (const std::runtime_error& error){ + throw runtime_error("The algorithm does not support the given bit size."); + } + dspk.setKey(dpk); + dspk.d_algorithm = algorithm; + dspk.d_flags = setSEPBit ? 257 : 256; + return addKey(name, dspk, id, active); +} + +void DNSSECKeeper::clearAllCaches() { + { + WriteLock l(&s_keycachelock); + s_keycache.clear(); + } + WriteLock l(&s_metacachelock); + s_metacache.clear(); +} + +void DNSSECKeeper::clearCaches(const DNSName& name) +{ + { + WriteLock l(&s_keycachelock); + s_keycache.erase(name); + } + WriteLock l(&s_metacachelock); + pair range = s_metacache.equal_range(tie(name)); + while(range.first != range.second) + s_metacache.erase(range.first++); +} + + +bool DNSSECKeeper::addKey(const DNSName& name, const DNSSECPrivateKey& dpk, int64_t& id, bool active) +{ + clearCaches(name); + DNSBackend::KeyData kd; + kd.flags = dpk.d_flags; // the dpk doesn't get stored, only they key part + kd.active = active; + kd.content = dpk.getKey()->convertToISC(); + // now store it + return d_keymetadb->addDomainKey(name, kd, id); +} + + +static bool keyCompareByKindAndID(const DNSSECKeeper::keyset_t::value_type& a, const DNSSECKeeper::keyset_t::value_type& b) +{ + return make_pair(!a.second.keyType, a.second.id) < + make_pair(!b.second.keyType, b.second.id); +} + +DNSSECPrivateKey DNSSECKeeper::getKeyById(const DNSName& zname, unsigned int id) +{ + vector keys; + d_keymetadb->getDomainKeys(zname, keys); + for(const DNSBackend::KeyData& kd : keys) { + if(kd.id != id) + continue; + + DNSSECPrivateKey dpk; + DNSKEYRecordContent dkrc; + dpk.setKey(shared_ptr(DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content))); + dpk.d_flags = kd.flags; + dpk.d_algorithm = dkrc.d_algorithm; + + if(dpk.d_algorithm == DNSSECKeeper::RSASHA1 && getNSEC3PARAM(zname)) { + dpk.d_algorithm = DNSSECKeeper::RSASHA1NSEC3SHA1; + } + + return dpk; + } + throw runtime_error("Can't find a key with id "+std::to_string(id)+" for zone '"+zname.toLogString()+"'"); +} + + +bool DNSSECKeeper::removeKey(const DNSName& zname, unsigned int id) +{ + clearCaches(zname); + return d_keymetadb->removeDomainKey(zname, id); +} + +bool DNSSECKeeper::deactivateKey(const DNSName& zname, unsigned int id) +{ + clearCaches(zname); + return d_keymetadb->deactivateDomainKey(zname, id); +} + +bool DNSSECKeeper::activateKey(const DNSName& zname, unsigned int id) +{ + clearCaches(zname); + return d_keymetadb->activateDomainKey(zname, id); +} + + +void DNSSECKeeper::getFromMeta(const DNSName& zname, const std::string& key, std::string& value) +{ + static int ttl = ::arg().asNum("domain-metadata-cache-ttl"); + value.clear(); + unsigned int now = time(0); + + if(!((++s_ops) % 100000)) { + cleanup(); + } + + if (ttl > 0) { + ReadLock l(&s_metacachelock); + + metacache_t::const_iterator iter = s_metacache.find(tie(zname, key)); + if(iter != s_metacache.end() && iter->d_ttd > now) { + value = iter->d_value; + return; + } + } + vector meta; + d_keymetadb->getDomainMetadata(zname, key, meta); + if(!meta.empty()) + value=*meta.begin(); + + if (ttl > 0) { + METACacheEntry nce; + nce.d_domain=zname; + nce.d_ttd = now + ttl; + nce.d_key= key; + nce.d_value = value; + { + WriteLock l(&s_metacachelock); + lruReplacingInsert(s_metacache, nce); + } + } +} + +void DNSSECKeeper::getSoaEdit(const DNSName& zname, std::string& value) +{ + static const string soaEdit(::arg()["default-soa-edit"]); + static const string soaEditSigned(::arg()["default-soa-edit-signed"]); + + if (isPresigned(zname)) { + // SOA editing on a presigned zone never makes sense + return; + } + + getFromMeta(zname, "SOA-EDIT", value); + + if ((!soaEdit.empty() || !soaEditSigned.empty()) && value.empty()) { + if (!soaEditSigned.empty() && isSecuredZone(zname)) + value=soaEditSigned; + if (value.empty()) + value=soaEdit; + } + + return; +} + +uint64_t DNSSECKeeper::dbdnssecCacheSizes(const std::string& str) +{ + if(str=="meta-cache-size") { + ReadLock l(&s_metacachelock); + return s_metacache.size(); + } + else if(str=="key-cache-size") { + ReadLock l(&s_keycachelock); + return s_keycache.size(); + } + return (uint64_t)-1; +} + +bool DNSSECKeeper::getNSEC3PARAM(const DNSName& zname, NSEC3PARAMRecordContent* ns3p, bool* narrow) +{ + string value; + getFromMeta(zname, "NSEC3PARAM", value); + if(value.empty()) { // "no NSEC3" + return false; + } + + static int maxNSEC3Iterations=::arg().asNum("max-nsec3-iterations"); + if(ns3p) { + *ns3p = NSEC3PARAMRecordContent(value); + if (ns3p->d_iterations > maxNSEC3Iterations) { + ns3p->d_iterations = maxNSEC3Iterations; + g_log<d_algorithm != 1) { + g_log<d_algorithm)<<"', setting to 1 for zone '"<d_algorithm = 1; + } + } + if(narrow) { + getFromMeta(zname, "NSEC3NARROW", value); + *narrow = (value=="1"); + } + return true; +} + +/* + * Check is the provided NSEC3PARAM record is something we can work with + * + * \param ns3p NSEC3PARAMRecordContent to check + * \param msg string to fill with an error message + * \return true on valid, false otherwise + */ +bool DNSSECKeeper::checkNSEC3PARAM(const NSEC3PARAMRecordContent& ns3p, string& msg) +{ + static int maxNSEC3Iterations=::arg().asNum("max-nsec3-iterations"); + bool ret = true; + if (ns3p.d_iterations > maxNSEC3Iterations) { + msg += "Number of NSEC3 iterations is above 'max-nsec3-iterations'."; + ret = false; + } + + if (ns3p.d_algorithm != 1) { + if (!ret) + msg += ' '; + msg += "Invalid hash algorithm for NSEC3: '"+std::to_string(ns3p.d_algorithm)+"', the only valid value is '1'."; + ret = false; + } + + return ret; +} + +bool DNSSECKeeper::setNSEC3PARAM(const DNSName& zname, const NSEC3PARAMRecordContent& ns3p, const bool& narrow) +{ + string error_msg = ""; + if (!checkNSEC3PARAM(ns3p, error_msg)) + throw runtime_error("NSEC3PARAMs provided for zone '"+zname.toLogString()+"' are invalid: " + error_msg); + + clearCaches(zname); + string descr = ns3p.getZoneRepresentation(); + vector meta; + meta.push_back(descr); + if (d_keymetadb->setDomainMetadata(zname, "NSEC3PARAM", meta)) { + meta.clear(); + + if(narrow) + meta.push_back("1"); + + return d_keymetadb->setDomainMetadata(zname, "NSEC3NARROW", meta); + } + return false; +} + +bool DNSSECKeeper::unsetNSEC3PARAM(const DNSName& zname) +{ + clearCaches(zname); + return (d_keymetadb->setDomainMetadata(zname, "NSEC3PARAM", vector()) && d_keymetadb->setDomainMetadata(zname, "NSEC3NARROW", vector())); +} + + +bool DNSSECKeeper::setPresigned(const DNSName& zname) +{ + clearCaches(zname); + vector meta; + meta.push_back("1"); + return d_keymetadb->setDomainMetadata(zname, "PRESIGNED", meta); +} + +bool DNSSECKeeper::unsetPresigned(const DNSName& zname) +{ + clearCaches(zname); + return d_keymetadb->setDomainMetadata(zname, "PRESIGNED", vector()); +} + +/** + * Add domainmetadata to allow publishing CDS records for zone zname + * + * @param zname DNSName of the zone + * @param digestAlgos string with comma-separated numbers that describe the + * used digest algorithms. This is copied to the database + * verbatim + * @return true if the data was inserted, false otherwise + */ +bool DNSSECKeeper::setPublishCDS(const DNSName& zname, const string& digestAlgos) +{ + clearCaches(zname); + vector meta; + meta.push_back(digestAlgos); + return d_keymetadb->setDomainMetadata(zname, "PUBLISH-CDS", meta); +} + +/** + * Remove domainmetadata to stop publishing CDS records for zone zname + * + * @param zname DNSName of the zone + * @return true if the operation was successful, false otherwise + */ +bool DNSSECKeeper::unsetPublishCDS(const DNSName& zname) +{ + clearCaches(zname); + return d_keymetadb->setDomainMetadata(zname, "PUBLISH-CDS", vector()); +} + +/** + * Add domainmetadata to allow publishing CDNSKEY records.for zone zname + * + * @param zname DNSName of the zone + * @return true if the data was inserted, false otherwise + */ +bool DNSSECKeeper::setPublishCDNSKEY(const DNSName& zname) +{ + clearCaches(zname); + vector meta; + meta.push_back("1"); + return d_keymetadb->setDomainMetadata(zname, "PUBLISH-CDNSKEY", meta); +} + +/** + * Remove domainmetadata to stop publishing CDNSKEY records for zone zname + * + * @param zname DNSName of the zone + * @return true if the operation was successful, false otherwise + */ +bool DNSSECKeeper::unsetPublishCDNSKEY(const DNSName& zname) +{ + clearCaches(zname); + return d_keymetadb->setDomainMetadata(zname, "PUBLISH-CDNSKEY", vector()); +} + +/** + * Returns all keys that are used to sign the DNSKEY RRSet in a zone + * + * @param zname DNSName of the zone + * @return a keyset_t with all keys that are used to sign the DNSKEY + * RRSet (these are the entrypoint(s) to the zone) + */ +DNSSECKeeper::keyset_t DNSSECKeeper::getEntryPoints(const DNSName& zname) +{ + DNSSECKeeper::keyset_t ret; + DNSSECKeeper::keyset_t keys = getKeys(zname); + + for(auto const &keymeta : keys) + if(keymeta.second.keyType == KSK || keymeta.second.keyType == CSK) + ret.push_back(keymeta); + return ret; +} + +DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, bool useCache) +{ + static int ttl = ::arg().asNum("dnssec-key-cache-ttl"); + unsigned int now = time(0); + + if(!((++s_ops) % 100000)) { + cleanup(); + } + + if (useCache && ttl > 0) { + ReadLock l(&s_keycachelock); + keycache_t::const_iterator iter = s_keycache.find(zone); + + if(iter != s_keycache.end() && iter->d_ttd > now) { + keyset_t ret; + for(const keyset_t::value_type& value : iter->d_keys) + ret.push_back(value); + return ret; + } + } + + keyset_t retkeyset; + vector dbkeyset; + + d_keymetadb->getDomainKeys(zone, dbkeyset); + + // Determine the algorithms that have a KSK/ZSK split + set algoSEP, algoNoSEP; + vector algoHasSeparateKSK; + for(const DNSBackend::KeyData &keydata : dbkeyset) { + DNSSECPrivateKey dpk; + DNSKEYRecordContent dkrc; + + dpk.setKey(shared_ptr(DNSCryptoKeyEngine::makeFromISCString(dkrc, keydata.content))); + + if(keydata.active) { + if(keydata.flags == 257) + algoSEP.insert(dkrc.d_algorithm); + else + algoNoSEP.insert(dkrc.d_algorithm); + } + } + set_intersection(algoSEP.begin(), algoSEP.end(), algoNoSEP.begin(), algoNoSEP.end(), std::back_inserter(algoHasSeparateKSK)); + + for(DNSBackend::KeyData& kd : dbkeyset) + { + DNSSECPrivateKey dpk; + DNSKEYRecordContent dkrc; + + dpk.setKey(shared_ptr(DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content))); + + dpk.d_flags = kd.flags; + dpk.d_algorithm = dkrc.d_algorithm; + if(dpk.d_algorithm == DNSSECKeeper::RSASHA1 && getNSEC3PARAM(zone)) { + g_log< 0) { + KeyCacheEntry kce; + kce.d_domain=zone; + kce.d_keys = retkeyset; + kce.d_ttd = now + ttl; + { + WriteLock l(&s_keycachelock); + lruReplacingInsert(s_keycache, kce); + } + } + + return retkeyset; +} + +bool DNSSECKeeper::checkKeys(const DNSName& zone, vector* errorMessages) +{ + vector dbkeyset; + d_keymetadb->getDomainKeys(zone, dbkeyset); + bool retval = true; + + for(const DNSBackend::KeyData &keydata : dbkeyset) { + DNSKEYRecordContent dkrc; + shared_ptr dke(DNSCryptoKeyEngine::makeFromISCString(dkrc, keydata.content)); + retval = dke->checkKey(errorMessages) && retval; + } + + return retval; +} + +bool DNSSECKeeper::getPreRRSIGs(UeberBackend& db, const DNSName& signer, const DNSName& qname, + const DNSName& wildcardname, const QType& qtype, + DNSResourceRecord::Place signPlace, vector& rrsigs, uint32_t signTTL) +{ + // cerr<<"Doing DB lookup for precomputed RRSIGs for '"<<(wildcardname.empty() ? qname : wildcardname)<<"'"<(rr.dr); + if(rrsig->d_type == qtype.getCode() && rrsig->d_signer==signer) { + if (wildcardname.countLabels()) + rr.dr.d_name = qname; + rr.dr.d_place = signPlace; + rr.dr.d_ttl = signTTL; + rrsigs.push_back(rr); + } + } + return true; +} + +bool DNSSECKeeper::TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname) +{ + vector allowed; + + d_keymetadb->getDomainMetadata(zone, "TSIG-ALLOW-AXFR", allowed); + + for(const string& dbkey : allowed) { + if(DNSName(dbkey)==keyname) + return true; + } + return false; +} + +bool DNSSECKeeper::getTSIGForAccess(const DNSName& zone, const ComboAddress& master, DNSName* keyname) +{ + vector keynames; + d_keymetadb->getDomainMetadata(zone, "AXFR-MASTER-TSIG", keynames); + keyname->trimToLabels(0); + + // XXX FIXME this should check for a specific master! + for(const string& dbkey : keynames) { + *keyname=DNSName(dbkey); + return true; + } + return false; +} + +bool DNSSECKeeper::unSecureZone(const DNSName& zone, string& error, string& info) { + // Not calling isSecuredZone(), as it will return false for zones with zero + // active keys. + DNSSECKeeper::keyset_t keyset=getKeys(zone); + + if(keyset.empty()) { + error = "No keys for zone '" + zone.toLogString() + "'."; + return false; + } + + for(auto& key : keyset) { + deactivateKey(zone, key.second.id); + removeKey(zone, key.second.id); + } + + unsetNSEC3PARAM(zone); + unsetPresigned(zone); + return true; +} + +/* Rectifies the zone + * + * \param zone The zone to rectify + * \param error& A string where error messages are added + * \param info& A string where informational messages are added + * \param doTransaction Whether or not to wrap the rectify in a transaction + */ +bool DNSSECKeeper::rectifyZone(const DNSName& zone, string& error, string& info, bool doTransaction) { + if (isPresigned(zone)) { + error = "Rectify presigned zone '"+zone.toLogString()+"' is not allowed/necessary."; + return false; + } + + UeberBackend* B = d_keymetadb; + std::unique_ptr b; + + if (d_ourDB) { + if (!doTransaction) { + error = "Can not rectify a zone with a new Ueberbackend inside a transaction."; + return false; + } + // We don't have a *full* Ueberbackend, just a key-only one. + // Let's create one and use it + b = std::unique_ptr(new UeberBackend()); + B = b.get(); + } + + SOAData sd; + + if(!B->getSOAUncached(zone, sd)) { + error = "No SOA known for '" + zone.toLogString() + "', is such a zone in the database?"; + return false; + } + + sd.db->list(zone, sd.domain_id); + + ostringstream infostream; + DNSResourceRecord rr; + set qnames, nsset, dsnames, insnonterm, delnonterm; + map nonterm; + vector rrs; + + while(sd.db->get(rr)) { + rr.qname.makeUsLowerCase(); + if (rr.qtype.getCode()) + { + rrs.push_back(rr); + qnames.insert(rr.qname); + if(rr.qtype.getCode() == QType::NS && rr.qname != zone) + nsset.insert(rr.qname); + if(rr.qtype.getCode() == QType::DS) + dsnames.insert(rr.qname); + } + else + delnonterm.insert(rr.qname); + } + + NSEC3PARAMRecordContent ns3pr; + bool securedZone = isSecuredZone(zone); + bool haveNSEC3 = false, isOptOut = false, narrow = false; + + if(securedZone) { + haveNSEC3 = getNSEC3PARAM(zone, &ns3pr, &narrow); + isOptOut = (haveNSEC3 && ns3pr.d_flags); + + if(!haveNSEC3) { + infostream<<"Adding NSEC ordering information "; + } + else if(!narrow) { + if(!isOptOut) { + infostream<<"Adding NSEC3 hashed ordering information for '"< nsec3set; + if (haveNSEC3 && (!narrow || !isOptOut)) { + for (auto &loopRR: rrs) { + bool skip=false; + DNSName shorter = loopRR.qname; + if (shorter != zone && shorter.chopOff() && shorter != zone) { + do { + if(nsset.count(shorter)) { + skip=true; + break; + } + } while(shorter.chopOff() && shorter != zone); + } + shorter = loopRR.qname; + if(!skip && (loopRR.qtype.getCode() != QType::NS || !isOptOut)) { + + do { + if(!nsec3set.count(shorter)) { + nsec3set.insert(shorter); + } + } while(shorter != zone && shorter.chopOff()); + } + } + } + + if (doTransaction) + sd.db->startTransaction(zone, -1); + + bool realrr=true; + bool doent=true; + uint32_t maxent = ::arg().asNum("max-ent-entries"); + + dononterm:; + for (const auto& qname: qnames) + { + bool auth=true; + DNSName ordername; + auto shorter(qname); + + if(realrr) { + do { + if(nsset.count(shorter)) { + auth=false; + break; + } + } while(shorter.chopOff()); + } else { + auth=nonterm.find(qname)->second; + } + + if(haveNSEC3) // NSEC3 + { + if(nsec3set.count(qname)) { + if(!narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, qname))); + if(!realrr && !isOptOut) + auth=true; + } + } + else if (realrr && securedZone) // NSEC + ordername=qname.makeRelative(zone); + + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, auth); + + if(realrr) + { + if (dsnames.count(qname)) + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, true, QType::DS); + if (!auth || nsset.count(qname)) { + ordername.clear(); + if(isOptOut && !dsnames.count(qname)) + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::NS); + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::A); + sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, qname, ordername, false, QType::AAAA); + } + + if(doent) + { + shorter=qname; + while(shorter!=zone && shorter.chopOff()) + { + if(!qnames.count(shorter)) + { + if(!(maxent)) + { + g_log<(shorter, auth)); + --maxent; + } else if (auth) + nonterm[shorter]=true; + } + } + } + } + } + + if(realrr) + { + //cerr<<"Total: "<updateEmptyNonTerminals(sd.domain_id, insnonterm, delnonterm, !doent); + } + if(doent) + { + realrr=false; + qnames.clear(); + for(const auto& nt : nonterm){ + qnames.insert(nt.first); + } + goto dononterm; + } + } + + if (doTransaction) + sd.db->commitTransaction(); + + info = infostream.str(); + return true; +} + +void DNSSECKeeper::cleanup() +{ + struct timeval now; + Utility::gettimeofday(&now, 0); + + if(now.tv_sec - s_last_prune > (time_t)(30)) { + { + WriteLock l(&s_metacachelock); + pruneCollection(*this, s_metacache, ::arg().asNum("max-cache-entries")); + } + { + WriteLock l(&s_keycachelock); + pruneCollection(*this, s_keycache, ::arg().asNum("max-cache-entries")); + } + s_last_prune=time(0); + } +} diff --git a/pdns/decafsigners.cc b/pdns/decafsigners.cc new file mode 100644 index 0000000..f39dfa0 --- /dev/null +++ b/pdns/decafsigners.cc @@ -0,0 +1,293 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "dnssecinfra.hh" + +using namespace decaf; + +class DecafED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit DecafED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo) + { + + } + string getName() const override { return "Decaf ED25519"; } + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string getPubKeyHash() const override; + std::string sign(const std::string& msg) const override; + bool verify(const std::string& msg, const std::string& signature) const override; + std::string getPublicKeyString() const override; + int getBits() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override + {} + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + unsigned char d_pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES]; + unsigned char d_seckey[DECAF_EDDSA_25519_PRIVATE_BYTES]; +}; + +void DecafED25519DNSCryptoKeyEngine::create(unsigned int bits) +{ + if(bits != (unsigned int)getBits()) { + throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED25519 class"); + } + + SpongeRng rng("/dev/urandom"); + + typename EdDSA::PrivateKey priv(rng); + typename EdDSA::PublicKey pub(priv); + + priv.serialize_into(d_seckey); + pub.serialize_into(d_pubkey); +} + +int DecafED25519DNSCryptoKeyEngine::getBits() const +{ + return DECAF_EDDSA_25519_PRIVATE_BYTES << 3; +} + +DNSCryptoKeyEngine::storvector_t DecafED25519DNSCryptoKeyEngine::convertToISCVector() const +{ + /* + Private-key-format: v1.2 + Algorithm: 15 (ED25519) + PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI= + */ + + storvector_t storvector; + + storvector.push_back(make_pair("Algorithm", "15 (ED25519)")); + storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES))); + + return storvector; +} + +void DecafED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap ) +{ + /* + Private-key-format: v1.2 + Algorithm: 15 (ED25519) + PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI= + */ + + drc.d_algorithm = pdns_stou(stormap["algorithm"]); + string privateKey = stormap["privatekey"]; + + if (privateKey.length() != DECAF_EDDSA_25519_PRIVATE_BYTES) + throw runtime_error("Private key size mismatch in ISCMap, DecafED25519 class"); + + typename EdDSA::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_25519_PRIVATE_BYTES)); + typename EdDSA::PublicKey pub(priv); + + priv.serialize_into(d_seckey); + pub.serialize_into(d_pubkey); +} + +std::string DecafED25519DNSCryptoKeyEngine::getPubKeyHash() const +{ + return this->getPublicKeyString(); +} + +std::string DecafED25519DNSCryptoKeyEngine::getPublicKeyString() const +{ + return string((char*)d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES); +} + +void DecafED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + if (input.length() != DECAF_EDDSA_25519_PUBLIC_BYTES) + throw runtime_error("Public key size mismatch, DecafED25519 class"); + + memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_25519_PUBLIC_BYTES); +} + +std::string DecafED25519DNSCryptoKeyEngine::sign(const std::string& msg) const +{ + typename EdDSA::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES)); + + SecureBuffer message(msg.begin(), msg.end()); + + SecureBuffer sig = priv.sign(message); + + return string(sig.begin(), sig.end()); +} + +bool DecafED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + if (signature.length() != DECAF_EDDSA_25519_SIGNATURE_BYTES) + return false; + + typename EdDSA::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES)); + + SecureBuffer sig(signature.begin(), signature.end()); + SecureBuffer message(msg.begin(), msg.end()); + + try { + pub.verify(sig, message); + } catch(CryptoException) { + return false; + } + + return true; +} + + +class DecafED448DNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit DecafED448DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo) + { + + } + string getName() const override { return "Decaf ED448"; } + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string getPubKeyHash() const override; + std::string sign(const std::string& msg) const override; + bool verify(const std::string& msg, const std::string& signature) const override; + std::string getPublicKeyString() const override; + int getBits() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override + {} + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + unsigned char d_pubkey[DECAF_EDDSA_448_PUBLIC_BYTES]; + unsigned char d_seckey[DECAF_EDDSA_448_PRIVATE_BYTES]; +}; + +void DecafED448DNSCryptoKeyEngine::create(unsigned int bits) +{ + if(bits != (unsigned int)getBits()) { + throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED448 class"); + } + + SpongeRng rng("/dev/urandom"); + + typename EdDSA::PrivateKey priv(rng); + typename EdDSA::PublicKey pub(priv); + + priv.serialize_into(d_seckey); + pub.serialize_into(d_pubkey); +} + +int DecafED448DNSCryptoKeyEngine::getBits() const +{ + return DECAF_EDDSA_448_PRIVATE_BYTES << 3; +} + +DNSCryptoKeyEngine::storvector_t DecafED448DNSCryptoKeyEngine::convertToISCVector() const +{ + /* + Private-key-format: v1.2 + Algorithm: 16 (ED448) + PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA + */ + + storvector_t storvector; + + storvector.push_back(make_pair("Algorithm", "16 (ED448)")); + storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES))); + + return storvector; +} + +void DecafED448DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap ) +{ + /* + Private-key-format: v1.2 + Algorithm: 16 (ED448) + PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA + */ + + drc.d_algorithm = pdns_stou(stormap["algorithm"]); + string privateKey = stormap["privatekey"]; + + if (privateKey.length() != DECAF_EDDSA_448_PRIVATE_BYTES) + throw runtime_error("Private key size mismatch in ISCMap, DecafED448 class"); + + typename EdDSA::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_448_PRIVATE_BYTES)); + typename EdDSA::PublicKey pub(priv); + + priv.serialize_into(d_seckey); + pub.serialize_into(d_pubkey); +} + +std::string DecafED448DNSCryptoKeyEngine::getPubKeyHash() const +{ + return this->getPublicKeyString(); +} + +std::string DecafED448DNSCryptoKeyEngine::getPublicKeyString() const +{ + return string((char*)d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES); +} + +void DecafED448DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + if (input.length() != DECAF_EDDSA_448_PUBLIC_BYTES) + throw runtime_error("Public key size mismatch, DecafED448 class"); + + memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_448_PUBLIC_BYTES); +} + +std::string DecafED448DNSCryptoKeyEngine::sign(const std::string& msg) const +{ + typename EdDSA::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES)); + + SecureBuffer message(msg.begin(), msg.end()); + + SecureBuffer sig = priv.sign(message); + + return string(sig.begin(), sig.end()); +} + +bool DecafED448DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + if (signature.length() != DECAF_EDDSA_448_SIGNATURE_BYTES) + return false; + + typename EdDSA::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES)); + + SecureBuffer sig(signature.begin(), signature.end()); + SecureBuffer message(msg.begin(), msg.end()); + + try { + pub.verify(sig, message); + } catch(CryptoException) { + return false; + } + + return true; +} + + +namespace { +struct LoaderDecafStruct +{ + LoaderDecafStruct() + { + DNSCryptoKeyEngine::report(15, &DecafED25519DNSCryptoKeyEngine::maker, true); + DNSCryptoKeyEngine::report(16, &DecafED448DNSCryptoKeyEngine::maker); + } +} loaderdecaf; +} diff --git a/pdns/devpollmplexer.cc b/pdns/devpollmplexer.cc new file mode 100644 index 0000000..37d3960 --- /dev/null +++ b/pdns/devpollmplexer.cc @@ -0,0 +1,207 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +/* + * NOTE: sys/devpoll.h relies on sigset_t being already defined so we need + * to include sys/signal.h *before* including sys/devpoll.h. + */ +#include +#include +#include "mplexer.hh" +#include "sstuff.hh" +#include +#include +#include "misc.hh" + +#include "namespaces.hh" + +class DevPollFDMultiplexer : public FDMultiplexer +{ +public: + DevPollFDMultiplexer(); + virtual ~DevPollFDMultiplexer() + { + close(d_devpollfd); + } + + virtual int run(struct timeval* tv, int timeout=500) override; + virtual void getAvailableFDs(std::vector& fds, int timeout) override; + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override; + virtual void removeFD(callbackmap_t& cbmap, int fd) override; + string getName() const override + { + return "/dev/poll"; + } +private: + int d_devpollfd; +}; + + +static FDMultiplexer* makeDevPoll() +{ + return new DevPollFDMultiplexer(); +} + +static struct DevPollRegisterOurselves +{ + DevPollRegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeDevPoll)); // priority 0! + } +} doItDevPoll; + + +//int DevPollFDMultiplexer::s_maxevents=1024; +DevPollFDMultiplexer::DevPollFDMultiplexer() +{ + d_devpollfd=open("/dev/poll", O_RDWR); + if(d_devpollfd < 0) + throw FDMultiplexerException("Setting up /dev/poll: "+stringerror()); + +} + +void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd) +{ + accountingAddFD(cbmap, fd, toDo, parameter, ttd); + + struct pollfd devent; + devent.fd=fd; + devent.events= (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT; + devent.revents = 0; + + if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) { + cbmap.erase(fd); + throw FDMultiplexerException("Adding fd to /dev/poll/ set: "+stringerror()); + } +} + +void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + if(!cbmap.erase(fd)) + throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); + + struct pollfd devent; + devent.fd=fd; + devent.events= POLLREMOVE; + devent.revents = 0; + + if(write(d_devpollfd, &devent, sizeof(devent)) != sizeof(devent)) { + cbmap.erase(fd); + throw FDMultiplexerException("Removing fd from epoll set: "+stringerror()); + } +} + +void DevPollFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) +{ + struct dvpoll dvp; + dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size(); + dvp.dp_fds = new pollfd[dvp.dp_nfds]; + dvp.dp_timeout = timeout; + int ret=ioctl(d_devpollfd, DP_POLL, &dvp); + + if(ret < 0 && errno!=EINTR) { + delete[] dvp.dp_fds; + throw FDMultiplexerException("/dev/poll returned error: "+stringerror()); + } + + for(int n=0; n < ret; ++n) { + fds.push_back(dvp.dp_fds[n].fd); + } + + delete[] dvp.dp_fds; +} + +int DevPollFDMultiplexer::run(struct timeval* now, int timeout) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + struct dvpoll dvp; + dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size(); + dvp.dp_fds = new pollfd[dvp.dp_nfds]; + dvp.dp_timeout = timeout; + int ret=ioctl(d_devpollfd, DP_POLL, &dvp); + gettimeofday(now,0); // MANDATORY! + + if(ret < 0 && errno!=EINTR) { + delete[] dvp.dp_fds; + throw FDMultiplexerException("/dev/poll returned error: "+stringerror()); + } + + if(ret < 1) { // thanks AB! + delete[] dvp.dp_fds; + return 0; + } + + d_inrun=true; + for(int n=0; n < ret; ++n) { + d_iter=d_readCallbacks.find(dvp.dp_fds[n].fd); + + if(d_iter != d_readCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + continue; // so we don't refind ourselves as writable! + } + d_iter=d_writeCallbacks.find(dvp.dp_fds[n].fd); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + } + } + delete[] dvp.dp_fds; + d_inrun=false; + return ret; +} + +#if 0 +void acceptData(int fd, funcparam_t& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "< +#include + +#include + +inline std::string pdns_hash(const EVP_MD * md, const std::string& input) +{ +#if OPENSSL_VERSION_NUMBER < 0x1010000fL + auto mdctx = std::unique_ptr(EVP_MD_CTX_create(), EVP_MD_CTX_destroy); +#else + auto mdctx = std::unique_ptr(EVP_MD_CTX_new(), EVP_MD_CTX_free); +#endif + if (!mdctx) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " context initialization failed"); + } + + if (EVP_DigestInit_ex(mdctx.get(), md, nullptr) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP initialization failed"); + } + + if (EVP_DigestUpdate(mdctx.get(), input.data(), input.size()) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP update failed"); + } + + unsigned int written; + std::string result; + result.resize(EVP_MD_size(md)); + + if (EVP_DigestFinal_ex(mdctx.get(), const_cast(reinterpret_cast(result.c_str())), &written) != 1) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP final failed"); + } + + if (written != result.size()) { + throw std::runtime_error(std::string(EVP_MD_name(md)) + " EVP final wrote " + std::to_string(written) + ", expected " + std::to_string(result.size())); + } + + return result; +} + +inline std::string pdns_md5sum(const std::string& input) +{ + const auto md = EVP_md5(); + if (md == nullptr) { + throw std::runtime_error("The MD5 digest is not available via the OpenSSL EVP interface"); + } + + return pdns_hash(md, input); +} + +inline std::string pdns_sha1sum(const std::string& input) +{ + const auto md = EVP_sha1(); + if (md == nullptr) { + throw std::runtime_error("The SHA1 digest is not available via the OpenSSL EVP interface"); + } + + return pdns_hash(md, input); +} diff --git a/pdns/distributor.hh b/pdns/distributor.hh new file mode 100644 index 0000000..f5b1e1e --- /dev/null +++ b/pdns/distributor.hh @@ -0,0 +1,342 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef DISTRIBUTOR_HH +#define DISTRIBUTOR_HH + +#include +#include +#include +#include +#include +#include "threadname.hh" +#include +#include "logger.hh" +#include "dns.hh" +#include "dnsbackend.hh" +#include "pdnsexception.hh" +#include "arguments.hh" +#include +#include "statbag.hh" + +extern StatBag S; + +/** the Distributor template class enables you to multithread slow question/answer + processes. + + Questions are posed to the Distributor, which returns the answer via a callback. + + The Distributor spawns sufficient backends, and if they thrown an exception, + it will cycle the backend but drop the query that was active during the exception. +*/ + +template class Distributor +{ +public: + static Distributor *Create(int n=1); //!< Create a new Distributor with \param n threads + typedef std::function callback_t; + virtual int question(Question *, callback_t callback) =0; //!< Submit a question to the Distributor + virtual int getQueueSize() =0; //!< Returns length of question queue + virtual bool isOverloaded() =0; +}; + +template class SingleThreadDistributor + : public Distributor +{ +public: + SingleThreadDistributor(const SingleThreadDistributor&) = delete; + void operator=(const SingleThreadDistributor&) = delete; + SingleThreadDistributor(); + typedef std::function callback_t; + int question(Question *, callback_t callback) override; //!< Submit a question to the Distributor + int getQueueSize() override { + return 0; + } + + bool isOverloaded() override + { + return false; + } + + ~SingleThreadDistributor() { + if (b) delete b; + } +private: + Backend *b{0}; +}; + +template class MultiThreadDistributor + : public Distributor +{ +public: + MultiThreadDistributor(const MultiThreadDistributor&) = delete; + void operator=(const MultiThreadDistributor&) = delete; + MultiThreadDistributor(int n); + typedef std::function callback_t; + int question(Question *, callback_t callback) override; //!< Submit a question to the Distributor + static void* makeThread(void *); //!< helper function to create our n threads + int getQueueSize() override { + return d_queued; + } + + struct QuestionData + { + Question *Q; + callback_t callback; + int id; + }; + + bool isOverloaded() override + { + return d_overloadQueueLength && (d_queued > d_overloadQueueLength); + } + +private: + int nextid; + time_t d_last_started; + unsigned int d_overloadQueueLength, d_maxQueueLength; + int d_num_threads; + std::atomic d_queued{0}, d_running{0}; + std::vector> d_pipes; +}; + +//template::nextid; +templateDistributor* Distributor::Create(int n) +{ + if( n == 1 ) + return new SingleThreadDistributor(); + else + return new MultiThreadDistributor( n ); +} + +templateSingleThreadDistributor::SingleThreadDistributor() +{ + g_log<MultiThreadDistributor::MultiThreadDistributor(int n) +{ + d_num_threads=n; + d_overloadQueueLength=::arg().asNum("overload-queue-length"); + d_maxQueueLength=::arg().asNum("max-queue-length"); + nextid=0; + d_last_started=time(0); + + pthread_t tid; + + + for(int i=0; i < n; ++i) { + int fds[2]; + if(pipe(fds) < 0) + unixDie("Creating pipe"); + d_pipes.push_back({fds[0],fds[1]}); + } + + if (n<1) { + g_log<(this)); + Utility::usleep(50000); // we've overloaded mysql in the past :-) + } + g_log<void *MultiThreadDistributor::makeThread(void *p) +{ + setThreadName("pdns/distributo"); + pthread_detach(pthread_self()); + MultiThreadDistributor *us=static_cast(p); + int ournum=us->d_running++; + + try { + Backend *b=new Backend(); // this will answer our questions + int queuetimeout=::arg().asNum("queue-limit"); + + for(;;) { + + QuestionData* QD; + if(read(us->d_pipes[ournum].first, &QD, sizeof(QD)) != sizeof(QD)) + unixDie("read"); + --us->d_queued; + Answer *a = nullptr; + + if(queuetimeout && QD->Q->d_dt.udiff()>queuetimeout*1000) { + delete QD->Q; + delete QD; + S.inc("timedout-packets"); + continue; + } + + bool allowRetry=true; +retry: + // this is the only point where we interact with the backend (synchronous) + try { + if (!b) { + allowRetry=false; + b=new Backend(); + } + a=b->question(QD->Q); + delete QD->Q; + } + catch(const PDNSException &e) { + delete b; + b=NULL; + if (!allowRetry) { + g_log<Q->replyPacket(); + + a->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", QD->Q->qdomain, QD->Q->qtype); + + delete QD->Q; + } else { + g_log<Q->replyPacket(); + + a->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", QD->Q->qdomain, QD->Q->qtype); + + delete QD->Q; + } else { + g_log<callback(a); + delete QD; + } + + delete b; + } + catch(const PDNSException &AE) { + g_log<int SingleThreadDistributor::question(Question* q, callback_t callback) +{ + Answer *a = nullptr; + bool allowRetry=true; +retry: + try { + if (!b) { + allowRetry=false; + b=new Backend; + } + a=b->question(q); // a can be NULL! + } + catch(const PDNSException &e) { + delete b; + b=NULL; + if (!allowRetry) { + g_log<replyPacket(); + + a->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", q->qdomain, q->qtype); + } else { + g_log<replyPacket(); + + a->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", q->qdomain, q->qtype); + } else { + g_log<int MultiThreadDistributor::question(Question* q, callback_t callback) +{ + q=new Question(*q); + + // this is passed to other process over pipe and released there + auto QD=new QuestionData(); + QD->Q=q; + auto ret = QD->id = nextid++; // might be deleted after write! + QD->callback=callback; + + ++d_queued; + if(write(d_pipes[QD->id % d_pipes.size()].second, &QD, sizeof(QD)) != sizeof(QD)) { + --d_queued; + unixDie("write"); + } + + if(d_queued > d_maxQueueLength) { + g_log< +#include +#include +#include +#include "dnsparser.hh" + +std::vector RCode::rcodes_s = boost::assign::list_of + ("No Error") + ("Form Error") + ("Server Failure") + ("Non-Existent domain") + ("Not Implemented") + ("Query Refused") + ("Name Exists when it should not") + ("RR Set Exists when it should not") + ("RR Set that should exist does not") + ("Server Not Authoritative for zone / Not Authorized") + ("Name not contained in zone") + ("Err#11") + ("Err#12") + ("Err#13") + ("Err#14") + ("Err#15") // Last non-extended RCode + ("Bad OPT Version / TSIG Signature Failure") + ("Key not recognized") + ("Signature out of time window") + ("Bad TKEY Mode") + ("Duplicate key name") + ("Algorithm not supported") + ("Bad Truncation") + ("Bad/missing Server Cookie") +; + +std::string RCode::to_s(uint8_t rcode) { + if (rcode > 0xF) + return std::string("ErrOutOfRange"); + return ERCode::to_s(rcode); +} + +std::string ERCode::to_s(uint8_t rcode) { + if (rcode > RCode::rcodes_s.size()-1) + return std::string("Err#")+std::to_string(rcode); + return RCode::rcodes_s[rcode]; +} + +class BoundsCheckingPointer +{ +public: + explicit BoundsCheckingPointer(const char* a, size_t length) + : d_ptr(a), d_length(length) + {} + + explicit BoundsCheckingPointer(const std::string& str) + : d_ptr(str.c_str()), d_length(str.size()) + {} + + + char operator[](size_t offset) const + { + if(offset < d_length) + return d_ptr[offset]; + throw runtime_error("out of bounds: "+std::to_string(offset)+" >= " + std::to_string(d_length)); + } +private: + const char* d_ptr; + const size_t d_length; +}; + + +// goal is to hash based purely on the question name, and turn error into 'default' +uint32_t hashQuestion(const char* packet, uint16_t len, uint32_t init) +{ + if(len < 12) + return init; + + uint32_t ret=init; + const unsigned char* end = (const unsigned char*)packet+len; + const unsigned char* pos = (const unsigned char*)packet+12; + + unsigned char labellen; + while((labellen=*pos++) && pos < end) { + if(pos + labellen + 1 > end) // include length field in hash + return 0; + ret=burtleCI(pos, labellen+1, ret); + pos += labellen; + } + return ret; +} + + +string& attodot(string &str) +{ + if(str.find_first_of("@")==string::npos) + return str; + + for (unsigned int i = 0; i < str.length(); i++) + { + if (str[i] == '@') { + str[i] = '.'; + break; + } else if (str[i] == '.') { + str.insert(i++, "\\"); + } + } + return str; +} diff --git a/pdns/dns.hh b/pdns/dns.hh new file mode 100644 index 0000000..53554ee --- /dev/null +++ b/pdns/dns.hh @@ -0,0 +1,247 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +#include +#include +#include "qtype.hh" +#include "dnsname.hh" +#include +#include + +#undef BADSIG // signal.h SIG_ERR + +class DNSBackend; +struct DNSRecord; + +struct SOAData +{ + SOAData() : ttl(0), serial(0), refresh(0), retry(0), expire(0), default_ttl(0), db(0), domain_id(-1) {}; + + DNSName qname; + DNSName nameserver; + DNSName hostmaster; + uint32_t ttl; + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t default_ttl; + DNSBackend *db; + int domain_id; +}; + +class RCode +{ +public: + enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10}; + static std::string to_s(uint8_t rcode); + static std::vector rcodes_s; +}; + +class ERCode +{ +public: + enum rcodes_ { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 }; + static std::string to_s(uint8_t rcode); +}; + +class Opcode +{ +public: + enum { Query=0, IQuery=1, Status=2, Notify=4, Update=5 }; +}; + +// enum for policy decisions, used by both auth and recursor. Not all values supported everywhere. +namespace PolicyDecision { enum returnTypes { PASS=-1, DROP=-2, TRUNCATE=-3 }; }; + +//! This class represents a resource record +class DNSResourceRecord +{ +public: + DNSResourceRecord() : last_modified(0), ttl(0), signttl(0), domain_id(-1), qclass(1), scopeMask(0), auth(1), disabled(0) {}; + ~DNSResourceRecord(){}; + static DNSResourceRecord fromWire(const DNSRecord& d); + + enum Place : uint8_t {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning within, say, a DNSPacket + + void setContent(const string& content); + string getZoneRepresentation(bool noDot=false) const; + + // data + DNSName qname; //!< the name of this record, for example: www.powerdns.com + DNSName wildcardname; + string content; //!< what this record points to. Example: 10.1.2.3 + + // Aligned on 8-byte boundries on systems where time_t is 8 bytes and int + // is 4 bytes, aka modern linux on x86_64 + time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in + + uint32_t ttl; //!< Time To Live of this record + uint32_t signttl; //!< If non-zero, use this TTL as original TTL in the RRSIG + + int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in + QType qtype; //!< qtype of this record, ie A, CNAME, MX etc + uint16_t qclass; //!< class of this record + + uint8_t scopeMask; + bool auth; + bool disabled; + + bool operator==(const DNSResourceRecord& rhs); + + bool operator<(const DNSResourceRecord &b) const + { + if(qname < b.qname) + return true; + if(qname == b.qname) + return(content < b.content); + return false; + } +}; + +#define GCCPACKATTRIBUTE __attribute__((packed)) + +struct dnsrecordheader +{ + uint16_t d_type; + uint16_t d_class; + uint32_t d_ttl; + uint16_t d_clen; +} GCCPACKATTRIBUTE; + +struct EDNS0Record +{ + uint8_t extRCode, version; + uint16_t extFlags; +} GCCPACKATTRIBUTE; + +static_assert(sizeof(EDNS0Record) == 4, "EDNS0Record size must be 4"); + +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#include +#elif __linux__ || __GNU__ +# include + +#else // with thanks to + +# define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +# define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +# define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(__i386) || defined(__ia64) || defined(__amd64) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) || \ + (defined(__Lynx__) && defined(__x86__)) +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(__sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined(__hp3000s900) || defined(MPE) || \ + defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \ + (defined(__Lynx__) && \ + (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) +# define BYTE_ORDER BIG_ENDIAN +#endif + +#endif + +struct dnsheader { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritative answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritative answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +}; + +static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12"); + +inline uint16_t * getFlagsFromDNSHeader(struct dnsheader * dh) +{ + return (uint16_t*) (((char *) dh) + sizeof(uint16_t)); +} + +#define DNS_TYPE_SIZE (2) +#define DNS_CLASS_SIZE (2) +#define DNS_TTL_SIZE (4) +#define DNS_RDLENGTH_SIZE (2) +#define EDNS_EXTENDED_RCODE_SIZE (1) +#define EDNS_VERSION_SIZE (1) +#define EDNS_OPTION_CODE_SIZE (2) +#define EDNS_OPTION_LENGTH_SIZE (2) + +#if BYTE_ORDER == BIG_ENDIAN +#define FLAGS_RD_OFFSET (8) +#define FLAGS_CD_OFFSET (12) +#elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN +#define FLAGS_RD_OFFSET (0) +#define FLAGS_CD_OFFSET (12) +#endif + +extern time_t s_starttime; + +uint32_t hashQuestion(const char* packet, uint16_t len, uint32_t init); + +struct TSIGTriplet +{ + DNSName name, algo; + string secret; +}; + +string &attodot(string &str); //!< for when you need to insert an email address in the SOA diff --git a/pdns/dns_random.cc b/pdns/dns_random.cc new file mode 100644 index 0000000..48b910c --- /dev/null +++ b/pdns/dns_random.cc @@ -0,0 +1,322 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "dns_random.hh" +#include "arguments.hh" +#include "logger.hh" +#include "boost/lexical_cast.hpp" + +#if defined(HAVE_RANDOMBYTES_STIR) +#include +#endif +#if defined(HAVE_RAND_BYTES) +#include +#endif +#if defined(HAVE_GETRANDOM) +#include +#endif + +static enum DNS_RNG { + RNG_UNINITIALIZED = 0, + RNG_SODIUM, + RNG_OPENSSL, + RNG_GETRANDOM, + RNG_ARC4RANDOM, + RNG_URANDOM, + RNG_KISS, +} chosen_rng = RNG_UNINITIALIZED; + +static int urandom_fd = -1; + +#if defined(HAVE_KISS_RNG) +/* KISS is intended for development use only */ +static unsigned int kiss_seed; +static uint32_t kiss_z, kiss_w, kiss_jsr, kiss_jcong; + +static void +kiss_init(unsigned int seed) +{ + kiss_seed = seed; + kiss_jsr = 0x5eed5eed; /* simply musn't be 0 */ + kiss_z = 1 ^ (kiss_w = kiss_jcong = seed); /* w=z=0 is bad, see Rose */ +} + +static unsigned int +kiss_rand(void) +{ + kiss_z = 36969 * (kiss_z&65535) + (kiss_z>>16); + kiss_w = 18000 * (kiss_w&65535) + (kiss_w>>16); + kiss_jcong = 69069 * kiss_jcong + 1234567; + kiss_jsr^=(kiss_jsr<<13); /* <<17, >>13 gives cycle length 2^28.2 max */ + kiss_jsr^=(kiss_jsr>>17); /* <<13, >>17 gives maximal cycle length */ + kiss_jsr^=(kiss_jsr<<5); + return (((kiss_z<<16) + kiss_w) ^ kiss_jcong) + kiss_jsr; +} +#endif + +static void dns_random_setup(bool force=false) +{ + string rdev; + string rng; + /* check if selection has been done */ + if (chosen_rng > RNG_UNINITIALIZED && !force) + return; + +/* XXX: A horrible hack to allow using dns_random in places where arguments are not available. + Forces /dev/urandom usage +*/ +#if defined(USE_URANDOM_ONLY) + chosen_rng = RNG_URANDOM; + rdev = "/dev/urandom"; +#else + rng = ::arg()["rng"]; + rdev = ::arg()["entropy-source"]; + if (rng == "auto") { +# if defined(HAVE_GETRANDOM) + chosen_rng = RNG_GETRANDOM; +# elif defined(HAVE_ARC4RANDOM) + chosen_rng = RNG_ARC4RANDOM; +# elif defined(HAVE_RANDOMBYTES_STIR) + chosen_rng = RNG_SODIUM; +# elif defined(HAVE_RAND_BYTES) + chosen_rng = RNG_OPENSSL; +# else + chosen_rng = RNG_URANDOM; +# endif +# if defined(HAVE_RANDOMBYTES_STIR) + } else if (rng == "sodium") { + chosen_rng = RNG_SODIUM; +# endif +# if defined(HAVE_RAND_BYTES) + } else if (rng == "openssl") { + chosen_rng = RNG_OPENSSL; +# endif +# if defined(HAVE_GETRANDOM) + } else if (rng == "getrandom") { + chosen_rng = RNG_GETRANDOM; +# endif +# if defined(HAVE_ARC4RANDOM) + } else if (rng == "arc4random") { + chosen_rng = RNG_ARC4RANDOM; +# endif + } else if (rng == "urandom") { + chosen_rng = RNG_URANDOM; +#if defined(HAVE_KISS_RNG) + } else if (rng == "kiss") { + chosen_rng = RNG_KISS; + g_log< 0xffffffffUL) + min = 0x100000000UL % upper_bound; +#else + /* Calculate (2**32 % upper_bound) avoiding 64-bit math */ + if (upper_bound > 0x80000000) + min = 1 + ~upper_bound; /* 2**32 - upper_bound */ + else { + /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */ + min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound; + } +#endif + + switch(chosen_rng) { + case RNG_UNINITIALIZED: + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + case RNG_SODIUM: +#if defined(HAVE_RANDOMBYTES_STIR) && !defined(USE_URANDOM_ONLY) + return randombytes_uniform(upper_bound); +#else + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached +#endif /* RND_SODIUM */ + case RNG_OPENSSL: { +#if defined(HAVE_RAND_BYTES) && !defined(USE_URANDOM_ONLY) + uint32_t num = 0; + do { + if (RAND_bytes(reinterpret_cast(&num), sizeof(num)) < 1) + throw std::runtime_error("Openssl RNG was not seeded"); + } + while(num < min); + + return num % upper_bound; +#else + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached +#endif /* RNG_OPENSSL */ + } + case RNG_GETRANDOM: { +#if defined(HAVE_GETRANDOM) && !defined(USE_URANDOM_ONLY) + uint32_t num = 0; + do { + if (getrandom(&num, sizeof(num), 0) != sizeof(num)) + throw std::runtime_error("getrandom() failed: " + std::string(strerror(errno))); + } + while(num < min); + + return num % upper_bound; +#else + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached +#endif + } + case RNG_ARC4RANDOM: +#if defined(HAVE_ARC4RANDOM) && !defined(USE_URANDOM_ONLY) + return arc4random_uniform(upper_bound); +#else + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached +#endif + case RNG_URANDOM: { + uint32_t num = 0; + size_t attempts = 5; + do { + ssize_t got = read(urandom_fd, &num, sizeof(num)); + if (got < 0) { + if (errno == EINTR) { + continue; + } + + (void)close(urandom_fd); + throw std::runtime_error("Cannot read random device"); + } + else if (static_cast(got) != sizeof(num)) { + /* short read, let's retry */ + if (attempts == 0) { + throw std::runtime_error("Too many short reads on random device"); + } + attempts--; + continue; + } + } + while(num < min); + + return num % upper_bound; + } +#if defined(HAVE_KISS_RNG) + case RNG_KISS: { + uint32_t num = 0; + do { + num = kiss_rand(); + } + while(num < min); + + return num % upper_bound; + } +#endif + default: + throw std::runtime_error("Unreachable at " __FILE__ ":" + boost::lexical_cast(__LINE__)); // cannot be reached + }; +} diff --git a/pdns/dns_random.hh b/pdns/dns_random.hh new file mode 100644 index 0000000..ad163ee --- /dev/null +++ b/pdns/dns_random.hh @@ -0,0 +1,29 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNS_RANDOM +#define PDNS_DNS_RANDOM +#include + +void dns_random_init(const std::string& data = "", bool force_reinit = false); +uint32_t dns_random(uint32_t n); + +#endif diff --git a/pdns/dns_random_urandom.cc b/pdns/dns_random_urandom.cc new file mode 100644 index 0000000..708d3df --- /dev/null +++ b/pdns/dns_random_urandom.cc @@ -0,0 +1,2 @@ +#define USE_URANDOM_ONLY +#include "dns_random.cc" diff --git a/pdns/dnsbackend.cc b/pdns/dnsbackend.cc new file mode 100644 index 0000000..eb48835 --- /dev/null +++ b/pdns/dnsbackend.cc @@ -0,0 +1,378 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include "dnsbackend.hh" +#include "arguments.hh" +#include "ueberbackend.hh" +#include "logger.hh" + +#include +#include "pdns/packetcache.hh" +#include "dnspacket.hh" +#include "dns.hh" + +// this has to be somewhere central, and not in a file that requires Lua +// this is so the geoipbackend can set this pointer if loaded for lua-record.cc +std::function g_getGeo; + +bool DNSBackend::getAuth(const DNSName &target, SOAData *sd) +{ + return this->getSOA(target, *sd); +} + +void DNSBackend::setArgPrefix(const string &prefix) +{ + d_prefix=prefix; +} + +bool DNSBackend::mustDo(const string &key) +{ + return arg().mustDo(d_prefix+"-"+key); +} + +const string &DNSBackend::getArg(const string &key) +{ + return arg()[d_prefix+"-"+key]; +} + +int DNSBackend::getArgAsNum(const string &key) +{ + return arg().asNum(d_prefix+"-"+key); +} + +void BackendFactory::declare(const string &suffix, const string ¶m, const string &help, const string &value) +{ + string fullname=d_name+suffix+"-"+param; + arg().set(fullname,help)=value; +} + +const string &BackendFactory::getName() const +{ + return d_name; +} + +BackendMakerClass &BackendMakers() +{ + static BackendMakerClass bmc; + return bmc; +} + +void BackendMakerClass::report(BackendFactory *bf) +{ + d_repository[bf->getName()]=bf; +} + + +vector BackendMakerClass::getModules() +{ + load_all(); + vector ret; + // copy(d_repository.begin(), d_repository.end(),back_inserter(ret)); + for(d_repository_t::const_iterator i=d_repository.begin();i!=d_repository.end();++i) + ret.push_back(i->first); + return ret; +} + +void BackendMakerClass::load_all() +{ + // TODO: Implement this? + DIR *dir=opendir(arg()["module-dir"].c_str()); + if(!dir) { + g_log<d_name,"lib",3) && + strlen(entry->d_name)>13 && + !strcmp(entry->d_name+strlen(entry->d_name)-10,"backend.so")) + load(entry->d_name); + } + closedir(dir); +} + +void BackendMakerClass::load(const string &module) +{ + bool res; + + if(module.find(".")==string::npos) + res=UeberBackend::loadmodule(arg()["module-dir"]+"/lib"+module+"backend.so"); + else if(module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) // absolute or current path + res=UeberBackend::loadmodule(module); + else + res=UeberBackend::loadmodule(arg()["module-dir"]+"/"+module); + + if(res==false) { + g_log< parts; + stringtok(parts,instr,", "); + + for (const auto part : parts) + if (count(parts.begin(), parts.end(), part) > 1) + throw ArgException("Refusing to launch multiple backends with the same name '" + part + "', verify all 'launch' statements in your configuration"); + + for(vector::const_iterator i=parts.begin();i!=parts.end();++i) { + const string &part=*i; + + string module, name; + vectorpparts; + stringtok(pparts,part,": "); + module=pparts[0]; + if(pparts.size()>1) + name="-"+pparts[1]; + + if(d_repository.find(module)==d_repository.end()) { + // this is *so* userfriendly + load(module); + if(d_repository.find(module)==d_repository.end()) + throw ArgException("Trying to launch unknown backend '"+module+"'"); + } + d_repository[module]->declareArguments(name); + d_instances.push_back(make_pair(module,name)); + } +} + +int BackendMakerClass::numLauncheable() +{ + return d_instances.size(); +} + +vectorBackendMakerClass::all(bool metadataOnly) +{ + vectorret; + if(d_instances.empty()) + throw PDNSException("No database backends configured for launch, unable to function"); + + try { + for(vector >::const_iterator i=d_instances.begin();i!=d_instances.end();++i) { + DNSBackend *made; + if(metadataOnly) + made = d_repository[i->first]->makeMetadataOnly(i->second); + else + made = d_repository[i->first]->make(i->second); + if(!made) + throw PDNSException("Unable to launch backend '"+i->first+"'"); + + ret.push_back(made); + } + } + catch(PDNSException &ae) { + g_log<::const_iterator i=ret.begin();i!=ret.end();++i) + delete *i; + throw; + } catch(...) { + // and cleanup + g_log<::const_iterator i=ret.begin();i!=ret.end();++i) + delete *i; + throw; + } + + return ret; +} + +/** getSOA() is a function that is called to get the SOA of a domain. Callers should ONLY + use getSOA() and not perform a lookup() themselves as backends may decide to special case + the SOA record. + + Returns false if there is definitely no SOA for the domain. May throw a DBException + to indicate that the backend is currently unable to supply an answer. + + WARNING: This function *may* fill out the db attribute of the SOAData, but then again, + it may not! If you find a zero in there, you may have been handed a non-live and cached + answer, in which case you need to perform a getDomainInfo call! + + \param domain Domain we want to get the SOA details of + \param sd SOAData which is filled with the SOA details + \param unmodifiedSerial bool if set, serial will be returned as stored in the backend (maybe 0) +*/ +bool DNSBackend::getSOA(const DNSName &domain, SOAData &sd) +{ + this->lookup(QType(QType::SOA),domain); + + DNSResourceRecord rr; + rr.auth = true; + + int hits=0; + + while(this->get(rr)) { + if (rr.qtype != QType::SOA) throw PDNSException("Got non-SOA record when asking for SOA"); + hits++; + fillSOAData(rr.content, sd); + sd.domain_id=rr.domain_id; + sd.ttl=rr.ttl; + } + + if(!hits) + return false; + sd.qname = domain; + if(!sd.nameserver.countLabels()) + sd.nameserver= DNSName(arg()["default-soa-name"]); + + if(!sd.hostmaster.countLabels()) { + if (!arg().isEmpty("default-soa-mail")) { + sd.hostmaster= DNSName(arg()["default-soa-mail"]); + // attodot(sd.hostmaster); FIXME400 + } + else + sd.hostmaster=DNSName("hostmaster")+domain; + } + + sd.db=this; + return true; +} + +bool DNSBackend::get(DNSZoneRecord& dzr) +{ + // cout<<"DNSBackend::get(DNSZoneRecord&) called - translating into DNSResourceRecord query"<get(rr)) + return false; + dzr.auth = rr.auth; + dzr.domain_id = rr.domain_id; + dzr.scopeMask = rr.scopeMask; + if(rr.qtype.getCode() == QType::TXT && !rr.content.empty() && rr.content[0]!='"') + rr.content = "\""+ rr.content + "\""; + if(rr.qtype.getCode() == QType::SOA) { + try { + dzr.dr = DNSRecord(rr); + } catch(...) { + vector parts; + stringtok(parts, rr.content, " \t"); + if(parts.size() < 1) + rr.content = arg()["default-soa-name"]; + if(parts.size() < 2) + rr.content += " " +arg()["default-soa-mail"]; + if(parts.size() < 3) + rr.content += " 0"; + if(parts.size() < 4) + rr.content += " " + ::arg()["soa-refresh-default"]; + if(parts.size() < 5) + rr.content += " " + ::arg()["soa-retry-default"]; + if(parts.size() < 6) + rr.content += " " + ::arg()["soa-expire-default"]; + if(parts.size() < 7) + rr.content += " " + ::arg()["soa-minimum-ttl"]; + dzr.dr = DNSRecord(rr); + } + } + else { + try { + dzr.dr = DNSRecord(rr); + } + catch(...) { + while(this->get(rr)); + throw; + } + } + return true; +} + +bool DNSBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) +{ + DNSName unhashed; + bool ret = this->getBeforeAndAfterNamesAbsolute(id, qname.makeRelative(zonename).makeLowerCase(), unhashed, before, after); + DNSName lczonename = zonename.makeLowerCase(); + before += lczonename; + after += lczonename; + return ret; +} + +void fillSOAData(const DNSZoneRecord& in, SOAData& sd) +{ + sd.domain_id = in.domain_id; + sd.ttl = in.dr.d_ttl; + + auto src=getRR(in.dr); + sd.nameserver = src->d_mname; + sd.hostmaster = src->d_rname; + sd.serial = src->d_st.serial; + sd.refresh = src->d_st.refresh; + sd.retry = src->d_st.retry; + sd.expire = src->d_st.expire; + sd.default_ttl = src->d_st.minimum; +} + +std::shared_ptr makeSOAContent(const SOAData& sd) +{ + struct soatimes st; + st.serial = sd.serial; + st.refresh = sd.refresh; + st.retry = sd.retry; + st.expire = sd.expire; + st.minimum = sd.default_ttl; + return std::make_shared(sd.nameserver, sd.hostmaster, st); +} + + +void fillSOAData(const string &content, SOAData &data) +{ + // content consists of fields separated by spaces: + // nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ] + + // fill out data with some plausible defaults: + // 10800 3600 604800 3600 + vectorparts; + stringtok(parts,content); + int pleft=parts.size(); + + // cout<<"'"<1) + data.hostmaster=DNSName(attodot(parts[1])); // ahu@ds9a.nl -> ahu.ds9a.nl, piet.puk@ds9a.nl -> piet\.puk.ds9a.nl + + try { + data.serial = pleft > 2 ? pdns_stou(parts[2]) : 0; + + data.refresh = pleft > 3 ? pdns_stou(parts[3]) + : ::arg().asNum("soa-refresh-default"); + + data.retry = pleft > 4 ? pdns_stou(parts[4].c_str()) + : ::arg().asNum("soa-retry-default"); + + data.expire = pleft > 5 ? pdns_stou(parts[5].c_str()) + : ::arg().asNum("soa-expire-default"); + + data.default_ttl = pleft > 6 ? pdns_stou(parts[6].c_str()) + : ::arg().asNum("soa-minimum-ttl"); + } + catch(const std::out_of_range& oor) { + throw PDNSException("Out of range exception parsing "+content); + } +} diff --git a/pdns/dnsbackend.hh b/pdns/dnsbackend.hh new file mode 100644 index 0000000..4fe4208 --- /dev/null +++ b/pdns/dnsbackend.hh @@ -0,0 +1,441 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef DNSBACKEND_HH +#define DNSBACKEND_HH + +class DNSPacket; + +#include "utility.hh" +#include +#include +#include +#include +#include "pdnsexception.hh" +#include +#include +#include +#include +#include "misc.hh" +#include "qtype.hh" +#include "dns.hh" +#include +#include "namespaces.hh" +#include "comment.hh" +#include "dnsname.hh" +#include "dnsrecords.hh" +#include "iputils.hh" + +class DNSBackend; +struct DomainInfo +{ + DomainInfo() : last_check(0), backend(NULL), id(0), notified_serial(0), serial(0), kind(DomainInfo::Native) {} + + DNSName zone; + time_t last_check; + string account; + vector masters; + DNSBackend *backend; + + uint32_t id; + uint32_t notified_serial; + + uint32_t serial; + enum DomainKind : uint8_t { Master, Slave, Native } kind; + + bool operator<(const DomainInfo& rhs) const + { + return zone < rhs.zone; + } + + const char *getKindString() const + { + return DomainInfo::getKindString(kind); + } + + static const char *getKindString(enum DomainKind kind) + { + const char *kinds[]={"Master", "Slave", "Native"}; + return kinds[kind]; + } + + static DomainKind stringToKind(const string& kind) + { + if(pdns_iequals(kind,"SLAVE")) + return DomainInfo::Slave; + else if(pdns_iequals(kind,"MASTER")) + return DomainInfo::Master; + else + return DomainInfo::Native; + } + + bool isMaster(const ComboAddress& ip) const + { + for( const auto& master: masters) { + if(ComboAddress::addressOnlyEqual()(ip, master)) + return true; + } + return false; + } + +}; + +struct TSIGKey { + DNSName name; + DNSName algorithm; + std::string key; +}; + +class DNSPacket; + +//! This virtual base class defines the interface for backends for PowerDNS. +/** To create a backend, inherit from this class and implement functions for all virtual methods. + Methods should not throw an exception if they are sure they did not find the requested data. However, + if an error occurred which prevented them temporarily from performing a lockup, they should throw a DBException, + which will cause the nameserver to send out a ServFail or take other evasive action. Probably only locking + issues should lead to DBExceptions. + + More serious errors, which may indicate that the database connection is hosed, or a configuration error occurred, should + lead to the throwing of an PDNSException. This exception will fall straight through the UeberBackend and the PacketHandler + and be caught by the Distributor, which will delete your DNSBackend instance and spawn a new one. +*/ +class DNSBackend +{ +public: + //! lookup() initiates a lookup. A lookup without results should not throw! + virtual void lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0; + virtual bool get(DNSResourceRecord &)=0; //!< retrieves one DNSResource record, returns false if no more were available + virtual bool get(DNSZoneRecord &r); + + //! Initiates a list of the specified domain + /** Once initiated, DNSResourceRecord objects can be retrieved using get(). Should return false + if the backend does not consider itself responsible for the id passed. + \param domain_id ID of which a list is requested + */ + virtual bool list(const DNSName &target, int domain_id, bool include_disabled=false)=0; + + virtual ~DNSBackend(){}; + + //! fills the soadata struct with the SOA details. Returns false if there is no SOA. + virtual bool getSOA(const DNSName &name, SOAData &soadata); + + virtual bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) + { + return false; + } + + virtual bool listSubZone(const DNSName &zone, int domain_id) + { + return false; + } + + // the DNSSEC related (getDomainMetadata has broader uses too) + bool isDnssecDomainMetadata (const string& name) { + return (name == "PRESIGNED" || name == "NSEC3PARAM" || name == "NSEC3NARROW"); + } + virtual bool getAllDomainMetadata(const DNSName& name, std::map >& meta) { return false; }; + virtual bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { return false; } + virtual bool getDomainMetadataOne(const DNSName& name, const std::string& kind, std::string& value) + { + std::vector meta; + if (getDomainMetadata(name, kind, meta)) { + if(!meta.empty()) { + value = *meta.begin(); + return true; + } + } + return false; + } + + virtual bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) {return false;} + virtual bool setDomainMetadataOne(const DNSName& name, const std::string& kind, const std::string& value) + { + const std::vector meta(1, value); + return setDomainMetadata(name, kind, meta); + } + + + virtual void getAllDomains(vector *domains, bool include_disabled=false) { } + + /** Determines if we are authoritative for a zone, and at what level */ + virtual bool getAuth(const DNSName &target, SOAData *sd); + + struct KeyData { + std::string content; + unsigned int id; + unsigned int flags; + bool active; + }; + + virtual bool getDomainKeys(const DNSName& name, std::vector& keys) { return false;} + virtual bool removeDomainKey(const DNSName& name, unsigned int id) { return false; } + virtual bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id){ return false; } + virtual bool activateDomainKey(const DNSName& name, unsigned int id) { return false; } + virtual bool deactivateDomainKey(const DNSName& name, unsigned int id) { return false; } + + virtual bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) { return false; } + virtual bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) { return false; } + virtual bool deleteTSIGKey(const DNSName& name) { return false; } + virtual bool getTSIGKeys(std::vector< struct TSIGKey > &keys) { return false; } + + virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) + { + std::cerr<<"Default beforeAndAfterAbsolute called!"<& insert, set& erase, bool remove) + { + return false; + } + + virtual bool doesDNSSEC() + { + return false; + } + + // end DNSSEC + + // comments support + virtual bool listComments(uint32_t domain_id) + { + return false; // unsupported by this backend + } + + virtual bool getComment(Comment& comment) + { + return false; + } + + virtual void feedComment(const Comment& comment) + { + } + + virtual bool replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& comments) + { + return false; + } + + //! returns true if master ip is master for domain name. + //! starts the transaction for updating domain qname (FIXME: what is id?) + virtual bool startTransaction(const DNSName &qname, int id=-1) + { + return false; + } + + //! commits the transaction started by startTransaction + virtual bool commitTransaction() + { + return false; + } + + //! aborts the transaction started by strartTransaction, should leave state unaltered + virtual bool abortTransaction() + { + return false; + } + + virtual void reload() + { + } + + virtual void rediscover(string* status=0) + { + } + + //! feeds a record to a zone, needs a call to startTransaction first + virtual bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false) + { + return false; // no problem! + } + virtual bool feedEnts(int domain_id, map &nonterm) + { + return false; + } + virtual bool feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) + { + return false; + } + + //! if this returns true, DomainInfo di contains information about the domain + virtual bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true) + { + return false; + } + //! slave capable backends should return a list of slaves that should be rechecked for staleness + virtual void getUnfreshSlaveInfos(vector* domains) + { + } + + //! get a list of IP addresses that should also be notified for a domain + virtual void alsoNotifies(const DNSName &domain, set *ips) + { + } + + //! get list of domains that have been changed since their last notification to slaves + virtual void getUpdatedMasters(vector* domains) + { + } + + //! Called by PowerDNS to inform a backend that a domain has been checked for freshness + virtual void setFresh(uint32_t domain_id) + { + + } + //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to slaves + virtual void setNotified(uint32_t id, uint32_t serial) + { + } + + //! Called when the Master of a domain should be changed + virtual bool setMaster(const DNSName &domain, const string &ip) + { + return false; + } + + //! Called when the Kind of a domain should be changed (master -> native and similar) + virtual bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) + { + return false; + } + + //! Called when the Account of a domain should be changed + virtual bool setAccount(const DNSName &domain, const string &account) + { + return false; + } + + //! Can be called to seed the getArg() function with a prefix + void setArgPrefix(const string &prefix); + + //! determine if ip is a supermaster or a domain + virtual bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) + { + return false; + } + + //! called by PowerDNS to create a new domain + virtual bool createDomain(const DNSName &domain) + { + return false; + } + + //! called by PowerDNS to create a slave record for a superMaster + virtual bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) + { + return false; + } + + //! called to delete a domain, incl. all metadata, zone contents, etc. + virtual bool deleteDomain(const DNSName &domain) + { + return false; + } + + virtual string directBackendCmd(const string &query) + { + return "directBackendCmd not supported for this backend\n"; + } + + //! Search for records, returns true if search was done successfully. + virtual bool searchRecords(const string &pattern, int maxResults, vector& result) + { + return false; + } + + //! Search for comments, returns true if search was done successfully. + virtual bool searchComments(const string &pattern, int maxResults, vector& result) + { + return false; + } + + const string& getPrefix() { return d_prefix; }; +protected: + bool mustDo(const string &key); + const string &getArg(const string &key); + int getArgAsNum(const string &key); + +private: + string d_prefix; +}; + +class BackendFactory +{ +public: + BackendFactory(const string &name) : d_name(name) {} + virtual ~BackendFactory(){} + virtual DNSBackend *make(const string &suffix)=0; + virtual DNSBackend *makeMetadataOnly(const string &suffix) + { + return this->make(suffix); + } + virtual void declareArguments(const string &suffix=""){} + const string &getName() const; + +protected: + void declare(const string &suffix, const string ¶m, const string &explanation, const string &value); + +private: + const string d_name; +}; + +class BackendMakerClass +{ +public: + void report(BackendFactory *bf); + void launch(const string &instr); + vectorall(bool skipBIND=false); + void load(const string &module); + int numLauncheable(); + vector getModules(); + +private: + void load_all(); + typedef mapd_repository_t; + d_repository_t d_repository; + vector >d_instances; +}; + +extern BackendMakerClass &BackendMakers(); + +//! Exception that can be thrown by a DNSBackend to indicate a failure +class DBException : public PDNSException +{ +public: + DBException(const string &reason_) : PDNSException(reason_){} +}; + +/** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */ +void fillSOAData(const string &content, SOAData &data); +// same but more karmic +void fillSOAData(const DNSZoneRecord& in, SOAData& data); +// the reverse +std::shared_ptr makeSOAContent(const SOAData& sd); + +#endif diff --git a/pdns/dnsbulktest.cc b/pdns/dnsbulktest.cc new file mode 100644 index 0000000..18bfeee --- /dev/null +++ b/pdns/dnsbulktest.cc @@ -0,0 +1,370 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include "inflighter.cc" +#include +#include "namespaces.hh" +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" + +using namespace boost::accumulators; +namespace po = boost::program_options; + +po::variables_map g_vm; + +StatBag S; + +bool g_quiet=false; +bool g_envoutput=false; + +struct DNSResult +{ + vector ips; + int rcode; + bool seenauthsoa; +}; + +struct TypedQuery +{ + TypedQuery(const string& name_, uint16_t type_) : name(name_), type(type_){} + DNSName name; + uint16_t type; +}; + +struct SendReceive +{ + typedef int Identifier; + typedef DNSResult Answer; // ip + int d_socket; + deque d_idqueue; + + typedef accumulator_set< + double + , stats + > acc_t; + acc_t* d_acc; + + boost::array d_probs; + + SendReceive(const std::string& remoteAddr, uint16_t port) : d_probs({{0.001,0.01, 0.025, 0.1, 0.25,0.5,0.75,0.9,0.975, 0.99,0.9999}}) + { + d_acc = new acc_t(boost::accumulators::tag::extended_p_square::probabilities=d_probs); + // + //d_acc = acc_t + d_socket = socket(AF_INET, SOCK_DGRAM, 0); + int val=1; + setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + + ComboAddress remote(remoteAddr, port); + connect(d_socket, (struct sockaddr*)&remote, remote.getSocklen()); + d_oks = d_errors = d_nodatas = d_nxdomains = d_unknowns = 0; + d_receiveds = d_receiveerrors = d_senderrors = 0; + for(unsigned int id =0 ; id < std::numeric_limits::max(); ++id) + d_idqueue.push_back(id); + } + + ~SendReceive() + { + close(d_socket); + } + + Identifier send(TypedQuery& domain) + { + //cerr<<"Sending query for '"< packet; + + DNSPacketWriter pw(packet, domain.name, domain.type); + + if(d_idqueue.empty()) { + cerr<<"Exhausted ids!"<id = d_idqueue.front(); + d_idqueue.pop_front(); + pw.getHeader()->rd = 1; + pw.getHeader()->qr = 0; + + if(::send(d_socket, &*packet.begin(), packet.size(), 0) < 0) + d_senderrors++; + + if(!g_quiet) + cout<<"Sent out query for '"<id<id; + } + + bool receive(Identifier& id, DNSResult& dr) + { + if(waitForData(d_socket, 0, 500000) > 0) { + char buf[512]; + + int len = recv(d_socket, buf, sizeof(buf), 0); + if(len < 0) { + d_receiveerrors++; + return 0; + } + else { + d_receiveds++; + } + // parse packet, set 'id', fill out 'ip' + + MOADNSParser mdp(false, string(buf, len)); + if(!g_quiet) { + cout<<"Reply to question for qname='"<first.d_place == 1 && i->first.d_type == mdp.d_qtype) + dr.ips.push_back(ComboAddress(i->first.d_content->getZoneRepresentation())); + if(i->first.d_place == 2 && i->first.d_type == QType::SOA) { + dr.seenauthsoa = 1; + } + if(!g_quiet) + { + cout<first.d_place-1<<"\t"<first.d_name<<"\tIN\t"<first.d_type); + cout<<"\t"<first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n"; + } + } + + id = mdp.d_header.id; + d_idqueue.push_back(id); + + return 1; + } + return 0; + } + + void deliverTimeout(const Identifier& id) + { + if(!g_quiet) { + cout<<"Timeout for id "< 1000000) + // cerr<<"Slow: "<()->default_value("A"), "What type to query for") + ("envoutput,e", "write report in shell environment format") + ("version", "show the version number") + ("www", po::value()->default_value(true), "duplicate all queries with an additional 'www.' in front") + ; + + po::options_description alloptions; + po::options_description hidden("hidden options"); + hidden.add_options() + ("ip-address", po::value(), "ip-address") + ("portnumber", po::value(), "portnumber") + ("limit", po::value()->default_value(0), "limit"); + + alloptions.add(desc).add(hidden); + po::positional_options_description p; + p.add("ip-address", 1); + p.add("portnumber", 1); + p.add("limit", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + if (g_vm.count("help")) { + usage(desc); + return EXIT_SUCCESS; + } + + if (g_vm.count("version")) { + cerr<<"dnsbulktest "<(); + g_quiet = g_vm.count("quiet") > 0; + g_envoutput = g_vm.count("envoutput") > 0; + uint16_t qtype; + reportAllTypes(); + try { + qtype = DNSRecordContent::TypeToNumber(g_vm["type"].as()); + } + catch(std::exception& e) { + cerr << e.what() << endl; + return EXIT_FAILURE; + } + + SendReceive sr(g_vm["ip-address"].as(), g_vm["portnumber"].as()); + unsigned int limit = g_vm["limit"].as(); + + vector domains; + + Inflighter, SendReceive> inflighter(domains, sr); + inflighter.d_maxInFlight = 1000; + inflighter.d_timeoutSeconds = 3; + inflighter.d_burst = 100; + string line; + + pair split; + string::size_type pos; + while(stringfgets(stdin, line)) { + if(limit && domains.size() >= limit) + break; + + trim_right(line); + if(line.empty() || line[0] == '#') + continue; + split=splitField(line,','); + if (split.second.empty()) + split=splitField(line,'\t'); + if(split.second.find('.') == 0) // skip 'Hidden profile' in quantcast list. + continue; + pos=split.second.find('/'); + if(pos != string::npos) // alexa has whole urls in the list now. + split.second.resize(pos); + if(find_if(split.second.begin(), split.second.end(), isalpha) == split.second.end()) + { + continue; // this was an IP address + } + domains.push_back(TypedQuery(split.second, qtype)); + if(doWww) + domains.push_back(TypedQuery("www."+split.second, qtype)); + } + cerr<<"Read "< +#include +#include +#include +#include +#include +#include "anadns.hh" + +#include "namespaces.hh" + +StatBag S; + +struct Entry +{ + ComboAddress ip; + uint16_t port; + uint16_t id; + + bool operator<(const struct Entry& rhs) const + { + return tie(ip, port, id) < tie(rhs.ip, rhs.port, rhs.id); + } +}; + + +typedef map emap_t; +emap_t ecount; + +int main(int argc, char** argv) +try +{ + cout << "begin;"; + for(int n=1 ; n < argc; ++n) { + PcapPacketReader pr(argv[n]); + + Entry entry; + while(pr.getUDPPacket()) { + if(ntohs(pr.d_udp->uh_dport)==53 && pr.d_len > 12) { + try { + dnsheader* dh= (dnsheader*) pr.d_payload; + + if(dh->rd || dh->qr) + continue; + + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); + + entry.ip = pr.getSource(); + entry.port = pr.d_udp->uh_sport; + entry.id=dh->id; + + cout << "insert into dnsstats (source, port, id, query, qtype, tstampSec, tstampUsec, arcount) values ('" << entry.ip.toString() <<"', "<< ntohs(entry.port) <<", "<< ntohs(dh->id); + cout <<", '"<arcount) <<");\n"; + + } + catch(const MOADNSException &mde) { + // cerr<<"error parsing packet: "<second > 1) + cout << U32ToIP(ntohl(i->first.ip)) <<":"<first.port)<<" -> "<second < + +#include "dnsdist.hh" +#include "dolog.hh" +#include "dnsparser.hh" +#include "dnsdist-cache.hh" +#include "dnsdist-ecs.hh" +#include "ednsoptions.hh" +#include "ednssubnet.hh" + +DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t maxNegativeTTL, uint32_t staleTTL, bool dontAge, uint32_t shards, bool deferrableInsertLock, bool parseECS): d_maxEntries(maxEntries), d_shardCount(shards), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_maxNegativeTTL(maxNegativeTTL), d_minTTL(minTTL), d_staleTTL(staleTTL), d_dontAge(dontAge), d_deferrableInsertLock(deferrableInsertLock), d_parseECS(parseECS) +{ + d_shards.resize(d_shardCount); + + /* we reserve maxEntries + 1 to avoid rehashing from occurring + when we get to maxEntries, as it means a load factor of 1 */ + for (auto& shard : d_shards) { + shard.setSize((maxEntries / d_shardCount) + 1); + } +} + +DNSDistPacketCache::~DNSDistPacketCache() +{ + try { + vector> locks; + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + locks.push_back(std::unique_ptr(new WriteLock(&d_shards.at(shardIndex).d_lock))); + } + } + catch(...) { + } +} + +bool DNSDistPacketCache::getClientSubnet(const char* packet, unsigned int consumed, uint16_t len, boost::optional& subnet) +{ + uint16_t optRDPosition; + size_t remaining = 0; + + int res = getEDNSOptionsStart(const_cast(packet), consumed, len, &optRDPosition, &remaining); + + if (res == 0) { + char * ecsOptionStart = nullptr; + size_t ecsOptionSize = 0; + + res = getEDNSOption(const_cast(packet) + optRDPosition, remaining, EDNSOptionCode::ECS, &ecsOptionStart, &ecsOptionSize); + + if (res == 0 && ecsOptionSize > (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) { + + EDNSSubnetOpts eso; + if (getEDNSSubnetOptsFromString(ecsOptionStart + (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), ecsOptionSize - (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), &eso) == true) { + subnet = eso.source; + return true; + } + } + } + + return false; +} + +bool DNSDistPacketCache::cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, bool dnssecOK, const boost::optional& subnet) const +{ + if (cachedValue.queryFlags != queryFlags || cachedValue.dnssecOK != dnssecOK || cachedValue.tcp != tcp || cachedValue.qtype != qtype || cachedValue.qclass != qclass || cachedValue.qname != qname) { + return false; + } + + if (d_parseECS && cachedValue.subnet != subnet) { + return false; + } + + return true; +} + +void DNSDistPacketCache::insertLocked(CacheShard& shard, uint32_t key, CacheValue& newValue) +{ + auto& map = shard.d_map; + /* check again now that we hold the lock to prevent a race */ + if (map.size() >= (d_maxEntries / d_shardCount)) { + return; + } + + std::unordered_map::iterator it; + bool result; + tie(it, result) = map.insert({key, newValue}); + + if (result) { + shard.d_entriesCount++; + return; + } + + /* in case of collision, don't override the existing entry + except if it has expired */ + CacheValue& value = it->second; + bool wasExpired = value.validity <= newValue.added; + + if (!wasExpired && !cachedValueMatches(value, newValue.queryFlags, newValue.qname, newValue.qtype, newValue.qclass, newValue.tcp, newValue.dnssecOK, newValue.subnet)) { + d_insertCollisions++; + return; + } + + /* if the existing entry had a longer TTD, keep it */ + if (newValue.validity <= value.validity) { + return; + } + + value = newValue; +} + +void DNSDistPacketCache::insert(uint32_t key, const boost::optional& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, uint8_t rcode, boost::optional tempFailureTTL) +{ + if (responseLen < sizeof(dnsheader)) { + return; + } + + uint32_t minTTL; + + if (rcode == RCode::ServFail || rcode == RCode::Refused) { + minTTL = tempFailureTTL == boost::none ? d_tempFailureTTL : *tempFailureTTL; + if (minTTL == 0) { + return; + } + } + else { + bool seenAuthSOA = false; + minTTL = getMinTTL(response, responseLen, &seenAuthSOA); + + /* no TTL found, we don't want to cache this */ + if (minTTL == std::numeric_limits::max()) { + return; + } + + if (rcode == RCode::NXDomain || (rcode == RCode::NoError && seenAuthSOA)) { + minTTL = std::min(minTTL, d_maxNegativeTTL); + } + else if (minTTL > d_maxTTL) { + minTTL = d_maxTTL; + } + + if (minTTL < d_minTTL) { + d_ttlTooShorts++; + return; + } + } + + uint32_t shardIndex = getShardIndex(key); + + if (d_shards.at(shardIndex).d_entriesCount >= (d_maxEntries / d_shardCount)) { + return; + } + + const time_t now = time(nullptr); + time_t newValidity = now + minTTL; + CacheValue newValue; + newValue.qname = qname; + newValue.qtype = qtype; + newValue.qclass = qclass; + newValue.queryFlags = queryFlags; + newValue.len = responseLen; + newValue.validity = newValidity; + newValue.added = now; + newValue.tcp = tcp; + newValue.dnssecOK = dnssecOK; + newValue.value = std::string(response, responseLen); + newValue.subnet = subnet; + + auto& shard = d_shards.at(shardIndex); + + if (d_deferrableInsertLock) { + TryWriteLock w(&shard.d_lock); + + if (!w.gotIt()) { + d_deferredInserts++; + return; + } + insertLocked(shard, key, newValue); + } + else { + WriteLock w(&shard.d_lock); + + insertLocked(shard, key, newValue); + } +} + +bool DNSDistPacketCache::get(const DNSQuestion& dq, uint16_t consumed, uint16_t queryId, char* response, uint16_t* responseLen, uint32_t* keyOut, boost::optional& subnet, bool dnssecOK, uint32_t allowExpired, bool skipAging) +{ + std::string dnsQName(dq.qname->toDNSString()); + uint32_t key = getKey(dnsQName, consumed, reinterpret_cast(dq.dh), dq.len, dq.tcp); + + if (keyOut) + *keyOut = key; + + if (d_parseECS) { + getClientSubnet(reinterpret_cast(dq.dh), consumed, dq.len, subnet); + } + + uint32_t shardIndex = getShardIndex(key); + time_t now = time(nullptr); + time_t age; + bool stale = false; + auto& shard = d_shards.at(shardIndex); + auto& map = shard.d_map; + { + TryReadLock r(&shard.d_lock); + if (!r.gotIt()) { + d_deferredLookups++; + return false; + } + + std::unordered_map::const_iterator it = map.find(key); + if (it == map.end()) { + d_misses++; + return false; + } + + const CacheValue& value = it->second; + if (value.validity <= now) { + if ((now - value.validity) >= static_cast(allowExpired)) { + d_misses++; + return false; + } + else { + stale = true; + } + } + + if (*responseLen < value.len || value.len < sizeof(dnsheader)) { + return false; + } + + /* check for collision */ + if (!cachedValueMatches(value, *(getFlagsFromDNSHeader(dq.dh)), *dq.qname, dq.qtype, dq.qclass, dq.tcp, dnssecOK, subnet)) { + d_lookupCollisions++; + return false; + } + + memcpy(response, &queryId, sizeof(queryId)); + memcpy(response + sizeof(queryId), value.value.c_str() + sizeof(queryId), sizeof(dnsheader) - sizeof(queryId)); + + if (value.len == sizeof(dnsheader)) { + /* DNS header only, our work here is done */ + *responseLen = value.len; + d_hits++; + return true; + } + + const size_t dnsQNameLen = dnsQName.length(); + if (value.len < (sizeof(dnsheader) + dnsQNameLen)) { + return false; + } + + memcpy(response + sizeof(dnsheader), dnsQName.c_str(), dnsQNameLen); + if (value.len > (sizeof(dnsheader) + dnsQNameLen)) { + memcpy(response + sizeof(dnsheader) + dnsQNameLen, value.value.c_str() + sizeof(dnsheader) + dnsQNameLen, value.len - (sizeof(dnsheader) + dnsQNameLen)); + } + *responseLen = value.len; + if (!stale) { + age = now - value.added; + } + else { + age = (value.validity - value.added) - d_staleTTL; + } + } + + if (!d_dontAge && !skipAging) { + ageDNSPacket(response, *responseLen, age); + } + + d_hits++; + return true; +} + +/* Remove expired entries, until the cache has at most + upTo entries in it. +*/ +size_t DNSDistPacketCache::purgeExpired(size_t upTo) +{ + size_t removed = 0; + uint64_t size = getSize(); + + if (size == 0 || upTo >= size) { + return removed; + } + + size_t toRemove = size - upTo; + + size_t scannedMaps = 0; + + const time_t now = time(nullptr); + do { + uint32_t shardIndex = (d_expungeIndex++ % d_shardCount); + WriteLock w(&d_shards.at(shardIndex).d_lock); + auto& map = d_shards[shardIndex].d_map; + + for(auto it = map.begin(); toRemove > 0 && it != map.end(); ) { + const CacheValue& value = it->second; + + if (value.validity <= now) { + it = map.erase(it); + --toRemove; + d_shards[shardIndex].d_entriesCount--; + ++removed; + } else { + ++it; + } + } + + scannedMaps++; + } + while (toRemove > 0 && scannedMaps < d_shardCount); + + return removed; +} + +/* Remove all entries, keeping only upTo + entries in the cache */ +size_t DNSDistPacketCache::expunge(size_t upTo) +{ + size_t removed = 0; + const uint64_t size = getSize(); + + if (upTo >= size) { + return removed; + } + + size_t toRemove = size - upTo; + + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + WriteLock w(&d_shards.at(shardIndex).d_lock); + auto& map = d_shards[shardIndex].d_map; + auto beginIt = map.begin(); + auto endIt = beginIt; + size_t removeFromThisShard = (toRemove - removed) / (d_shardCount - shardIndex); + if (map.size() >= removeFromThisShard) { + std::advance(endIt, removeFromThisShard); + map.erase(beginIt, endIt); + d_shards[shardIndex].d_entriesCount -= removeFromThisShard; + removed += removeFromThisShard; + } + else { + removed += map.size(); + map.clear(); + d_shards[shardIndex].d_entriesCount = 0; + } + } + + return removed; +} + +size_t DNSDistPacketCache::expungeByName(const DNSName& name, uint16_t qtype, bool suffixMatch) +{ + size_t removed = 0; + + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + WriteLock w(&d_shards.at(shardIndex).d_lock); + auto& map = d_shards[shardIndex].d_map; + + for(auto it = map.begin(); it != map.end(); ) { + const CacheValue& value = it->second; + + if ((value.qname == name || (suffixMatch && value.qname.isPartOf(name))) && (qtype == QType::ANY || qtype == value.qtype)) { + it = map.erase(it); + d_shards[shardIndex].d_entriesCount--; + ++removed; + } else { + ++it; + } + } + } + + return removed; +} + +bool DNSDistPacketCache::isFull() +{ + return (getSize() >= d_maxEntries); +} + +uint64_t DNSDistPacketCache::getSize() +{ + uint64_t count = 0; + + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + count += d_shards.at(shardIndex).d_entriesCount; + } + + return count; +} + +uint32_t DNSDistPacketCache::getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA) +{ + return getDNSPacketMinTTL(packet, length, seenNoDataSOA); +} + +uint32_t DNSDistPacketCache::getKey(const std::string& qname, uint16_t consumed, const unsigned char* packet, uint16_t packetLen, bool tcp) +{ + uint32_t result = 0; + /* skip the query ID */ + if (packetLen < sizeof(dnsheader)) + throw std::range_error("Computing packet cache key for an invalid packet size"); + result = burtle(packet + 2, sizeof(dnsheader) - 2, result); + string lc(toLower(qname)); + result = burtle((const unsigned char*) lc.c_str(), lc.length(), result); + if (packetLen < sizeof(dnsheader) + consumed) { + throw std::range_error("Computing packet cache key for an invalid packet"); + } + if (packetLen > ((sizeof(dnsheader) + consumed))) { + result = burtle(packet + sizeof(dnsheader) + consumed, packetLen - (sizeof(dnsheader) + consumed), result); + } + result = burtle((const unsigned char*) &tcp, sizeof(tcp), result); + return result; +} + +uint32_t DNSDistPacketCache::getShardIndex(uint32_t key) const +{ + return key % d_shardCount; +} + +string DNSDistPacketCache::toString() +{ + return std::to_string(getSize()) + "/" + std::to_string(d_maxEntries); +} + +uint64_t DNSDistPacketCache::getEntriesCount() +{ + return getSize(); +} + +uint64_t DNSDistPacketCache::dump(int fd) +{ + FILE * fp = fdopen(dup(fd), "w"); + if (fp == nullptr) { + return 0; + } + + fprintf(fp, "; dnsdist's packet cache dump follows\n;\n"); + + uint64_t count = 0; + time_t now = time(nullptr); + for (uint32_t shardIndex = 0; shardIndex < d_shardCount; shardIndex++) { + ReadLock w(&d_shards.at(shardIndex).d_lock); + auto& map = d_shards[shardIndex].d_map; + + for(const auto entry : map) { + const CacheValue& value = entry.second; + count++; + + try { + fprintf(fp, "%s %" PRId64 " %s ; key %" PRIu32 ", length %" PRIu16 ", tcp %d, added %" PRId64 "\n", value.qname.toString().c_str(), static_cast(value.validity - now), QType(value.qtype).getName().c_str(), entry.first, value.len, value.tcp, static_cast(value.added)); + } + catch(...) { + fprintf(fp, "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); + } + } + } + + fclose(fp); + return count; +} diff --git a/pdns/dnsdist-cache.hh b/pdns/dnsdist-cache.hh new file mode 100644 index 0000000..887f03d --- /dev/null +++ b/pdns/dnsdist-cache.hh @@ -0,0 +1,138 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include + +#include "iputils.hh" +#include "lock.hh" + +struct DNSQuestion; + +class DNSDistPacketCache : boost::noncopyable +{ +public: + DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t maxNegativeTTL=3600, uint32_t staleTTL=60, bool dontAge=false, uint32_t shards=1, bool deferrableInsertLock=true, bool parseECS=false); + ~DNSDistPacketCache(); + + void insert(uint32_t key, const boost::optional& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, uint8_t rcode, boost::optional tempFailureTTL); + bool get(const DNSQuestion& dq, uint16_t consumed, uint16_t queryId, char* response, uint16_t* responseLen, uint32_t* keyOut, boost::optional& subnetOut, bool dnssecOK, uint32_t allowExpired=0, bool skipAging=false); + size_t purgeExpired(size_t upTo=0); + size_t expunge(size_t upTo=0); + size_t expungeByName(const DNSName& name, uint16_t qtype=QType::ANY, bool suffixMatch=false); + bool isFull(); + string toString(); + uint64_t getSize(); + uint64_t getHits() const { return d_hits; } + uint64_t getMisses() const { return d_misses; } + uint64_t getDeferredLookups() const { return d_deferredLookups; } + uint64_t getDeferredInserts() const { return d_deferredInserts; } + uint64_t getLookupCollisions() const { return d_lookupCollisions; } + uint64_t getInsertCollisions() const { return d_insertCollisions; } + uint64_t getMaxEntries() const { return d_maxEntries; } + uint64_t getTTLTooShorts() const { return d_ttlTooShorts; } + uint64_t getEntriesCount(); + uint64_t dump(int fd); + + bool isECSParsingEnabled() const { return d_parseECS; } + + bool keepStaleData() const + { + return d_keepStaleData; + } + void setKeepStaleData(bool keep) + { + d_keepStaleData = keep; + } + + static uint32_t getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA); + static uint32_t getKey(const std::string& qname, uint16_t consumed, const unsigned char* packet, uint16_t packetLen, bool tcp); + static bool getClientSubnet(const char* packet, unsigned int consumed, uint16_t len, boost::optional& subnet); + +private: + + struct CacheValue + { + time_t getTTD() const { return validity; } + std::string value; + DNSName qname; + boost::optional subnet; + uint16_t qtype{0}; + uint16_t qclass{0}; + uint16_t queryFlags{0}; + time_t added{0}; + time_t validity{0}; + uint16_t len{0}; + bool tcp{false}; + bool dnssecOK{false}; + }; + + class CacheShard + { + public: + CacheShard(): d_entriesCount(0) + { + pthread_rwlock_init(&d_lock, 0); + } + CacheShard(const CacheShard& old): d_entriesCount(0) + { + pthread_rwlock_init(&d_lock, 0); + } + + void setSize(size_t maxSize) + { + d_map.reserve(maxSize); + } + + std::unordered_map d_map; + pthread_rwlock_t d_lock; + std::atomic d_entriesCount; + }; + + bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, bool dnssecOK, const boost::optional& subnet) const; + uint32_t getShardIndex(uint32_t key) const; + void insertLocked(CacheShard& shard, uint32_t key, CacheValue& newValue); + + std::vector d_shards; + + std::atomic d_deferredLookups{0}; + std::atomic d_deferredInserts{0}; + std::atomic d_hits{0}; + std::atomic d_misses{0}; + std::atomic d_insertCollisions{0}; + std::atomic d_lookupCollisions{0}; + std::atomic d_ttlTooShorts{0}; + + size_t d_maxEntries; + uint32_t d_expungeIndex{0}; + uint32_t d_shardCount; + uint32_t d_maxTTL; + uint32_t d_tempFailureTTL; + uint32_t d_maxNegativeTTL; + uint32_t d_minTTL; + uint32_t d_staleTTL; + bool d_dontAge; + bool d_deferrableInsertLock; + bool d_parseECS; + bool d_keepStaleData{false}; +}; diff --git a/pdns/dnsdist-ecs.cc b/pdns/dnsdist-ecs.cc new file mode 100644 index 0000000..5e8974d --- /dev/null +++ b/pdns/dnsdist-ecs.cc @@ -0,0 +1,767 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "dolog.hh" +#include "dnsdist.hh" +#include "dnsdist-ecs.hh" +#include "dnsparser.hh" +#include "dnswriter.hh" +#include "ednsoptions.hh" +#include "ednssubnet.hh" + +/* when we add EDNS to a query, we don't want to advertise + a large buffer size */ +size_t g_EdnsUDPPayloadSize = 512; +uint16_t g_PayloadSizeSelfGenAnswers{s_udpIncomingBufferSize}; + +/* draft-ietf-dnsop-edns-client-subnet-04 "11.1. Privacy" */ +uint16_t g_ECSSourcePrefixV4 = 24; +uint16_t g_ECSSourcePrefixV6 = 56; + +bool g_ECSOverride{false}; +bool g_addEDNSToSelfGeneratedResponses{true}; + +int rewriteResponseWithoutEDNS(const std::string& initialPacket, vector& newContent) +{ + assert(initialPacket.size() >= sizeof(dnsheader)); + const struct dnsheader* dh = reinterpret_cast(initialPacket.data()); + + if (ntohs(dh->arcount) == 0) + return ENOENT; + + if (ntohs(dh->qdcount) == 0) + return ENOENT; + + PacketReader pr(initialPacket); + + size_t idx = 0; + DNSName rrname; + uint16_t qdcount = ntohs(dh->qdcount); + uint16_t ancount = ntohs(dh->ancount); + uint16_t nscount = ntohs(dh->nscount); + uint16_t arcount = ntohs(dh->arcount); + uint16_t rrtype; + uint16_t rrclass; + string blob; + struct dnsrecordheader ah; + + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + + DNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode); + pw.getHeader()->id=dh->id; + pw.getHeader()->qr=dh->qr; + pw.getHeader()->aa=dh->aa; + pw.getHeader()->tc=dh->tc; + pw.getHeader()->rd=dh->rd; + pw.getHeader()->ra=dh->ra; + pw.getHeader()->ad=dh->ad; + pw.getHeader()->cd=dh->cd; + pw.getHeader()->rcode=dh->rcode; + + /* consume remaining qd if any */ + if (qdcount > 1) { + for(idx = 1; idx < qdcount; idx++) { + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + (void) rrtype; + (void) rrclass; + } + } + + /* copy AN and NS */ + for (idx = 0; idx < ancount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ANSWER, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } + + for (idx = 0; idx < nscount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::AUTHORITY, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } + /* consume AR, looking for OPT */ + for (idx = 0; idx < arcount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + if (ah.d_type != QType::OPT) { + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } else { + pr.skip(ah.d_clen); + } + } + pw.commit(); + + return 0; +} + +int locateEDNSOptRR(const std::string& packet, uint16_t * optStart, size_t * optLen, bool * last) +{ + assert(optStart != NULL); + assert(optLen != NULL); + assert(last != NULL); + const struct dnsheader* dh = reinterpret_cast(packet.data()); + + if (ntohs(dh->arcount) == 0) + return ENOENT; + + PacketReader pr(packet); + size_t idx = 0; + DNSName rrname; + uint16_t qdcount = ntohs(dh->qdcount); + uint16_t ancount = ntohs(dh->ancount); + uint16_t nscount = ntohs(dh->nscount); + uint16_t arcount = ntohs(dh->arcount); + uint16_t rrtype; + uint16_t rrclass; + struct dnsrecordheader ah; + + /* consume qd */ + for(idx = 0; idx < qdcount; idx++) { + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + (void) rrtype; + (void) rrclass; + } + + /* consume AN and NS */ + for (idx = 0; idx < ancount + nscount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + pr.skip(ah.d_clen); + } + + /* consume AR, looking for OPT */ + for (idx = 0; idx < arcount; idx++) { + uint16_t start = pr.getPosition(); + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + if (ah.d_type == QType::OPT) { + *optStart = start; + *optLen = (pr.getPosition() - start) + ah.d_clen; + + if (packet.size() < (*optStart + *optLen)) { + throw std::range_error("Opt record overflow"); + } + + if (idx == ((size_t) arcount - 1)) { + *last = true; + } + else { + *last = false; + } + return 0; + } + pr.skip(ah.d_clen); + } + + return ENOENT; +} + +/* extract the start of the OPT RR in a QUERY packet if any */ +int getEDNSOptionsStart(const char* packet, const size_t offset, const size_t len, uint16_t* optRDPosition, size_t * remaining) +{ + assert(packet != nullptr); + assert(optRDPosition != nullptr); + assert(remaining != nullptr); + const struct dnsheader* dh = reinterpret_cast(packet); + + if (offset >= len) { + return ENOENT; + } + + if (ntohs(dh->qdcount) != 1 || ntohs(dh->ancount) != 0 || ntohs(dh->arcount) != 1 || ntohs(dh->nscount) != 0) + return ENOENT; + + size_t pos = sizeof(dnsheader) + offset; + pos += DNS_TYPE_SIZE + DNS_CLASS_SIZE; + + if (pos >= len) + return ENOENT; + + if ((pos + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE) >= len) { + return ENOENT; + } + + if (packet[pos] != 0) { + /* not the root so not an OPT record */ + return ENOENT; + } + pos += 1; + + uint16_t qtype = (reinterpret_cast(packet)[pos])*256 + reinterpret_cast(packet)[pos+1]; + pos += DNS_TYPE_SIZE; + pos += DNS_CLASS_SIZE; + + if(qtype != QType::OPT || (len - pos) < (DNS_TTL_SIZE + DNS_RDLENGTH_SIZE)) + return ENOENT; + + pos += DNS_TTL_SIZE; + *optRDPosition = pos; + *remaining = len - pos; + + return 0; +} + +void generateECSOption(const ComboAddress& source, string& res, uint16_t ECSPrefixLength) +{ + Netmask sourceNetmask(source, ECSPrefixLength); + EDNSSubnetOpts ecsOpts; + ecsOpts.source = sourceNetmask; + string payload = makeEDNSSubnetOptsString(ecsOpts); + generateEDNSOption(EDNSOptionCode::ECS, payload, res); +} + +void generateOptRR(const std::string& optRData, string& res, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK) +{ + const uint8_t name = 0; + dnsrecordheader dh; + EDNS0Record edns0; + edns0.extRCode = ednsrcode; + edns0.version = 0; + edns0.extFlags = dnssecOK ? htons(EDNS_HEADER_FLAG_DO) : 0; + + dh.d_type = htons(QType::OPT); + dh.d_class = htons(udpPayloadSize); + static_assert(sizeof(EDNS0Record) == sizeof(dh.d_ttl), "sizeof(EDNS0Record) must match sizeof(dnsrecordheader.d_ttl)"); + memcpy(&dh.d_ttl, &edns0, sizeof edns0); + dh.d_clen = htons(static_cast(optRData.length())); + res.reserve(sizeof(name) + sizeof(dh) + optRData.length()); + res.assign(reinterpret_cast(&name), sizeof name); + res.append(reinterpret_cast(&dh), sizeof(dh)); + res.append(optRData.c_str(), optRData.length()); +} + +static bool replaceEDNSClientSubnetOption(char * const packet, const size_t packetSize, uint16_t * const len, char * const oldEcsOptionStart, size_t const oldEcsOptionSize, unsigned char * const optRDLen, const string& newECSOption) +{ + assert(packet != NULL); + assert(len != NULL); + assert(oldEcsOptionStart != NULL); + assert(optRDLen != NULL); + + if (newECSOption.size() == oldEcsOptionSize) { + /* same size as the existing option */ + memcpy(oldEcsOptionStart, newECSOption.c_str(), oldEcsOptionSize); + } + else { + /* different size than the existing option */ + const unsigned int newPacketLen = *len + (newECSOption.length() - oldEcsOptionSize); + const size_t beforeOptionLen = oldEcsOptionStart - packet; + const size_t dataBehindSize = *len - beforeOptionLen - oldEcsOptionSize; + + /* check that it fits in the existing buffer */ + if (newPacketLen > packetSize) { + return false; + } + + /* fix the size of ECS Option RDLen */ + uint16_t newRDLen = (optRDLen[0] * 256) + optRDLen[1]; + newRDLen += (newECSOption.size() - oldEcsOptionSize); + optRDLen[0] = newRDLen / 256; + optRDLen[1] = newRDLen % 256; + + if (dataBehindSize > 0) { + memmove(oldEcsOptionStart, oldEcsOptionStart + oldEcsOptionSize, dataBehindSize); + } + memcpy(oldEcsOptionStart + dataBehindSize, newECSOption.c_str(), newECSOption.size()); + *len = newPacketLen; + } + + return true; +} + +/* This function looks for an OPT RR, return true if a valid one was found (even if there was no options) + and false otherwise. */ +bool parseEDNSOptions(DNSQuestion& dq) +{ + assert(dq.dh != nullptr); + assert(dq.consumed <= dq.len); + assert(dq.len <= dq.size); + + if (dq.ednsOptions != nullptr) { + return true; + } + + dq.ednsOptions = std::make_shared >(); + const char* packet = reinterpret_cast(dq.dh); + + size_t remaining = 0; + uint16_t optRDPosition; + int res = getEDNSOptionsStart(packet, dq.consumed, dq.len, &optRDPosition, &remaining); + + if (res == 0) { + res = getEDNSOptions(packet + optRDPosition, remaining, *dq.ednsOptions); + return (res == 0); + } + + return false; +} + +static bool addECSToExistingOPT(char* const packet, size_t const packetSize, uint16_t* const len, const string& newECSOption, unsigned char* optRDLen, bool* const ecsAdded) +{ + /* we need to add one EDNS0 ECS option, fixing the size of EDNS0 RDLENGTH */ + /* getEDNSOptionsStart has already checked that there is exactly one AR, + no NS and no AN */ + + /* check if the existing buffer is large enough */ + const size_t newECSOptionSize = newECSOption.size(); + if (packetSize - *len <= newECSOptionSize) { + return false; + } + + uint16_t newRDLen = (optRDLen[0] * 256) + optRDLen[1]; + newRDLen += newECSOptionSize; + optRDLen[0] = newRDLen / 256; + optRDLen[1] = newRDLen % 256; + + memcpy(packet + *len, newECSOption.c_str(), newECSOptionSize); + *len += newECSOptionSize; + *ecsAdded = true; + + return true; +} + +static bool addEDNSWithECS(char* const packet, size_t const packetSize, uint16_t* const len, const string& newECSOption, bool* const ednsAdded, bool preserveTrailingData) +{ + /* we need to add a EDNS0 RR with one EDNS0 ECS option, fixing the AR count */ + string EDNSRR; + struct dnsheader* dh = reinterpret_cast(packet); + generateOptRR(newECSOption, EDNSRR, g_EdnsUDPPayloadSize, 0, false); + + /* does it fit in the existing buffer? */ + if (packetSize - *len <= EDNSRR.size()) { + return false; + } + + uint32_t realPacketLen = getDNSPacketLength(packet, *len); + if (realPacketLen < *len && preserveTrailingData) { + size_t toMove = *len - realPacketLen; + memmove(packet + realPacketLen + EDNSRR.size(), packet + realPacketLen, toMove); + *len += EDNSRR.size(); + } + else { + *len = realPacketLen + EDNSRR.size(); + } + + uint16_t arcount = ntohs(dh->arcount); + arcount++; + dh->arcount = htons(arcount); + *ednsAdded = true; + + memcpy(packet + realPacketLen, EDNSRR.c_str(), EDNSRR.size()); + + return true; +} + +bool handleEDNSClientSubnet(char* const packet, const size_t packetSize, const unsigned int consumed, uint16_t* const len, bool* const ednsAdded, bool* const ecsAdded, bool overrideExisting, const string& newECSOption, bool preserveTrailingData) +{ + assert(packet != nullptr); + assert(len != nullptr); + assert(consumed <= (size_t) *len); + assert(ednsAdded != nullptr); + assert(ecsAdded != nullptr); + uint16_t optRDPosition = 0; + size_t remaining = 0; + + int res = getEDNSOptionsStart(packet, consumed, *len, &optRDPosition, &remaining); + + if (res != 0) { + return addEDNSWithECS(packet, packetSize, len, newECSOption, ednsAdded, preserveTrailingData); + } + + unsigned char* optRDLen = reinterpret_cast(packet) + optRDPosition; + char * ecsOptionStart = nullptr; + size_t ecsOptionSize = 0; + + res = getEDNSOption(reinterpret_cast(optRDLen), remaining, EDNSOptionCode::ECS, &ecsOptionStart, &ecsOptionSize); + + if (res == 0) { + /* there is already an ECS value */ + if (!overrideExisting) { + return true; + } + + return replaceEDNSClientSubnetOption(packet, packetSize, len, ecsOptionStart, ecsOptionSize, optRDLen, newECSOption); + } else { + /* we have an EDNS OPT RR but no existing ECS option */ + return addECSToExistingOPT(packet, packetSize, len, newECSOption, optRDLen, ecsAdded); + } + + return true; +} + +bool handleEDNSClientSubnet(DNSQuestion& dq, bool* ednsAdded, bool* ecsAdded, bool preserveTrailingData) +{ + assert(dq.remote != nullptr); + string newECSOption; + generateECSOption(dq.ecsSet ? dq.ecs.getNetwork() : *dq.remote, newECSOption, dq.ecsSet ? dq.ecs.getBits() : dq.ecsPrefixLength); + char* packet = reinterpret_cast(dq.dh); + + return handleEDNSClientSubnet(packet, dq.size, dq.consumed, &dq.len, ednsAdded, ecsAdded, dq.ecsOverride, newECSOption, preserveTrailingData); +} + +static int removeEDNSOptionFromOptions(unsigned char* optionsStart, const uint16_t optionsLen, const uint16_t optionCodeToRemove, uint16_t* newOptionsLen) +{ + unsigned char* p = optionsStart; + size_t pos = 0; + while ((pos + 4) <= optionsLen) { + unsigned char* optionBegin = p; + const uint16_t optionCode = 0x100*p[0] + p[1]; + p += sizeof(optionCode); + pos += sizeof(optionCode); + const uint16_t optionLen = 0x100*p[0] + p[1]; + p += sizeof(optionLen); + pos += sizeof(optionLen); + if ((pos + optionLen) > optionsLen) { + return EINVAL; + } + if (optionCode == optionCodeToRemove) { + if (pos + optionLen < optionsLen) { + /* move remaining options over the removed one, + if any */ + memmove(optionBegin, p + optionLen, optionsLen - (pos + optionLen)); + } + *newOptionsLen = optionsLen - (sizeof(optionCode) + sizeof(optionLen) + optionLen); + return 0; + } + p += optionLen; + pos += optionLen; + } + return ENOENT; +} + +int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove) +{ + if (*optLen < optRecordMinimumSize) { + return EINVAL; + } + const unsigned char* end = (const unsigned char*) optStart + *optLen; + unsigned char* p = (unsigned char*) optStart + 9; + unsigned char* rdLenPtr = p; + uint16_t rdLen = (0x100*p[0] + p[1]); + p += sizeof(rdLen); + if (p + rdLen != end) { + return EINVAL; + } + uint16_t newRdLen = 0; + int res = removeEDNSOptionFromOptions(p, rdLen, optionCodeToRemove, &newRdLen); + if (res != 0) { + return res; + } + *optLen -= (rdLen - newRdLen); + rdLenPtr[0] = newRdLen / 0x100; + rdLenPtr[1] = newRdLen % 0x100; + return 0; +} + +bool isEDNSOptionInOpt(const std::string& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart, uint16_t* optContentLen) +{ + if (optLen < optRecordMinimumSize) { + return false; + } + size_t p = optStart + 9; + uint16_t rdLen = (0x100*packet.at(p) + packet.at(p+1)); + p += sizeof(rdLen); + if (rdLen > (optLen - optRecordMinimumSize)) { + return false; + } + + size_t rdEnd = p + rdLen; + while ((p + 4) <= rdEnd) { + const uint16_t optionCode = 0x100*packet.at(p) + packet.at(p+1); + p += sizeof(optionCode); + const uint16_t optionLen = 0x100*packet.at(p) + packet.at(p+1); + p += sizeof(optionLen); + + if ((p + optionLen) > rdEnd) { + return false; + } + + if (optionCode == optionCodeToFind) { + if (optContentStart != nullptr) { + *optContentStart = p; + } + + if (optContentLen != nullptr) { + *optContentLen = optionLen; + } + + return true; + } + p += optionLen; + } + return false; +} + +int rewriteResponseWithoutEDNSOption(const std::string& initialPacket, const uint16_t optionCodeToSkip, vector& newContent) +{ + assert(initialPacket.size() >= sizeof(dnsheader)); + const struct dnsheader* dh = reinterpret_cast(initialPacket.data()); + + if (ntohs(dh->arcount) == 0) + return ENOENT; + + if (ntohs(dh->qdcount) == 0) + return ENOENT; + + PacketReader pr(initialPacket); + + size_t idx = 0; + DNSName rrname; + uint16_t qdcount = ntohs(dh->qdcount); + uint16_t ancount = ntohs(dh->ancount); + uint16_t nscount = ntohs(dh->nscount); + uint16_t arcount = ntohs(dh->arcount); + uint16_t rrtype; + uint16_t rrclass; + string blob; + struct dnsrecordheader ah; + + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + + DNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode); + pw.getHeader()->id=dh->id; + pw.getHeader()->qr=dh->qr; + pw.getHeader()->aa=dh->aa; + pw.getHeader()->tc=dh->tc; + pw.getHeader()->rd=dh->rd; + pw.getHeader()->ra=dh->ra; + pw.getHeader()->ad=dh->ad; + pw.getHeader()->cd=dh->cd; + pw.getHeader()->rcode=dh->rcode; + + /* consume remaining qd if any */ + if (qdcount > 1) { + for(idx = 1; idx < qdcount; idx++) { + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + (void) rrtype; + (void) rrclass; + } + } + + /* copy AN and NS */ + for (idx = 0; idx < ancount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ANSWER, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } + + for (idx = 0; idx < nscount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::AUTHORITY, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } + + /* consume AR, looking for OPT */ + for (idx = 0; idx < arcount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + if (ah.d_type != QType::OPT) { + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, true); + pr.xfrBlob(blob); + pw.xfrBlob(blob); + } else { + pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, false); + pr.xfrBlob(blob); + uint16_t rdLen = blob.length(); + removeEDNSOptionFromOptions((unsigned char*)blob.c_str(), rdLen, optionCodeToSkip, &rdLen); + /* xfrBlob(string, size) completely ignores size.. */ + if (rdLen > 0) { + blob.resize((size_t)rdLen); + pw.xfrBlob(blob); + } else { + pw.commit(); + } + } + } + pw.commit(); + + return 0; +} + +bool addEDNS(dnsheader* dh, uint16_t& len, const size_t size, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode) +{ + if (dh->arcount != 0) { + return false; + } + + std::string optRecord; + generateOptRR(std::string(), optRecord, payloadSize, ednsrcode, dnssecOK); + + if (optRecord.size() >= size || (size - optRecord.size()) < len) { + return false; + } + + char * optPtr = reinterpret_cast(dh) + len; + memcpy(optPtr, optRecord.data(), optRecord.size()); + len += optRecord.size(); + dh->arcount = htons(1); + + return true; +} + +bool addEDNSToQueryTurnedResponse(DNSQuestion& dq) +{ + uint16_t optRDPosition; + /* remaining is at least the size of the rdlen + the options if any + the following records if any */ + size_t remaining = 0; + + int res = getEDNSOptionsStart(reinterpret_cast(dq.dh), dq.consumed, dq.len, &optRDPosition, &remaining); + + if (res != 0) { + /* if the initial query did not have EDNS0, we are done */ + return true; + } + + const size_t existingOptLen = /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE + /* Z */ 2 + remaining; + if (existingOptLen >= dq.len) { + /* something is wrong, bail out */ + return false; + } + + char* optRDLen = reinterpret_cast(dq.dh) + optRDPosition; + char * optPtr = (optRDLen - (/* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE + /* Z */ 2)); + + const uint8_t* zPtr = reinterpret_cast(optPtr) + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE; + uint16_t z = 0x100 * (*zPtr) + *(zPtr + 1); + bool dnssecOK = z & EDNS_HEADER_FLAG_DO; + + /* remove the existing OPT record, and everything else that follows (any SIG or TSIG would be useless anyway) */ + dq.len -= existingOptLen; + dq.dh->arcount = 0; + + if (g_addEDNSToSelfGeneratedResponses) { + /* now we need to add a new OPT record */ + return addEDNS(dq.dh, dq.len, dq.size, dnssecOK, g_PayloadSizeSelfGenAnswers, dq.ednsRCode); + } + + /* otherwise we are just fine */ + return true; +} + +// goal in life - if you send us a reasonably normal packet, we'll get Z for you, otherwise 0 +int getEDNSZ(const DNSQuestion& dq) +try +{ + if (ntohs(dq.dh->qdcount) != 1 || dq.dh->ancount != 0 || ntohs(dq.dh->arcount) != 1 || dq.dh->nscount != 0) { + return 0; + } + + if (dq.len <= sizeof(dnsheader)) { + return 0; + } + + size_t pos = sizeof(dnsheader) + dq.consumed + DNS_TYPE_SIZE + DNS_CLASS_SIZE; + + if (dq.len <= (pos + /* root */ 1 + DNS_TYPE_SIZE + DNS_CLASS_SIZE)) { + return 0; + } + + const char* packet = reinterpret_cast(dq.dh); + + if (packet[pos] != 0) { + /* not root, so not a valid OPT record */ + return 0; + } + + pos++; + + uint16_t qtype = (reinterpret_cast(packet)[pos])*256 + reinterpret_cast(packet)[pos+1]; + pos += DNS_TYPE_SIZE; + pos += DNS_CLASS_SIZE; + + if (qtype != QType::OPT || (pos + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE + 1) >= dq.len) { + return 0; + } + + const uint8_t* z = reinterpret_cast(packet) + pos + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE; + return 0x100 * (*z) + *(z+1); +} +catch(...) +{ + return 0; +} + +bool queryHasEDNS(const DNSQuestion& dq) +{ + uint16_t optRDPosition; + size_t ecsRemaining = 0; + + int res = getEDNSOptionsStart(reinterpret_cast(dq.dh), dq.consumed, dq.len, &optRDPosition, &ecsRemaining); + if (res == 0) { + return true; + } + + return false; +} + +bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0) +{ + uint16_t optStart; + size_t optLen = 0; + bool last = false; + const char * packet = reinterpret_cast(dq.dh); + std::string packetStr(packet, dq.len); + int res = locateEDNSOptRR(packetStr, &optStart, &optLen, &last); + if (res != 0) { + // no EDNS OPT RR + return false; + } + + if (optLen < optRecordMinimumSize) { + return false; + } + + if (optStart < dq.len && packetStr.at(optStart) != 0) { + // OPT RR Name != '.' + return false; + } + + static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t) AKA RR TTL size"); + // copy out 4-byte "ttl" (really the EDNS0 record), after root label (1) + type (2) + class (2). + memcpy(&edns0, packet + optStart + 5, sizeof edns0); + return true; +} diff --git a/pdns/dnsdist-ecs.hh b/pdns/dnsdist-ecs.hh new file mode 100644 index 0000000..7675757 --- /dev/null +++ b/pdns/dnsdist-ecs.hh @@ -0,0 +1,48 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +// root label (1), type (2), class (2), ttl (4) + rdlen (2) +static const size_t optRecordMinimumSize = 11; + +extern size_t g_EdnsUDPPayloadSize; +extern uint16_t g_PayloadSizeSelfGenAnswers; + +int rewriteResponseWithoutEDNS(const std::string& initialPacket, vector& newContent); +int locateEDNSOptRR(const std::string& packet, uint16_t * optStart, size_t * optLen, bool * last); +void generateOptRR(const std::string& optRData, string& res, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK); +void generateECSOption(const ComboAddress& source, string& res, uint16_t ECSPrefixLength); +int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove); +int rewriteResponseWithoutEDNSOption(const std::string& initialPacket, const uint16_t optionCodeToSkip, vector& newContent); +int getEDNSOptionsStart(const char* packet, const size_t offset, const size_t len, uint16_t* optRDPosition, size_t * remaining); +bool isEDNSOptionInOpt(const std::string& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart = nullptr, uint16_t* optContentLen = nullptr); +bool addEDNS(dnsheader* dh, uint16_t& len, const size_t size, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode); +bool addEDNSToQueryTurnedResponse(DNSQuestion& dq); + +bool handleEDNSClientSubnet(DNSQuestion& dq, bool* ednsAdded, bool* ecsAdded, bool preserveTrailingData); +bool handleEDNSClientSubnet(char* const packet, const size_t packetSize, const unsigned int consumed, uint16_t* const len, bool* const ednsAdded, bool* const ecsAdded, bool overrideExisting, const string& newECSOption, bool preserveTrailingData); + +bool parseEDNSOptions(DNSQuestion& dq); + +int getEDNSZ(const DNSQuestion& dq); +bool queryHasEDNS(const DNSQuestion& dq); +bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0); diff --git a/pdns/dnsgram.cc b/pdns/dnsgram.cc new file mode 100644 index 0000000..34fd0ca --- /dev/null +++ b/pdns/dnsgram.cc @@ -0,0 +1,254 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define __FAVOR_BSD +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "statbag.hh" +#include "dnspcap.hh" +#include "dnsrecords.hh" +#include "dnsparser.hh" +#include +#include +#include +#include +#include +#include +#include "anadns.hh" + +#include "namespaces.hh" +#include "namespaces.hh" + +StatBag S; + +struct tm* pdns_localtime_r(const uint32_t* then, struct tm* tm) +{ + time_t t = *then; + + return localtime_r(&t, tm); +} + +int32_t g_clientQuestions, g_clientResponses, g_serverQuestions, g_serverResponses, g_skipped; +struct pdns_timeval g_lastanswerTime, g_lastquestionTime; +void makeReport(const struct pdns_timeval& tv) +{ + int64_t clientdiff = g_clientQuestions - g_clientResponses; + int64_t serverdiff = g_serverQuestions - g_serverResponses; + + if(clientdiff > 1 && clientdiff > 0.02*g_clientQuestions) { + char tmp[80]; + struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm); + strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm); + + cout << tmp << ": Resolver dropped too many questions (" + << g_clientQuestions <<" vs " << g_clientResponses << "), diff: " < 1 && serverdiff > 0.02*g_serverQuestions) { + char tmp[80]; + struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm); + strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm); + + cout << tmp << ": Auth server dropped too many questions (" + << g_serverQuestions <<" vs " << g_serverResponses << "), diff: " < > queries_t; + queries_t questions, answers; + + // unsigned int count = 50000; + + map, int> counts; + + map rdqcounts, rdacounts; + + while(pr.getUDPPacket()) { + if((ntohs(pr.d_udp->uh_dport)==5300 || ntohs(pr.d_udp->uh_sport)==5300 || + ntohs(pr.d_udp->uh_dport)==53 || ntohs(pr.d_udp->uh_sport)==53) && + pr.d_len > 12) { + try { + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); + + if(lastreport.tv_sec == 0) { + lastreport = pr.d_pheader.ts; + } + + if(mdp.d_header.rd && !mdp.d_header.qr) { + rdqcounts[pr.d_pheader.ts.tv_sec + 0.01*(pr.d_pheader.ts.tv_usec/10000)]++; + g_lastquestionTime=pr.d_pheader.ts; + g_clientQuestions++; + totalQueries++; + counts[make_pair(mdp.d_qname, mdp.d_qtype)]++; + questions.insert(make_pair(mdp.d_qname, mdp.d_qtype)); + } + else if(mdp.d_header.rd && mdp.d_header.qr) { + rdacounts[pr.d_pheader.ts.tv_sec + 0.01*(pr.d_pheader.ts.tv_usec/10000)]++; + g_lastanswerTime=pr.d_pheader.ts; + g_clientResponses++; + answers.insert(make_pair(mdp.d_qname, mdp.d_qtype)); + } + else if(!mdp.d_header.rd && !mdp.d_header.qr) { + g_lastquestionTime=pr.d_pheader.ts; + g_serverQuestions++; + counts[make_pair(mdp.d_qname, mdp.d_qtype)]++; + questions.insert(make_pair(mdp.d_qname, mdp.d_qtype)); + totalQueries++; + } + else if(!mdp.d_header.rd && mdp.d_header.qr) { + answers.insert(make_pair(mdp.d_qname, mdp.d_qtype)); + g_serverResponses++; + } + + if(pr.d_pheader.ts.tv_sec - lastreport.tv_sec >= 1) { + makeReport(pr.d_pheader.ts); + lastreport = pr.d_pheader.ts; + } + } + catch(const MOADNSException &mde) { + // cerr<<"error parsing packet: "<> splot; + + for(auto& a : rdqcounts) { + splot[a.first].first = a.second; + } + for(auto& a : rdacounts) { + splot[a.first].second = a.second; + } + + cerr<<"Writing out sub-second rd query/response stats to ./rdqaplot"< diff_t; + diff_t diff; + set_difference(questions.begin(), questions.end(), answers.begin(), answers.end(), back_inserter(diff)); + cerr<first << "\t" << DNSRecordContent::NumberToType(i->second) << "\t"<< counts[make_pair(i->first, i->second)]<<"\n"; + } + + diff.clear(); + + set_difference(answers.begin(), answers.end(), questions.begin(), questions.end(), back_inserter(diff)); + cerr<first << "\t" <second) << "\t" << counts[make_pair(i->first, i->second)]<<"\n"; + } + } +} +catch(std::exception& e) +{ + cerr<<"Fatal: "< +#include +#include +#include +#include +#include "dnsname.hh" +#include "namespaces.hh" + +namespace { +void appendSplit(vector& ret, string& segment, char c) +{ + if(segment.size()>254) { + ret.push_back(segment); + segment.clear(); + } + segment.append(1, c); +} + +} + +vector segmentDNSText(const string& input ) +{ + // cerr<<"segmentDNSText("< ret; + + +#line 98 "dnslabeltext.cc" + { + cs = dnstext_start; + } + +#line 103 "dnslabeltext.cc" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const unsigned char *_keys; + + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _dnstext_trans_keys + _dnstext_key_offsets[cs]; + _trans = _dnstext_index_offsets[cs]; + + _klen = _dnstext_single_lengths[cs]; + if ( _klen > 0 ) { + const unsigned char *_lower = _keys; + const unsigned char *_mid; + const unsigned char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _dnstext_range_lengths[cs]; + if ( _klen > 0 ) { + const unsigned char *_lower = _keys; + const unsigned char *_mid; + const unsigned char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + cs = _dnstext_trans_targs[_trans]; + + if ( _dnstext_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _dnstext_actions + _dnstext_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 0: +#line 40 "dnslabeltext.rl" + { + ret.push_back(segment); + segment.clear(); + } + break; + case 1: +#line 44 "dnslabeltext.rl" + { + segment.clear(); + } + break; + case 2: +#line 48 "dnslabeltext.rl" + { + char c = *p; + appendSplit(ret, segment, c); + } + break; + case 3: +#line 52 "dnslabeltext.rl" + { + char c = *p; + val *= 10; + val += c-'0'; + + } + break; + case 4: +#line 58 "dnslabeltext.rl" + { + appendSplit(ret, segment, val); + val=0; + } + break; + case 5: +#line 63 "dnslabeltext.rl" + { + appendSplit(ret, segment, *(p)); + } + break; +#line 218 "dnslabeltext.cc" + } + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + const char *__acts = _dnstext_actions + _dnstext_eof_actions[cs]; + unsigned int __nacts = (unsigned int) *__acts++; + while ( __nacts-- > 0 ) { + switch ( *__acts++ ) { + case 0: +#line 40 "dnslabeltext.rl" + { + ret.push_back(segment); + segment.clear(); + } + break; +#line 241 "dnslabeltext.cc" + } + } + } + + _out: {} + } + +#line 76 "dnslabeltext.rl" + + + if ( cs < dnstext_first_final ) { + throw runtime_error("Unable to parse DNS TXT '"+input+"'"); + } + + return ret; +}; + + +DNSName::string_t segmentDNSNameRaw(const char* realinput) +{ + +#line 263 "dnslabeltext.cc" +static const char _dnsnameraw_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 1, + 3, 1, 4, 1, 5, 2, 1, 5, + 2, 4, 0, 2, 4, 5 +}; + +static const char _dnsnameraw_key_offsets[] = { + 0, 0, 2, 4, 6, 8, 10, 12 +}; + +static const unsigned char _dnsnameraw_trans_keys[] = { + 46u, 92u, 48u, 57u, 48u, 57u, 48u, 57u, + 46u, 92u, 46u, 92u, 46u, 92u, 0 +}; + +static const char _dnsnameraw_single_lengths[] = { + 0, 2, 0, 0, 0, 2, 2, 2 +}; + +static const char _dnsnameraw_range_lengths[] = { + 0, 0, 1, 1, 1, 0, 0, 0 +}; + +static const char _dnsnameraw_index_offsets[] = { + 0, 0, 3, 5, 7, 9, 12, 15 +}; + +static const char _dnsnameraw_trans_targs[] = { + 0, 2, 5, 3, 5, 4, 0, 7, + 0, 6, 2, 5, 0, 2, 5, 6, + 2, 5, 0 +}; + +static const char _dnsnameraw_trans_actions[] = { + 0, 3, 13, 7, 5, 7, 0, 7, + 0, 1, 0, 11, 0, 3, 13, 16, + 9, 19, 0 +}; + +static const char _dnsnameraw_eof_actions[] = { + 0, 0, 0, 0, 0, 1, 0, 16 +}; + +static const int dnsnameraw_start = 1; +static const int dnsnameraw_first_final = 5; +static const int dnsnameraw_error = 0; + +static const int dnsnameraw_en_main = 1; + + +#line 92 "dnslabeltext.rl" + + (void)dnsnameraw_error; // silence warnings + (void)dnsnameraw_en_main; + + DNSName::string_t ret; + + if(!*realinput || *realinput == '.') { + ret.append(1, (char)0); + return ret; + } + + unsigned int inputlen=strlen(realinput); + ret.reserve(inputlen+1); + + const char *p = realinput, *pe = realinput + inputlen; + const char* eof = pe; + int cs; + char val = 0; + char labellen=0; + unsigned int lenpos=0; + +#line 336 "dnslabeltext.cc" + { + cs = dnsnameraw_start; + } + +#line 341 "dnslabeltext.cc" + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const unsigned char *_keys; + + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _dnsnameraw_trans_keys + _dnsnameraw_key_offsets[cs]; + _trans = _dnsnameraw_index_offsets[cs]; + + _klen = _dnsnameraw_single_lengths[cs]; + if ( _klen > 0 ) { + const unsigned char *_lower = _keys; + const unsigned char *_mid; + const unsigned char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) + _upper = _mid - 1; + else if ( (*p) > *_mid ) + _lower = _mid + 1; + else { + _trans += (unsigned int)(_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _dnsnameraw_range_lengths[cs]; + if ( _klen > 0 ) { + const unsigned char *_lower = _keys; + const unsigned char *_mid; + const unsigned char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) + _upper = _mid - 2; + else if ( (*p) > _mid[1] ) + _lower = _mid + 2; + else { + _trans += (unsigned int)((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } + +_match: + cs = _dnsnameraw_trans_targs[_trans]; + + if ( _dnsnameraw_trans_actions[_trans] == 0 ) + goto _again; + + _acts = _dnsnameraw_actions + _dnsnameraw_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) + { + switch ( *_acts++ ) + { + case 0: +#line 113 "dnslabeltext.rl" + { + if (labellen < 0 || labellen > 63) { + throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen)); + } + ret[lenpos]=labellen; + labellen=0; + } + break; + case 1: +#line 120 "dnslabeltext.rl" + { + lenpos=ret.size(); + ret.append(1, (char)0); + labellen=0; + } + break; + case 2: +#line 126 "dnslabeltext.rl" + { + char c = *p; + ret.append(1, c); + labellen++; + } + break; + case 3: +#line 131 "dnslabeltext.rl" + { + char c = *p; + val *= 10; + val += c-'0'; + } + break; + case 4: +#line 136 "dnslabeltext.rl" + { + ret.append(1, val); + labellen++; + val=0; + } + break; + case 5: +#line 142 "dnslabeltext.rl" + { + ret.append(1, *(p)); + labellen++; + } + break; +#line 463 "dnslabeltext.cc" + } + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + const char *__acts = _dnsnameraw_actions + _dnsnameraw_eof_actions[cs]; + unsigned int __nacts = (unsigned int) *__acts++; + while ( __nacts-- > 0 ) { + switch ( *__acts++ ) { + case 0: +#line 113 "dnslabeltext.rl" + { + if (labellen < 0 || labellen > 63) { + throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen)); + } + ret[lenpos]=labellen; + labellen=0; + } + break; + case 4: +#line 136 "dnslabeltext.rl" + { + ret.append(1, val); + labellen++; + val=0; + } + break; +#line 497 "dnslabeltext.cc" + } + } + } + + _out: {} + } + +#line 163 "dnslabeltext.rl" + + + if ( cs < dnsnameraw_first_final ) { + throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs)); + } + ret.append(1, (char)0); + return ret; +}; + + + +#if 0 +int main() +{ + //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\""; + char blah[]="\"v=spf1 ip4:67.106.74.128/25 ip4:63.138.42.224/28 ip4:65.204.46.224/27 \\013\\010ip4:66.104.217.176/28 \\013\\010ip4:209.48.147.0/27 ~all\""; + //char blah[]="\"abc \\097\\098 def\""; + printf("Input: '%s'\n", blah); + vector res=dnstext(blah); + cerr< +#include +#include +#include +#include +#include "dnsname.hh" +#include "namespaces.hh" + +namespace { +void appendSplit(vector& ret, string& segment, char c) +{ + if(segment.size()>254) { + ret.push_back(segment); + segment.clear(); + } + segment.append(1, c); +} + +} + +vector segmentDNSText(const string& input ) +{ + // cerr<<"segmentDNSText("< ret; + + %%{ + action segmentEnd { + ret.push_back(segment); + segment.clear(); + } + action segmentBegin { + segment.clear(); + } + + action reportEscaped { + char c = *fpc; + appendSplit(ret, segment, c); + } + action reportEscapedNumber { + char c = *fpc; + val *= 10; + val += c-'0'; + + } + action doneEscapedNumber { + appendSplit(ret, segment, val); + val=0; + } + + action reportPlain { + appendSplit(ret, segment, *(fpc)); + } + + escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber)); + plain = ((extend-'\\'-'"')|'\n'|'\t') $ reportPlain; + txtElement = escaped | plain; + + main := (('"' txtElement* '"' space?) >segmentBegin %segmentEnd)+; + + # Initialize and execute. + write init; + write exec; + }%% + + if ( cs < dnstext_first_final ) { + throw runtime_error("Unable to parse DNS TXT '"+input+"'"); + } + + return ret; +}; + + +DNSName::string_t segmentDNSNameRaw(const char* realinput) +{ +%%{ + machine dnsnameraw; + write data; + alphtype unsigned char; +}%% + (void)dnsnameraw_error; // silence warnings + (void)dnsnameraw_en_main; + + DNSName::string_t ret; + + if(!*realinput || *realinput == '.') { + ret.append(1, (char)0); + return ret; + } + + unsigned int inputlen=strlen(realinput); + ret.reserve(inputlen+1); + + const char *p = realinput, *pe = realinput + inputlen; + const char* eof = pe; + int cs; + char val = 0; + char labellen=0; + unsigned int lenpos=0; + %%{ + action labelEnd { + if (labellen < 0 || labellen > 63) { + throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen)); + } + ret[lenpos]=labellen; + labellen=0; + } + action labelBegin { + lenpos=ret.size(); + ret.append(1, (char)0); + labellen=0; + } + + action reportEscaped { + char c = *fpc; + ret.append(1, c); + labellen++; + } + action reportEscapedNumber { + char c = *fpc; + val *= 10; + val += c-'0'; + } + action doneEscapedNumber { + ret.append(1, val); + labellen++; + val=0; + } + + action reportPlain { + ret.append(1, *(fpc)); + labellen++; + } + + escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber)); + plain = (extend-'\\'-'.') $ reportPlain; + labelElement = escaped | plain; + + label = labelElement+ >labelBegin %labelEnd; + + main:= label ('.' label )* '.'?; + + #main := labelElement((labelElement+ '.') >labelBegin %labelEnd)+; + + # label = (plain | escaped | escdecb)+ >label_init %label_fin; + # dnsname := '.'? label ('.' label >label_sep)* '.'?; + + # Initialize and execute. + write init; + write exec; + }%% + + if ( cs < dnsnameraw_first_final ) { + throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs)); + } + ret.append(1, (char)0); + return ret; +}; + + + +#if 0 +int main() +{ + //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\""; + char blah[]="\"v=spf1 ip4:67.106.74.128/25 ip4:63.138.42.224/28 ip4:65.204.46.224/27 \\013\\010ip4:66.104.217.176/28 \\013\\010ip4:209.48.147.0/27 ~all\""; + //char blah[]="\"abc \\097\\098 def\""; + printf("Input: '%s'\n", blah); + vector res=dnstext(blah); + cerr< +#include + +#include "dnswriter.hh" +#include "misc.hh" + +#include + +const DNSName g_rootdnsname("."), g_wildcarddnsname("*"); + +/* raw storage + in DNS label format, with trailing 0. W/o trailing 0, we are 'empty' + www.powerdns.com = 3www8powerdns3com0 +*/ + +std::ostream & operator<<(std::ostream &os, const DNSName& d) +{ + return os < 63) + throw std::range_error("label too long to append"); + + if(iter-pbegin > 254) // reserve two bytes, one for length and one for the root label + throw std::range_error("name too long to append"); + + d_storage[lenpos]=labellen; + } + d_storage.append(1, (char)0); + } + else { + d_storage=segmentDNSNameRaw(p); + if(d_storage.size() > 255) { + throw std::range_error("name too long"); + } + } + } +} + + +DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, uint16_t minOffset) +{ + if (offset >= len) + throw std::range_error("Trying to read past the end of the buffer ("+std::to_string(offset)+ " >= "+std::to_string(len)+")"); + + if(!uncompress) { + if(const void * fnd=memchr(pos+offset, 0, len-offset)) { + d_storage.reserve(2+(const char*)fnd-(pos+offset)); + } + } + + packetParser(pos, len, offset, uncompress, qtype, qclass, consumed, 0, minOffset); +} + +// this should be the __only__ dns name parser in PowerDNS. +void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, int depth, uint16_t minOffset) +{ + const unsigned char* pos=(const unsigned char*)qpos; + unsigned char labellen; + const unsigned char *opos = pos; + + if (offset >= len) + throw std::range_error("Trying to read past the end of the buffer ("+std::to_string(offset)+ " >= "+std::to_string(len)+")"); + if (offset < (int) minOffset) + throw std::range_error("Trying to read before the beginning of the buffer ("+std::to_string(offset)+ " < "+std::to_string(minOffset)+")"); + + const unsigned char* end = pos + len; + pos += offset; + while((labellen=*pos++) && pos < end) { // "scan and copy" + if(labellen >= 0xc0) { + if(!uncompress) + throw std::range_error("Found compressed label, instructed not to follow"); + + labellen &= (~0xc0); + int newpos = (labellen << 8) + *(const unsigned char*)pos; + + if(newpos < offset) { + if(newpos < (int) minOffset) + throw std::range_error("Invalid label position during decompression ("+std::to_string(newpos)+ " < "+std::to_string(minOffset)+")"); + if (++depth > 100) + throw std::range_error("Abort label decompression after 100 redirects"); + packetParser((const char*)opos, len, newpos, true, 0, 0, 0, depth, minOffset); + } else + throw std::range_error("Found a forward reference during label decompression"); + pos++; + break; + } else if(labellen & 0xc0) { + throw std::range_error("Found an invalid label length in qname (only one of the first two bits is set)"); + } + if (pos + labellen < end) { + appendRawLabel((const char*)pos, labellen); + } + else + throw std::range_error("Found an invalid label length in qname"); + pos+=labellen; + } + if(d_storage.empty()) + d_storage.append(1, (char)0); // we just parsed the root + if(consumed) + *consumed = pos - opos - offset; + if(qtype) { + if (pos + 2 > end) { + throw std::range_error("Trying to read qtype past the end of the buffer ("+std::to_string((pos - opos) + 2)+ " > "+std::to_string(len)+")"); + } + *qtype=(*(const unsigned char*)pos)*256 + *((const unsigned char*)pos+1); + } + pos+=2; + if(qclass) { + if (pos + 2 > end) { + throw std::range_error("Trying to read qclass past the end of the buffer ("+std::to_string((pos - opos) + 2)+ " > "+std::to_string(len)+")"); + } + *qclass=(*(const unsigned char*)pos)*256 + *((const unsigned char*)pos+1); + } +} + +std::string DNSName::toString(const std::string& separator, const bool trailing) const +{ + if (empty()) { + throw std::out_of_range("Attempt to print an unset dnsname"); + } + + if(isRoot()) + return trailing ? separator : ""; + + std::string ret; + ret.reserve(d_storage.size()); + + { + // iterate over the raw labels + const char* p = d_storage.c_str(); + const char* end = p + d_storage.size(); + + while (p < end && *p) { + ret += escapeLabel(p + 1, static_cast(*p)) + separator; + p += *p + 1; + } + } + if (!trailing) { + ret.resize(ret.size() - separator.size()); + } + return ret; +} + +std::string DNSName::toLogString() const +{ + if (empty()) { + return "(empty)"; + } + + return toStringRootDot(); +} + +std::string DNSName::toDNSString() const +{ + if (empty()) + throw std::out_of_range("Attempt to DNSString an unset dnsname"); + + return std::string(d_storage.c_str(), d_storage.length()); +} + +std::string DNSName::toDNSStringLC() const +{ + return toLower(toDNSString()); // label lengths are always < 'A' +} + +/** + * Get the length of the DNSName on the wire + * + * @return the total wirelength of the DNSName + */ +size_t DNSName::wirelength() const { + return d_storage.length(); +} + +// Are WE part of parent +bool DNSName::isPartOf(const DNSName& parent) const +{ + if(parent.empty() || empty()) + throw std::out_of_range("empty dnsnames aren't part of anything"); + + if(parent.d_storage.size() > d_storage.size()) + return false; + + // this is slightly complicated since we can't start from the end, since we can't see where a label begins/ends then + for(auto us=d_storage.cbegin(); us(distance) < parent.d_storage.size()) { + break; + } + if (static_cast(distance) == parent.d_storage.size()) { + auto p = parent.d_storage.cbegin(); + for(; us != d_storage.cend(); ++us, ++p) { + if(dns_tolower(*p) != dns_tolower(*us)) + return false; + } + return true; + } + if (*us < 0) { + throw std::out_of_range("negative label length in dnsname"); + } + } + return false; +} + +DNSName DNSName::makeRelative(const DNSName& zone) const +{ + DNSName ret(*this); + ret.makeUsRelative(zone); + return ret.empty() ? zone : ret; // HACK FIXME400 +} +void DNSName::makeUsRelative(const DNSName& zone) +{ + if (isPartOf(zone)) { + d_storage.erase(d_storage.size()-zone.d_storage.size()); + d_storage.append(1, (char)0); // put back the trailing 0 + } + else + clear(); +} + +DNSName DNSName::getCommonLabels(const DNSName& other) const +{ + DNSName result; + + const std::vector ours = getRawLabels(); + const std::vector others = other.getRawLabels(); + + for (size_t pos = 0; ours.size() > pos && others.size() > pos; pos++) { + const std::string& ourLabel = ours.at(ours.size() - pos - 1); + const std::string& otherLabel = others.at(others.size() - pos - 1); + + if (!pdns_iequals(ourLabel, otherLabel)) { + break; + } + + result.prependRawLabel(ourLabel); + } + + return result; +} + +DNSName DNSName::labelReverse() const +{ + DNSName ret; + + if(isRoot()) + return *this; // we don't create the root automatically below + + if (!empty()) { + vector l=getRawLabels(); + while(!l.empty()) { + ret.appendRawLabel(l.back()); + l.pop_back(); + } + } + return ret; +} + +void DNSName::appendRawLabel(const std::string& label) +{ + appendRawLabel(label.c_str(), label.length()); +} + +void DNSName::appendRawLabel(const char* start, unsigned int length) +{ + if(length==0) + throw std::range_error("no such thing as an empty label to append"); + if(length > 63) + throw std::range_error("label too long to append"); + if(d_storage.size() + length > 254) // reserve one byte for the label length + throw std::range_error("name too long to append"); + + if(d_storage.empty()) { + d_storage.append(1, (char)length); + } + else { + *d_storage.rbegin()=(char)length; + } + d_storage.append(start, length); + d_storage.append(1, (char)0); +} + +void DNSName::prependRawLabel(const std::string& label) +{ + if(label.empty()) + throw std::range_error("no such thing as an empty label to prepend"); + if(label.size() > 63) + throw std::range_error("label too long to prepend"); + if(d_storage.size() + label.size() > 254) // reserve one byte for the label length + throw std::range_error("name too long to prepend"); + + if(d_storage.empty()) + d_storage.append(1, (char)0); + + string_t prep(1, (char)label.size()); + prep.append(label.c_str(), label.size()); + d_storage = prep+d_storage; +} + +bool DNSName::slowCanonCompare(const DNSName& rhs) const +{ + auto ours=getRawLabels(), rhsLabels = rhs.getRawLabels(); + return std::lexicographical_compare(ours.rbegin(), ours.rend(), rhsLabels.rbegin(), rhsLabels.rend(), CIStringCompare()); +} + +vector DNSName::getRawLabels() const +{ + vector ret; + ret.reserve(countLabels()); + // 3www4ds9a2nl0 + for(const unsigned char* p = (const unsigned char*) d_storage.c_str(); p < ((const unsigned char*) d_storage.c_str()) + d_storage.size() && *p; p+=*p+1) { + ret.push_back({(const char*)p+1, (size_t)*p}); // XXX FIXME + } + return ret; +} + +std::string DNSName::getRawLabel(unsigned int pos) const +{ + unsigned int currentPos = 0; + for(const unsigned char* p = (const unsigned char*) d_storage.c_str(); p < ((const unsigned char*) d_storage.c_str()) + d_storage.size() && *p; p+=*p+1, currentPos++) { + if (currentPos == pos) { + return std::string((const char*)p+1, (size_t)*p); + } + } + + throw std::out_of_range("trying to get label at position "+std::to_string(pos)+" of a DNSName that only has "+std::to_string(currentPos)+" labels"); +} + +DNSName DNSName::getLastLabel() const +{ + DNSName ret(*this); + ret.trimToLabels(1); + return ret; +} + +bool DNSName::chopOff() +{ + if(d_storage.empty() || d_storage[0]==0) + return false; + d_storage.erase(0, (unsigned int)d_storage[0]+1); + return true; +} + +bool DNSName::isWildcard() const +{ + if(d_storage.size() < 2) + return false; + auto p = d_storage.begin(); + return (*p == 0x01 && *++p == '*'); +} + +/* + * Returns true if the DNSName is a valid RFC 1123 hostname, this function uses + * a regex on the string, so it is probably best not used when speed is essential. + */ +bool DNSName::isHostname() const +{ + static Regex hostNameRegex = Regex("^(([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)\\.)+$"); + return hostNameRegex.match(this->toString()); +} + +unsigned int DNSName::countLabels() const +{ + unsigned int count=0; + const unsigned char* p = reinterpret_cast(d_storage.c_str()); + const unsigned char* end = reinterpret_cast(p + d_storage.size()); + + while (p < end && *p) { + ++count; + p += *p + 1; + } + return count; +} + +void DNSName::trimToLabels(unsigned int to) +{ + while(countLabels() > to && chopOff()) + ; +} + + +size_t hash_value(DNSName const& d) +{ + return d.hash(); +} + +string DNSName::escapeLabel(const std::string& label) +{ + return escapeLabel(label.c_str(), label.size()); +} + +string DNSName::escapeLabel(const char* orig, size_t len) +{ + std::string ret; + size_t pos = 0; + + ret.reserve(len); + while (pos < len) { + auto p = static_cast(orig[pos]); + if(p=='.') + ret+="\\."; + else if(p=='\\') + ret+="\\\\"; + else if(p > 0x20 && p < 0x7f) + ret.append(1, (char)p); + else { + ret+="\\" + (boost::format("%03d") % (unsigned int)p).str(); + } + ++pos; + } + return ret; +} diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh new file mode 100644 index 0000000..ea540ce --- /dev/null +++ b/pdns/dnsname.hh @@ -0,0 +1,469 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// it crashes on OSX and doesn't compile on OpenBSD +#if BOOST_VERSION >= 105300 && ! defined( __APPLE__ ) && ! defined(__OpenBSD__) +#include +#endif + +#include "ascii.hh" + +uint32_t burtleCI(const unsigned char* k, uint32_t length, uint32_t init); + +// #include "dns.hh" +// #include "logger.hh" + +//#include + +/* Quest in life: + accept escaped ascii presentations of DNS names and store them "natively" + accept a DNS packet with an offset, and extract a DNS name from it + build up DNSNames with prepend and append of 'raw' unescaped labels + + Be able to turn them into ASCII and "DNS name in a packet" again on request + + Provide some common operators for comparison, detection of being part of another domain + + NOTE: For now, everything MUST be . terminated, otherwise it is an error +*/ + +class DNSName +{ +public: + DNSName() {} //!< Constructs an *empty* DNSName, NOT the root! + explicit DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation + explicit DNSName(const std::string& str) : DNSName(str.c_str()) {}; //!< Constructs from a human formatted, escaped presentation + DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0, uint16_t minOffset=0); //!< Construct from a DNS Packet, taking the first question if offset=12 + + bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name? + inline bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) - empty compares to empty + bool operator!=(const DNSName& other) const { return !(*this == other); } + + std::string toString(const std::string& separator=".", const bool trailing=true) const; //!< Our human-friendly, escaped, representation + std::string toLogString() const; //!< like plain toString, but returns (empty) on empty names + std::string toStringNoDot() const { return toString(".", false); } + std::string toStringRootDot() const { if(isRoot()) return "."; else return toString(".", false); } + std::string toDNSString() const; //!< Our representation in DNS native format + std::string toDNSStringLC() const; //!< Our representation in DNS native format, lower cased + void appendRawLabel(const std::string& str); //!< Append this unescaped label + void appendRawLabel(const char* start, unsigned int length); //!< Append this unescaped label + void prependRawLabel(const std::string& str); //!< Prepend this unescaped label + std::vector getRawLabels() const; //!< Individual raw unescaped labels + std::string getRawLabel(unsigned int pos) const; //!< Get the specified raw unescaped label + DNSName getLastLabel() const; //!< Get the DNSName of the last label + bool chopOff(); //!< Turn www.powerdns.com. into powerdns.com., returns false for . + DNSName makeRelative(const DNSName& zone) const; + DNSName makeLowerCase() const + { + DNSName ret(*this); + ret.makeUsLowerCase(); + return ret; + } + void makeUsLowerCase() + { + for(auto & c : d_storage) { + c=dns_tolower(c); + } + } + void makeUsRelative(const DNSName& zone); + DNSName getCommonLabels(const DNSName& other) const; //!< Return the list of common labels from the top, for example 'c.d' for 'a.b.c.d' and 'x.y.c.d' + DNSName labelReverse() const; + bool isWildcard() const; + bool isHostname() const; + unsigned int countLabels() const; + size_t wirelength() const; //!< Number of total bytes in the name + bool empty() const { return d_storage.empty(); } + bool isRoot() const { return d_storage.size()==1 && d_storage[0]==0; } + void clear() { d_storage.clear(); } + void trimToLabels(unsigned int); + size_t hash(size_t init=0) const + { + return burtleCI((const unsigned char*)d_storage.c_str(), d_storage.size(), init); + } + DNSName& operator+=(const DNSName& rhs) + { + if(d_storage.size() + rhs.d_storage.size() > 256) // one extra byte for the second root label + throw std::range_error("name too long"); + if(rhs.empty()) + return *this; + + if(d_storage.empty()) + d_storage+=rhs.d_storage; + else + d_storage.replace(d_storage.length()-1, rhs.d_storage.length(), rhs.d_storage); + + return *this; + } + + bool operator<(const DNSName& rhs) const // this delivers _some_ kind of ordering, but not one useful in a DNS context. Really fast though. + { + return std::lexicographical_compare(d_storage.rbegin(), d_storage.rend(), + rhs.d_storage.rbegin(), rhs.d_storage.rend(), + [](const unsigned char& a, const unsigned char& b) { + return dns_tolower(a) < dns_tolower(b); + }); // note that this is case insensitive, including on the label lengths + } + + inline bool canonCompare(const DNSName& rhs) const; + bool slowCanonCompare(const DNSName& rhs) const; + +#if BOOST_VERSION >= 105300 && ! defined( __APPLE__ ) && ! defined(__OpenBSD__) + typedef boost::container::string string_t; +#else + typedef std::string string_t; +#endif + const string_t& getStorage() const { + return d_storage; + } +private: + string_t d_storage; + + void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, int depth, uint16_t minOffset); + static std::string escapeLabel(const std::string& orig); + static std::string escapeLabel(const char* orig, size_t len); + static std::string unescapeLabel(const std::string& orig); +}; + +size_t hash_value(DNSName const& d); + + +inline bool DNSName::canonCompare(const DNSName& rhs) const +{ + // 01234567890abcd + // us: 1a3www4ds9a2nl + // rhs: 3www6online3com + // to compare, we start at the back, is nl < com? no -> done + // + // 0,2,6,a + // 0,4,a + + uint8_t ourpos[64], rhspos[64]; + uint8_t ourcount=0, rhscount=0; + //cout<<"Asked to compare "< +{ + bool operator()(const DNSName&a, const DNSName& b) const + { + return a.canonCompare(b); + } +}; + +inline DNSName operator+(const DNSName& lhs, const DNSName& rhs) +{ + DNSName ret=lhs; + ret += rhs; + return ret; +} + +template +struct SuffixMatchTree +{ + SuffixMatchTree(const std::string& name="", bool endNode_=false) : d_name(name), endNode(endNode_) + {} + + SuffixMatchTree(const SuffixMatchTree& rhs): d_name(rhs.d_name), children(rhs.children), endNode(rhs.endNode) + { + if (endNode) { + d_value = rhs.d_value; + } + } + std::string d_name; + mutable std::set children; + mutable bool endNode; + mutable T d_value; + bool operator<(const SuffixMatchTree& rhs) const + { + return strcasecmp(d_name.c_str(), rhs.d_name.c_str()) < 0; + } + typedef SuffixMatchTree value_type; + + template + void visit(const V& v) const { + for(const auto& c : children) + c.visit(v); + if(endNode) + v(*this); + } + + void add(const DNSName& name, const T& t) + { + add(name.getRawLabels(), t); + } + + void add(std::vector labels, const T& value) const + { + if(labels.empty()) { // this allows insertion of the root + endNode=true; + d_value=value; + } + else if(labels.size()==1) { + auto res=children.emplace(*labels.begin(), true); + if(!res.second) { + // we might already have had the node as an + // intermediary one, but it's now an end node + if(!res.first->endNode) { + res.first->endNode = true; + } + } + res.first->d_value = value; + } + else { + auto res=children.emplace(*labels.rbegin(), false); + labels.pop_back(); + res.first->add(labels, value); + } + } + + void remove(const DNSName &name) const + { + remove(name.getRawLabels()); + } + + /* Removes the node at `labels`, also make sure that no empty + * children will be left behind in memory + */ + void remove(std::vector labels) const + { + SuffixMatchTree smt(*labels.rbegin()); + auto child = children.find(smt); + if (child == children.end()) { + // No subnode found, we're done + return; + } + + // We have found a child + labels.pop_back(); + if (labels.empty()) { + // The child is no longer an endnode + child->endNode = false; + + // If the child has no further children, just remove it from the set. + if (child->children.empty()) { + children.erase(child); + } + return; + } + + // We are not at the end, let the child figure out what to do + child->remove(labels); + } + + T* lookup(const DNSName& name) const + { + if(children.empty()) { // speed up empty set + if(endNode) + return &d_value; + return 0; + } + return lookup(name.getRawLabels()); + } + + T* lookup(std::vector labels) const + { + if(labels.empty()) { // optimization + if(endNode) + return &d_value; + return 0; + } + + SuffixMatchTree smn(*labels.rbegin()); + auto child = children.find(smn); + if(child == children.end()) { + if(endNode) + return &d_value; + return 0; + } + labels.pop_back(); + return child->lookup(labels); + } + + // Returns all end-nodes, fully qualified (not as separate labels) + std::vector getNodes() const { + std::vector ret; + if (endNode) { + ret.push_back(DNSName(d_name)); + } + for (const auto& child : children) { + auto nodes = child.getNodes(); + for (const auto &node: nodes) { + ret.push_back(node + DNSName(d_name)); + } + } + return ret; + } +}; + +/* Quest in life: serve as a rapid block list. If you add a DNSName to a root SuffixMatchNode, + anything part of that domain will return 'true' in check */ +struct SuffixMatchNode +{ + public: + SuffixMatchNode() + {} + SuffixMatchTree d_tree; + + void add(const DNSName& dnsname) + { + d_tree.add(dnsname, true); + d_nodes.insert(dnsname); + } + + void add(std::vector labels) + { + d_tree.add(labels, true); + DNSName tmp; + while (!labels.empty()) { + tmp.appendRawLabel(labels.back()); + labels.pop_back(); // This is safe because we have a copy of labels + } + d_nodes.insert(tmp); + } + + void remove(const DNSName& name) + { + d_tree.remove(name); + d_nodes.erase(name); + } + + void remove(std::vector labels) + { + d_tree.remove(labels); + DNSName tmp; + while (!labels.empty()) { + tmp.appendRawLabel(labels.back()); + labels.pop_back(); // This is safe because we have a copy of labels + } + d_nodes.erase(tmp); + } + + bool check(const DNSName& dnsname) const + { + return d_tree.lookup(dnsname) != nullptr; + } + + std::string toString() const + { + std::string ret; + bool first = true; + for (const auto& n : d_nodes) { + if (!first) { + ret += ", "; + } + first = false; + ret += n.toString(); + } + return ret; + } + + private: + mutable std::set d_nodes; // Only used for string generation +}; + +std::ostream & operator<<(std::ostream &os, const DNSName& d); +namespace std { + template <> + struct hash { + size_t operator () (const DNSName& dn) const { return dn.hash(0); } + }; +} + +DNSName::string_t segmentDNSNameRaw(const char* input); // from ragel +bool DNSName::operator==(const DNSName& rhs) const +{ + if(rhs.empty() != empty() || rhs.d_storage.size() != d_storage.size()) + return false; + + auto us = d_storage.cbegin(); + auto p = rhs.d_storage.cbegin(); + for(; us != d_storage.cend() && p != rhs.d_storage.cend(); ++us, ++p) { + if(dns_tolower(*p) != dns_tolower(*us)) + return false; + } + return true; +} + +extern const DNSName g_rootdnsname, g_wildcarddnsname; + +struct DNSNameSet: public std::unordered_set { + std::string toString() const { + std::ostringstream oss; + std::copy(begin(), end(), std::ostream_iterator(oss, "\n")); + return oss.str(); + } +}; diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc new file mode 100644 index 0000000..ac752f5 --- /dev/null +++ b/pdns/dnspacket.cc @@ -0,0 +1,704 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dnsseckeeper.hh" +#include "dns.hh" +#include "dnsbackend.hh" +#include "ednsoptions.hh" +#include "pdnsexception.hh" +#include "dnspacket.hh" +#include "logger.hh" +#include "arguments.hh" +#include "dnswriter.hh" +#include "dnsparser.hh" +#include "dnsrecords.hh" +#include "dnssecinfra.hh" +#include "base64.hh" +#include "ednssubnet.hh" +#include "gss_context.hh" +#include "dns_random.hh" + +bool DNSPacket::s_doEDNSSubnetProcessing; +uint16_t DNSPacket::s_udpTruncationThreshold; + +DNSPacket::DNSPacket(bool isQuery): d_isQuery(isQuery) +{ + memset(&d, 0, sizeof(d)); +} + +const string& DNSPacket::getString() +{ + if(!d_wrapped) + wrapup(); + + return d_rawpacket; +} + +ComboAddress DNSPacket::getRemote() const +{ + return d_remote; +} + +uint16_t DNSPacket::getRemotePort() const +{ + return d_remote.sin4.sin_port; +} + +DNSPacket::DNSPacket(const DNSPacket &orig) : + d_anyLocal(orig.d_anyLocal), + d_dt(orig.d_dt), + qdomain(orig.qdomain), + qdomainwild(orig.qdomainwild), + qdomainzone(orig.qdomainzone), + + d(orig.d), + d_trc(orig.d_trc), + d_remote(orig.d_remote), + d_tsig_algo(orig.d_tsig_algo), + + d_ednsRawPacketSizeLimit(orig.d_ednsRawPacketSizeLimit), + qclass(orig.qclass), + qtype(orig.qtype), + d_tcp(orig.d_tcp), + d_dnssecOk(orig.d_dnssecOk), + d_havetsig(orig.d_havetsig), + + d_tsigsecret(orig.d_tsigsecret), + d_tsigkeyname(orig.d_tsigkeyname), + d_tsigprevious(orig.d_tsigprevious), + d_rrs(orig.d_rrs), + d_rawpacket(orig.d_rawpacket), + d_eso(orig.d_eso), + d_maxreplylen(orig.d_maxreplylen), + d_socket(orig.d_socket), + d_hash(orig.d_hash), + d_ednsrcode(orig.d_ednsrcode), + d_ednsversion(orig.d_ednsversion), + + d_wrapped(orig.d_wrapped), + d_compress(orig.d_compress), + d_tsigtimersonly(orig.d_tsigtimersonly), + d_wantsnsid(orig.d_wantsnsid), + d_haveednssubnet(orig.d_haveednssubnet), + d_haveednssection(orig.d_haveednssection), + + d_isQuery(orig.d_isQuery) +{ + DLOG(g_log<<"DNSPacket copy constructor called!"<(rr).dr.d_content->serialize(rr.dr.d_name); + auto hash = boost::hash< std::pair >()({rr.dr.d_name, ser}); + if(d_dedup.count(hash)) { // might be a dup + for(auto i=d_rrs.begin();i!=d_rrs.end();++i) { + if(rr.dr == i->dr) // XXX SUPER SLOW + return; + } + } + d_dedup.insert(hash); + } + + d_rrs.push_back(rr); +} + +vector DNSPacket::getAPRecords() +{ + vector arrs; + + for(vector::iterator i=d_rrs.begin(); + i!=d_rrs.end(); + ++i) + { + if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL && + (i->dr.d_type==QType::MX || + i->dr.d_type==QType::NS || + i->dr.d_type==QType::SRV)) + { + arrs.push_back(&*i); + } + } + return arrs; +} + +vector DNSPacket::getAnswerRecords() +{ + vector arrs; + + for(vector::iterator i=d_rrs.begin(); + i!=d_rrs.end(); + ++i) + { + if(i->dr.d_place!=DNSResourceRecord::ADDITIONAL) + arrs.push_back(&*i); + } + return arrs; +} + + +void DNSPacket::setCompress(bool compress) +{ + d_compress=compress; + d_rawpacket.reserve(65000); + d_rrs.reserve(200); +} + +bool DNSPacket::couldBeCached() +{ + return !d_wantsnsid && qclass==QClass::IN && !d_havetsig; +} + +unsigned int DNSPacket::getMinTTL() +{ + unsigned int minttl = UINT_MAX; + for(const DNSZoneRecord& rr : d_rrs) { + if (rr.dr.d_ttl < minttl) + minttl = rr.dr.d_ttl; + } + + return minttl; +} + +bool DNSPacket::isEmpty() +{ + return (d_rrs.empty()); +} + +/** Must be called before attempting to access getData(). This function stuffs all resource + * records found in rrs into the data buffer. It also frees resource records queued for us. + */ +void DNSPacket::wrapup() +{ + if(d_wrapped) { + return; + } + + DNSZoneRecord rr; + vector::iterator pos; + + // we now need to order rrs so that the different sections come at the right place + // we want a stable sort, based on the d_place field + + stable_sort(d_rrs.begin(),d_rrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) { + return a.dr.d_place < b.dr.d_place; + }); + static bool mustNotShuffle = ::arg().mustDo("no-shuffle"); + + if(!d_tcp && !mustNotShuffle) { + shuffle(d_rrs); + } + d_wrapped=true; + + vector packet; + DNSPacketWriter pw(packet, qdomain, qtype.getCode(), qclass); + + pw.getHeader()->rcode=d.rcode; + pw.getHeader()->opcode = d.opcode; + pw.getHeader()->aa=d.aa; + pw.getHeader()->ra=d.ra; + pw.getHeader()->qr=d.qr; + pw.getHeader()->id=d.id; + pw.getHeader()->rd=d.rd; + pw.getHeader()->tc=d.tc; + + DNSPacketWriter::optvect_t opts; + + /* optsize is expected to hold an upper bound of data that will be + added after actual record data - i.e. OPT, TSIG, perhaps one day + XPF. Because of the way `pw` incrementally writes the packet, we + cannot easily 'go back' and remove a few records. So, to prevent + going over our maximum size, we keep our (potential) extra data + in mind. + + This means that sometimes we'll send TC even if we'd end up with + a few bytes to spare, but so be it. + */ + size_t optsize = 0; + + if (d_haveednssection || d_dnssecOk) { + /* root label (1), type (2), class (2), ttl (4) + rdlen (2) */ + optsize = 11; + } + + if(d_wantsnsid) { + const static string mode_server_id=::arg()["server-id"]; + if(mode_server_id != "disabled") { + opts.push_back(make_pair(EDNSOptionCode::NSID, mode_server_id)); + optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + mode_server_id.size(); + } + } + + if (d_haveednssubnet) + { + // this is an upper bound + optsize += EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 + 1 + 1; // code+len+family+src len+scope len + optsize += d_eso.source.isIpv4() ? 4 : 16; + } + + if (d_trc.d_algoName.countLabels()) + { + // TSIG is not OPT, but we count it in optsize anyway + optsize += d_trc.d_algoName.wirelength() + 3 + 1 + 2; // algo + time + fudge + maclen + optsize += EVP_MAX_MD_SIZE + 2 + 2 + 2 + 0; // mac + origid + ercode + otherdatalen + no other data + + static_assert(EVP_MAX_MD_SIZE <= 64, "EVP_MAX_MD_SIZE is overly huge on this system, please check"); + } + + if(!d_rrs.empty() || !opts.empty() || d_haveednssubnet || d_haveednssection) { + try { + uint8_t maxScopeMask=0; + for(pos=d_rrs.begin(); pos < d_rrs.end(); ++pos) { + // cerr<<"during wrapup, content=["<content<<"]"<scopeMask); + + pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place); + pos->dr.d_content->toPacket(pw); + if(pw.size() + optsize > (d_tcp ? 65535 : getMaxReplyLen())) { + pw.rollback(); + pw.truncate(); + pw.getHeader()->tc=1; + goto noCommit; + } + } + + // if(!pw.getHeader()->tc) // protect against double commit from addSignature + + if(!d_rrs.empty()) pw.commit(); + + noCommit:; + + if(d_haveednssubnet) { + EDNSSubnetOpts eso = d_eso; + eso.scope = Netmask(eso.source.getNetwork(), maxScopeMask); + + string opt = makeEDNSSubnetOptsString(eso); + opts.push_back(make_pair(8, opt)); // 'EDNS SUBNET' + } + + if(!opts.empty() || d_haveednssection || d_dnssecOk) + { + pw.addOpt(s_udpTruncationThreshold, d_ednsrcode, d_dnssecOk ? EDNSOpts::DNSSECOK : 0, opts); + pw.commit(); + } + } + catch(std::exception& e) { + g_log<qdcount; + d.ancount = pw.getHeader()->ancount; + d.nscount = pw.getHeader()->nscount; + d.arcount = pw.getHeader()->arcount; +} + +void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype) +{ + memset(&d,0,sizeof(d)); + d.id=dns_random(0xffff); + d.rd=d.tc=d.aa=false; + d.qr=false; + d.qdcount=1; // is htons'ed later on + d.ancount=d.arcount=d.nscount=0; + d.opcode=op; + qdomain=qd; + qtype=newqtype; +} + +/** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */ +DNSPacket *DNSPacket::replyPacket() const +{ + DNSPacket *r=new DNSPacket(false); + r->setSocket(d_socket); + r->d_anyLocal=d_anyLocal; + r->setRemote(&d_remote); + r->setAnswer(true); // this implies the allocation of the header + r->setA(true); // and we are authoritative + r->setRA(0); // no recursion available + r->setRD(d.rd); // if you wanted to recurse, answer will say you wanted it + r->setID(d.id); + r->setOpcode(d.opcode); + + r->d_dt=d_dt; + r->d.qdcount=1; + r->d_tcp = d_tcp; + r->qdomain = qdomain; + r->qtype = qtype; + r->qclass = qclass; + r->d_maxreplylen = d_maxreplylen; + r->d_wantsnsid = d_wantsnsid; + r->d_dnssecOk = d_dnssecOk; + r->d_eso = d_eso; + r->d_haveednssubnet = d_haveednssubnet; + r->d_haveednssection = d_haveednssection; + r->d_ednsversion = 0; + r->d_ednsrcode = 0; + + if(d_tsigkeyname.countLabels()) { + r->d_tsigkeyname = d_tsigkeyname; + r->d_tsigprevious = d_tsigprevious; + r->d_trc = d_trc; + r->d_tsigsecret = d_tsigsecret; + r->d_tsigtimersonly = d_tsigtimersonly; + } + r->d_havetsig = d_havetsig; + return r; +} + +void DNSPacket::spoofQuestion(const DNSPacket *qd) +{ + d_wrapped=true; // if we do this, don't later on wrapup + + int labellen; + string::size_type i=sizeof(d); + + for(;;) { + labellen = qd->d_rawpacket[i]; + if(!labellen) break; + i++; + d_rawpacket.replace(i, labellen, qd->d_rawpacket, i, labellen); + i = i + labellen; + } +} + +int DNSPacket::noparse(const char *mesg, size_t length) +{ + d_rawpacket.assign(mesg,length); + if(length < 12) { + g_log << Logger::Debug << "Ignoring packet: too short ("<>8)); + d_tsigkeyname = keyname; + d_tsigsecret = secret; + d_tsigprevious = previous; + d_tsigtimersonly=timersonly; +} + +bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const +{ + MOADNSParser mdp(d_isQuery, d_rawpacket); + uint16_t tsigPos = mdp.getTSIGPos(); + if(!tsigPos) + return false; + + bool gotit=false; + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_type == QType::TSIG && i->first.d_class == QType::ANY) { + // cast can fail, f.e. if d_content is an UnknownRecordContent. + shared_ptr content = std::dynamic_pointer_cast(i->first.d_content); + if (!content) { + g_log<first.d_name; + gotit=true; + } + } + if(!gotit) + return false; + + if (tsigPosOut) { + *tsigPosOut = tsigPos; + } + + return true; +} + +bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const +{ + MOADNSParser mdp(d_isQuery, d_rawpacket); + bool gotit=false; + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if (gotit) { + g_log<first.d_type == QType::TKEY) { + // cast can fail, f.e. if d_content is an UnknownRecordContent. + shared_ptr content = std::dynamic_pointer_cast(i->first.d_content); + if (!content) { + g_log<first.d_name; + gotit=true; + } + } + + return gotit; +} + +/** This function takes data from the network, possibly received with recvfrom, and parses + it into our class. Results of calling this function multiple times on one packet are + unknown. Returns -1 if the packet cannot be parsed. +*/ +int DNSPacket::parse(const char *mesg, size_t length) +try +{ + d_rawpacket.assign(mesg,length); + d_wrapped=true; + if(length < 12) { + g_log << Logger::Debug << "Ignoring packet: too short from " + << getRemote() << endl; + return -1; + } + + MOADNSParser mdp(d_isQuery, d_rawpacket); + EDNSOpts edo; + + // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST! + + d_wantsnsid=false; + d_dnssecOk=false; + d_havetsig = mdp.getTSIGPos(); + d_haveednssubnet = false; + d_haveednssection = false; + + if(getEDNSOpts(mdp, &edo)) { + d_haveednssection=true; + /* rfc6891 6.2.3: + "Values lower than 512 MUST be treated as equal to 512." + */ + d_ednsRawPacketSizeLimit=edo.d_packetsize; + d_maxreplylen=std::min(std::max(static_cast(512), edo.d_packetsize), s_udpTruncationThreshold); +// cerr< >::const_iterator iter = edo.d_options.begin(); + iter != edo.d_options.end(); + ++iter) { + if(iter->first == EDNSOptionCode::NSID) { + d_wantsnsid=true; + } + else if(s_doEDNSSubnetProcessing && (iter->first == EDNSOptionCode::ECS)) { // 'EDNS SUBNET' + if(getEDNSSubnetOptsFromString(iter->second, &d_eso)) { + //cerr<<"Parsed, source: "<first<<": "<second)<getTSIGKey(*keyname, &tt.algo, &secret64)) { + g_log<qdomain<<"' denied: can't find TSIG key with name '"<<*keyname<<"' and algorithm '"<d_mac, false); + } + catch(const std::runtime_error& err) { + g_log<qdomain<<"' denied: "< +#include +#include +#include +#include "iputils.hh" +#include "ednssubnet.hh" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "qtype.hh" +#include "dns.hh" +#include "misc.hh" +#include "utility.hh" +#include "logger.hh" +#include "pdnsexception.hh" +#include "dnsrecords.hh" + +class UeberBackend; +class DNSSECKeeper; + + +//! This class represents DNS packets, either received or to be sent. +class DNSPacket +{ +public: + DNSPacket(bool isQuery); + DNSPacket(const DNSPacket &orig); + + int noparse(const char *mesg, size_t len); //!< just suck the data inward + int parse(const char *mesg, size_t len); //!< parse a raw UDP or TCP packet and suck the data inward + const string& getString(); //!< for serialization - just passes the whole packet + + // address & socket manipulation + void setRemote(const ComboAddress*); + ComboAddress getRemote() const; + Netmask getRealRemote() const; + ComboAddress getLocal() const + { + ComboAddress ca; + socklen_t len=sizeof(ca); + getsockname(d_socket, (sockaddr*)&ca, &len); + return ca; + } + uint16_t getRemotePort() const; + + boost::optional d_anyLocal; + + Utility::sock_t getSocket() const + { + return d_socket; + } + void setSocket(Utility::sock_t sock); + + + // these manipulate 'd' + void setA(bool); //!< make this packet authoritative - manipulates 'd' + void setID(uint16_t); //!< set the DNS id of this packet - manipulates 'd' + void setRA(bool); //!< set the Recursion Available flag - manipulates 'd' + void setRD(bool); //!< set the Recursion Desired flag - manipulates 'd' + void setAnswer(bool); //!< Make this packet an answer - clears the 'stringbuffer' first, if passed 'true', does nothing otherwise, manipulates 'd' + + void setOpcode(uint16_t); //!< set the Opcode of this packet - manipulates 'd' + void setRcode(int v); //!< set the Rcode of this packet - manipulates 'd' + + void clearRecords(); //!< when building a packet, wipe all previously added records (clears 'rrs') + + /** Add a DNSZoneRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions, + Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the + DNSZoneRecord d_place field */ + void addRecord(const DNSZoneRecord &); // adds to 'rrs' + + void setQuestion(int op, const DNSName &qdomain, int qtype); // wipes 'd', sets a random id, creates start of packet (domain, type, class etc) + + DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer + void wrapup(); // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer + void spoofQuestion(const DNSPacket *qd); //!< paste in the exact right case of the question. Useful for PacketCache + unsigned int getMinTTL(); //!< returns lowest TTL of any record in the packet + bool isEmpty(); //!< returns true if there are no rrs in the packet + + vector getAPRecords(); //!< get a vector with DNSZoneRecords that need additional processing + vector getAnswerRecords(); //!< get a vector with DNSZoneRecords that are answers + void setCompress(bool compress); + + DNSPacket *replyPacket() const; //!< convenience function that creates a virgin answer packet to this question + + void commitD(); //!< copies 'd' into the stringbuffer + unsigned int getMaxReplyLen(); //!< retrieve the maximum length of the packet we should send in response + void setMaxReplyLen(int bytes); //!< set the max reply len (used when retrieving from the packet cache, and this changed) + + bool couldBeCached(); //!< returns 0 if this query should bypass the packet cache + bool hasEDNSSubnet() const; + bool hasEDNS(); + uint8_t getEDNSVersion() const { return d_ednsversion; }; + void setEDNSRcode(uint16_t extRCode) + { + // WARNING: this is really 12 bits + d_ednsrcode=extRCode; + }; + uint8_t getEDNSRCode() const { return d_ednsrcode; }; + uint32_t getHash() const { return d_hash; }; + void setHash(uint32_t hash) { d_hash = hash; }; + + //////// DATA ! + + DNSName qdomain; //!< qname of the question 4 - unsure how this is used + DNSName qdomainwild; //!< wildcard matched by qname, used by LuaPolicyEngine + DNSName qdomainzone; //!< zone name for the answer (as reflected in SOA for negative responses), used by LuaPolicyEngine + string d_peer_principal; + const DNSName& getTSIGKeyname() const; + + struct dnsheader d; //!< dnsheader at the start of the databuffer 12 + + TSIGRecordContent d_trc; //72 + + ComboAddress d_remote; //28 + TSIGHashEnum d_tsig_algo{TSIG_MD5}; //4 + + int d_ednsRawPacketSizeLimit{-1}; // only used for Lua record + uint16_t qclass{QClass::IN}; //!< class of the question - should always be INternet 2 + QType qtype; //!< type of the question 2 + + bool d_tcp{false}; + bool d_dnssecOk{false}; + bool d_havetsig{false}; + + bool getTSIGDetails(TSIGRecordContent* tr, DNSName* keyname, uint16_t* tsigPos=nullptr) const; + void setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly=false); + bool getTKEYRecord(TKEYRecordContent* tr, DNSName* keyname) const; + + vector& getRRS() { return d_rrs; } + bool checkForCorrectTSIG(UeberBackend* B, DNSName* keyname, string* secret, TSIGRecordContent* trc) const; + + static uint16_t s_udpTruncationThreshold; + static bool s_doEDNSSubnetProcessing; + +private: + void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies + + string d_tsigsecret; + DNSName d_tsigkeyname; + string d_tsigprevious; + + vector d_rrs; // 8 + std::unordered_set d_dedup; + string d_rawpacket; // this is where everything lives 8 + EDNSSubnetOpts d_eso; + + int d_maxreplylen{0}; + int d_socket{-1}; // 4 + uint32_t d_hash{0}; + // WARNING! This is really 12 bits + uint16_t d_ednsrcode{0}; + uint8_t d_ednsversion{0}; + + bool d_wrapped{false}; // 1 + bool d_compress{true}; // 1 + bool d_tsigtimersonly{false}; + bool d_wantsnsid{false}; + bool d_haveednssubnet{false}; + bool d_haveednssection{false}; + bool d_isQuery; +}; + +#endif diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc new file mode 100644 index 0000000..f89ff3f --- /dev/null +++ b/pdns/dnsparser.cc @@ -0,0 +1,989 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "dnsparser.hh" +#include "dnswriter.hh" +#include +#include + +#include "namespaces.hh" + +class UnknownRecordContent : public DNSRecordContent +{ +public: + UnknownRecordContent(const DNSRecord& dr, PacketReader& pr) + : d_dr(dr) + { + pr.copyRecord(d_record, dr.d_clen); + } + + UnknownRecordContent(const string& zone) + { + // parse the input + vector parts; + stringtok(parts, zone); + if(parts.size()!=3 && !(parts.size()==2 && equals(parts[1],"0")) ) + throw MOADNSException("Unknown record was stored incorrectly, need 3 fields, got "+std::to_string(parts.size())+": "+zone ); + const string& relevant=(parts.size() > 2) ? parts[2] : ""; + unsigned int total=pdns_stou(parts[1]); + if(relevant.size() % 2 || relevant.size() / 2 != total) + throw MOADNSException((boost::format("invalid unknown record length: size not equal to length field (%d != 2 * %d)") % relevant.size() % total).str()); + string out; + out.reserve(total+1); + for(unsigned int n=0; n < total; ++n) { + int c; + sscanf(relevant.c_str()+2*n, "%02x", &c); + out.append(1, (char)c); + } + + d_record.insert(d_record.end(), out.begin(), out.end()); + } + + string getZoneRepresentation(bool noDot) const override + { + ostringstream str; + str<<"\\# "<<(unsigned int)d_record.size()<<" "; + char hex[4]; + for(size_t n=0; n d_record; +}; + +shared_ptr DNSRecordContent::unserialize(const DNSName& qname, uint16_t qtype, const string& serialized) +{ + dnsheader dnsheader; + memset(&dnsheader, 0, sizeof(dnsheader)); + dnsheader.qdcount=htons(1); + dnsheader.ancount=htons(1); + + vector packet; // build pseudo packet + + /* will look like: dnsheader, 5 bytes, encoded qname, dns record header, serialized data */ + + string encoded=qname.toDNSString(); + + packet.resize(sizeof(dnsheader) + 5 + encoded.size() + sizeof(struct dnsrecordheader) + serialized.size()); + + uint16_t pos=0; + + memcpy(&packet[0], &dnsheader, sizeof(dnsheader)); pos+=sizeof(dnsheader); + + char tmp[6]="\x0" "\x0\x1" "\x0\x1"; // root question for ns_t_a + memcpy(&packet[pos], &tmp, 5); pos+=5; + + memcpy(&packet[pos], encoded.c_str(), encoded.size()); pos+=(uint16_t)encoded.size(); + + struct dnsrecordheader drh; + drh.d_type=htons(qtype); + drh.d_class=htons(QClass::IN); + drh.d_ttl=0; + drh.d_clen=htons(serialized.size()); + + memcpy(&packet[pos], &drh, sizeof(drh)); pos+=sizeof(drh); + memcpy(&packet[pos], serialized.c_str(), serialized.size()); pos+=(uint16_t)serialized.size(); + + MOADNSParser mdp(false, (char*)&*packet.begin(), (unsigned int)packet.size()); + shared_ptr ret= mdp.d_answers.begin()->first.d_content; + return ret; +} + +std::shared_ptr DNSRecordContent::mastermake(const DNSRecord &dr, + PacketReader& pr) +{ + uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT + + typemap_t::const_iterator i=getTypemap().find(make_pair(searchclass, dr.d_type)); + if(i==getTypemap().end() || !i->second) { + return std::make_shared(dr, pr); + } + + return i->second(dr, pr); +} + +std::shared_ptr DNSRecordContent::mastermake(uint16_t qtype, uint16_t qclass, + const string& content) +{ + zmakermap_t::const_iterator i=getZmakermap().find(make_pair(qclass, qtype)); + if(i==getZmakermap().end()) { + return std::make_shared(content); + } + + return i->second(content); +} + +std::shared_ptr DNSRecordContent::mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t oc) { + // For opcode UPDATE and where the DNSRecord is an answer record, we don't care about content, because this is + // not used within the prerequisite section of RFC2136, so - we can simply use unknownrecordcontent. + // For section 3.2.3, we do need content so we need to get it properly. But only for the correct QClasses. + if (oc == Opcode::Update && dr.d_place == DNSResourceRecord::ANSWER && dr.d_class != 1) + return std::make_shared(dr, pr); + + uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT + + typemap_t::const_iterator i=getTypemap().find(make_pair(searchclass, dr.d_type)); + if(i==getTypemap().end() || !i->second) { + return std::make_shared(dr, pr); + } + + return i->second(dr, pr); +} + + +DNSRecordContent::typemap_t& DNSRecordContent::getTypemap() +{ + static DNSRecordContent::typemap_t typemap; + return typemap; +} + +DNSRecordContent::n2typemap_t& DNSRecordContent::getN2Typemap() +{ + static DNSRecordContent::n2typemap_t n2typemap; + return n2typemap; +} + +DNSRecordContent::t2namemap_t& DNSRecordContent::getT2Namemap() +{ + static DNSRecordContent::t2namemap_t t2namemap; + return t2namemap; +} + +DNSRecordContent::zmakermap_t& DNSRecordContent::getZmakermap() +{ + static DNSRecordContent::zmakermap_t zmakermap; + return zmakermap; +} + +DNSRecord::DNSRecord(const DNSResourceRecord& rr): d_name(rr.qname) +{ + d_type = rr.qtype.getCode(); + d_ttl = rr.ttl; + d_class = rr.qclass; + d_place = DNSResourceRecord::ANSWER; + d_clen = 0; + d_content = DNSRecordContent::mastermake(d_type, rr.qclass, rr.content); +} + +// If you call this and you are not parsing a packet coming from a socket, you are doing it wrong. +DNSResourceRecord DNSResourceRecord::fromWire(const DNSRecord& d) { + DNSResourceRecord rr; + rr.qname = d.d_name; + rr.qtype = QType(d.d_type); + rr.ttl = d.d_ttl; + rr.content = d.d_content->getZoneRepresentation(true); + rr.auth = false; + rr.qclass = d.d_class; + return rr; +} + +void MOADNSParser::init(bool query, const std::string& packet) +{ + if (packet.size() < sizeof(dnsheader)) + throw MOADNSException("Packet shorter than minimal header"); + + memcpy(&d_header, packet.data(), sizeof(dnsheader)); + + if(d_header.opcode != Opcode::Query && d_header.opcode != Opcode::Notify && d_header.opcode != Opcode::Update) + throw MOADNSException("Can't parse non-query packet with opcode="+ std::to_string(d_header.opcode)); + + d_header.qdcount=ntohs(d_header.qdcount); + d_header.ancount=ntohs(d_header.ancount); + d_header.nscount=ntohs(d_header.nscount); + d_header.arcount=ntohs(d_header.arcount); + + if (query && (d_header.qdcount > 1)) + throw MOADNSException("Query with QD > 1 ("+std::to_string(d_header.qdcount)+")"); + + unsigned int n=0; + + PacketReader pr(packet); + bool validPacket=false; + try { + d_qtype = d_qclass = 0; // sometimes replies come in with no question, don't present garbage then + + for(n=0;n < d_header.qdcount; ++n) { + d_qname=pr.getName(); + d_qtype=pr.get16BitInt(); + d_qclass=pr.get16BitInt(); + } + + struct dnsrecordheader ah; + vector record; + bool seenTSIG = false; + validPacket=true; + d_answers.reserve((unsigned int)(d_header.ancount + d_header.nscount + d_header.arcount)); + for(n=0;n < (unsigned int)(d_header.ancount + d_header.nscount + d_header.arcount); ++n) { + DNSRecord dr; + + if(n < d_header.ancount) + dr.d_place=DNSResourceRecord::ANSWER; + else if(n < d_header.ancount + d_header.nscount) + dr.d_place=DNSResourceRecord::AUTHORITY; + else + dr.d_place=DNSResourceRecord::ADDITIONAL; + + unsigned int recordStartPos=pr.getPosition(); + + DNSName name=pr.getName(); + + pr.getDnsrecordheader(ah); + dr.d_ttl=ah.d_ttl; + dr.d_type=ah.d_type; + dr.d_class=ah.d_class; + + dr.d_name=name; + dr.d_clen=ah.d_clen; + + if (query && + !(d_qtype == QType::IXFR && dr.d_place == DNSResourceRecord::AUTHORITY && dr.d_type == QType::SOA) && // IXFR queries have a SOA in their AUTHORITY section + (dr.d_place == DNSResourceRecord::ANSWER || dr.d_place == DNSResourceRecord::AUTHORITY || (dr.d_type != QType::OPT && dr.d_type != QType::TSIG && dr.d_type != QType::SIG && dr.d_type != QType::TKEY) || ((dr.d_type == QType::TSIG || dr.d_type == QType::SIG || dr.d_type == QType::TKEY) && dr.d_class != QClass::ANY))) { +// cerr<<"discarding RR, query is "<(dr, pr); + } + else { +// cerr<<"parsing RR, query is "<(&ah); + + for(n=0; n < sizeof(dnsrecordheader); ++n) + p[n]=d_content.at(d_pos++); + + ah.d_type=ntohs(ah.d_type); + ah.d_class=ntohs(ah.d_class); + ah.d_clen=ntohs(ah.d_clen); + ah.d_ttl=ntohl(ah.d_ttl); + + d_startrecordpos=d_pos; // needed for getBlob later on + d_recordlen=ah.d_clen; +} + + +void PacketReader::copyRecord(vector& dest, uint16_t len) +{ + dest.resize(len); + if(!len) + return; + + for(uint16_t n=0;n d_content.size()) + throw std::out_of_range("Attempt to copy outside of packet"); + + memcpy(dest, &d_content.at(d_pos), len); + d_pos+=len; +} + +void PacketReader::xfr48BitInt(uint64_t& ret) +{ + ret=0; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); +} + +uint32_t PacketReader::get32BitInt() +{ + uint32_t ret=0; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + + return ret; +} + + +uint16_t PacketReader::get16BitInt() +{ + uint16_t ret=0; + ret+=static_cast(d_content.at(d_pos++)); + ret<<=8; + ret+=static_cast(d_content.at(d_pos++)); + + return ret; +} + +uint8_t PacketReader::get8BitInt() +{ + return d_content.at(d_pos++); +} + +DNSName PacketReader::getName() +{ + unsigned int consumed; + try { + DNSName dn((const char*) d_content.data(), d_content.size(), d_pos, true /* uncompress */, 0 /* qtype */, 0 /* qclass */, &consumed, sizeof(dnsheader)); + + d_pos+=consumed; + return dn; + } + catch(const std::range_error& re) { + throw std::out_of_range(string("dnsname issue: ")+re.what()); + } + catch(...) { + throw std::out_of_range("dnsname issue"); + } + throw PDNSException("PacketReader::getName(): name is empty"); +} + +static string txtEscape(const string &name) +{ + string ret; + char ebuf[5]; + + for(string::const_iterator i=name.begin();i!=name.end();++i) { + if((unsigned char) *i >= 127 || (unsigned char) *i < 32) { + snprintf(ebuf, sizeof(ebuf), "\\%03u", (unsigned char)*i); + ret += ebuf; + } + else if(*i=='"' || *i=='\\'){ + ret += '\\'; + ret += *i; + } + else + ret += *i; + } + return ret; +} + +// exceptions thrown here do not result in logging in the main pdns auth server - just so you know! +string PacketReader::getText(bool multi, bool lenField) +{ + string ret; + ret.reserve(40); + while(d_pos < d_startrecordpos + d_recordlen ) { + if(!ret.empty()) { + ret.append(1,' '); + } + uint16_t labellen; + if(lenField) + labellen=static_cast(d_content.at(d_pos++)); + else + labellen=d_recordlen - (d_pos - d_startrecordpos); + + ret.append(1,'"'); + if(labellen) { // no need to do anything for an empty string + string val(&d_content.at(d_pos), &d_content.at(d_pos+labellen-1)+1); + ret.append(txtEscape(val)); // the end is one beyond the packet + } + ret.append(1,'"'); + d_pos+=labellen; + if(!multi) + break; + } + + return ret; +} + +string PacketReader::getUnquotedText(bool lenField) +{ + uint16_t stop_at; + if(lenField) + stop_at = static_cast(d_content.at(d_pos)) + d_pos + 1; + else + stop_at = d_recordlen; + + /* think unsigned overflow */ + if (stop_at < d_pos) { + throw std::out_of_range("getUnquotedText out of record range"); + } + + if(stop_at == d_pos) + return ""; + + d_pos++; + string ret(&d_content.at(d_pos), &d_content.at(stop_at)); + d_pos = stop_at; + return ret; +} + +void PacketReader::xfrBlob(string& blob) +try +{ + if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen))) { + if (d_pos > (d_startrecordpos + d_recordlen)) { + throw std::out_of_range("xfrBlob out of record range"); + } + blob.assign(&d_content.at(d_pos), &d_content.at(d_startrecordpos + d_recordlen - 1 ) + 1); + } + else { + blob.clear(); + } + + d_pos = d_startrecordpos + d_recordlen; +} +catch(...) +{ + throw std::out_of_range("xfrBlob out of range"); +} + +void PacketReader::xfrBlobNoSpaces(string& blob, int length) { + xfrBlob(blob, length); +} + +void PacketReader::xfrBlob(string& blob, int length) +{ + if(length) { + if (length < 0) { + throw std::out_of_range("xfrBlob out of range (negative length)"); + } + + blob.assign(&d_content.at(d_pos), &d_content.at(d_pos + length - 1 ) + 1 ); + + d_pos += length; + } + else { + blob.clear(); + } +} + + +void PacketReader::xfrHexBlob(string& blob, bool keepReading) +{ + xfrBlob(blob); +} + +//FIXME400 remove this method completely +string simpleCompress(const string& elabel, const string& root) +{ + string label=elabel; + // FIXME400: this relies on the semi-canonical escaped output from getName + if(strchr(label.c_str(), '\\')) { + boost::replace_all(label, "\\.", "."); + boost::replace_all(label, "\\032", " "); + boost::replace_all(label, "\\\\", "\\"); + } + typedef vector > parts_t; + parts_t parts; + vstringtok(parts, label, "."); + string ret; + ret.reserve(label.size()+4); + for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) { + if(!root.empty() && !strncasecmp(root.c_str(), label.c_str() + i->first, 1 + label.length() - i->first)) { // also match trailing 0, hence '1 +' + const unsigned char rootptr[2]={0xc0,0x11}; + ret.append((const char *) rootptr, 2); + return ret; + } + ret.append(1, (char)(i->second - i->first)); + ret.append(label.c_str() + i->first, i->second - i->first); + } + ret.append(1, (char)0); + return ret; +} + + +/** Simple DNSPacketMangler. Ritual is: get a pointer into the packet and moveOffset() to beyond your needs + * If you survive that, feel free to read from the pointer */ +class DNSPacketMangler +{ +public: + explicit DNSPacketMangler(std::string& packet) + : d_packet((char*) packet.c_str()), d_length(packet.length()), d_notyouroffset(12), d_offset(d_notyouroffset) + {} + DNSPacketMangler(char* packet, size_t length) + : d_packet(packet), d_length(length), d_notyouroffset(12), d_offset(d_notyouroffset) + {} + + /*! Advances past a wire-format domain name + * The name is not checked for adherence to length restrictions. + * Compression pointers are not followed. + */ + void skipDomainName() + { + uint8_t len; + while((len=get8BitInt())) { + if(len >= 0xc0) { // extended label + get8BitInt(); + return; + } + skipBytes(len); + } + } + + void skipBytes(uint16_t bytes) + { + moveOffset(bytes); + } + void rewindBytes(uint16_t by) + { + rewindOffset(by); + } + uint32_t get32BitInt() + { + const char* p = d_packet + d_offset; + moveOffset(4); + uint32_t ret; + memcpy(&ret, (void*)p, sizeof(ret)); + return ntohl(ret); + } + uint16_t get16BitInt() + { + const char* p = d_packet + d_offset; + moveOffset(2); + uint16_t ret; + memcpy(&ret, (void*)p, sizeof(ret)); + return ntohs(ret); + } + + uint8_t get8BitInt() + { + const char* p = d_packet + d_offset; + moveOffset(1); + return *p; + } + + void skipRData() + { + int toskip = get16BitInt(); + moveOffset(toskip); + } + + void decreaseAndSkip32BitInt(uint32_t decrease) + { + const char *p = d_packet + d_offset; + moveOffset(4); + + uint32_t tmp; + memcpy(&tmp, (void*) p, sizeof(tmp)); + tmp = ntohl(tmp); + tmp-=decrease; + tmp = htonl(tmp); + memcpy(d_packet + d_offset-4, (const char*)&tmp, sizeof(tmp)); + } + void setAndSkip32BitInt(uint32_t value) + { + moveOffset(4); + + value = htonl(value); + memcpy(d_packet + d_offset-4, (const char*)&value, sizeof(value)); + } + uint32_t getOffset() const + { + return d_offset; + } +private: + void moveOffset(uint16_t by) + { + d_notyouroffset += by; + if(d_notyouroffset > d_length) + throw std::out_of_range("dns packet out of range: "+std::to_string(d_notyouroffset) +" > " + + std::to_string(d_length) ); + } + void rewindOffset(uint16_t by) + { + if(d_notyouroffset < by) + throw std::out_of_range("Rewinding dns packet out of range: "+std::to_string(d_notyouroffset) +" < " + + std::to_string(by)); + d_notyouroffset -= by; + if(d_notyouroffset < 12) + throw std::out_of_range("Rewinding dns packet out of range: "+std::to_string(d_notyouroffset) +" < " + + std::to_string(12)); + } + char* d_packet; + size_t d_length; + + uint32_t d_notyouroffset; // only 'moveOffset' can touch this + const uint32_t& d_offset; // look.. but don't touch + +}; + +// method of operation: silently fail if it doesn't work - we're only trying to be nice, don't fall over on it +void editDNSPacketTTL(char* packet, size_t length, std::function visitor) +{ + if(length < sizeof(dnsheader)) + return; + try + { + dnsheader dh; + memcpy((void*)&dh, (const dnsheader*)packet, sizeof(dh)); + uint64_t numrecords = ntohs(dh.ancount) + ntohs(dh.nscount) + ntohs(dh.arcount); + DNSPacketMangler dpm(packet, length); + + uint64_t n; + for(n=0; n < ntohs(dh.qdcount) ; ++n) { + dpm.skipDomainName(); + /* type and class */ + dpm.skipBytes(4); + } + + for(n=0; n < numrecords; ++n) { + dpm.skipDomainName(); + + uint8_t section = n < ntohs(dh.ancount) ? 1 : (n < (ntohs(dh.ancount) + ntohs(dh.nscount)) ? 2 : 3); + uint16_t dnstype = dpm.get16BitInt(); + uint16_t dnsclass = dpm.get16BitInt(); + + if(dnstype == QType::OPT) // not getting near that one with a stick + break; + + uint32_t dnsttl = dpm.get32BitInt(); + uint32_t newttl = visitor(section, dnsclass, dnstype, dnsttl); + if (newttl) { + dpm.rewindBytes(sizeof(newttl)); + dpm.setAndSkip32BitInt(newttl); + } + dpm.skipRData(); + } + } + catch(...) + { + return; + } +} + +// method of operation: silently fail if it doesn't work - we're only trying to be nice, don't fall over on it +void ageDNSPacket(char* packet, size_t length, uint32_t seconds) +{ + if(length < sizeof(dnsheader)) + return; + try + { + const dnsheader* dh = reinterpret_cast(packet); + const uint64_t dqcount = ntohs(dh->qdcount); + const uint64_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount); + DNSPacketMangler dpm(packet, length); + + uint64_t n; + for(n=0; n < dqcount; ++n) { + dpm.skipDomainName(); + /* type and class */ + dpm.skipBytes(4); + } + // cerr<<"Skipped "<::max(); + if(length < sizeof(dnsheader)) { + return result; + } + try + { + const dnsheader* dh = (const dnsheader*) packet; + DNSPacketMangler dpm(const_cast(packet), length); + + const uint16_t qdcount = ntohs(dh->qdcount); + for(size_t n = 0; n < qdcount; ++n) { + dpm.skipDomainName(); + /* type and class */ + dpm.skipBytes(4); + } + const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount); + for(size_t n = 0; n < numrecords; ++n) { + dpm.skipDomainName(); + const uint16_t dnstype = dpm.get16BitInt(); + /* class */ + const uint16_t dnsclass = dpm.get16BitInt(); + + if(dnstype == QType::OPT) { + break; + } + + /* report it if we see a SOA record in the AUTHORITY section */ + if(dnstype == QType::SOA && dnsclass == QClass::IN && seenAuthSOA != nullptr && n >= ntohs(dh->ancount) && n < (ntohs(dh->ancount) + ntohs(dh->nscount))) { + *seenAuthSOA = true; + } + + const uint32_t ttl = dpm.get32BitInt(); + if (result > ttl) { + result = ttl; + } + + dpm.skipRData(); + } + } + catch(...) + { + } + return result; +} + +uint32_t getDNSPacketLength(const char* packet, size_t length) +{ + uint32_t result = length; + if(length < sizeof(dnsheader)) { + return result; + } + try + { + const dnsheader* dh = reinterpret_cast(packet); + DNSPacketMangler dpm(const_cast(packet), length); + + const uint16_t qdcount = ntohs(dh->qdcount); + for(size_t n = 0; n < qdcount; ++n) { + dpm.skipDomainName(); + /* type and class */ + dpm.skipBytes(4); + } + const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount); + for(size_t n = 0; n < numrecords; ++n) { + dpm.skipDomainName(); + /* type (2), class (2) and ttl (4) */ + dpm.skipBytes(8); + dpm.skipRData(); + } + result = dpm.getOffset(); + } + catch(...) + { + } + return result; +} + +uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t section, uint16_t type) +{ + uint16_t result = 0; + if(length < sizeof(dnsheader)) { + return result; + } + try + { + const dnsheader* dh = (const dnsheader*) packet; + DNSPacketMangler dpm(const_cast(packet), length); + + const uint16_t qdcount = ntohs(dh->qdcount); + for(size_t n = 0; n < qdcount; ++n) { + dpm.skipDomainName(); + if (section == 0) { + uint16_t dnstype = dpm.get16BitInt(); + if (dnstype == type) { + result++; + } + /* class */ + dpm.skipBytes(2); + } else { + /* type and class */ + dpm.skipBytes(4); + } + } + const uint16_t ancount = ntohs(dh->ancount); + for(size_t n = 0; n < ancount; ++n) { + dpm.skipDomainName(); + if (section == 1) { + uint16_t dnstype = dpm.get16BitInt(); + if (dnstype == type) { + result++; + } + /* class */ + dpm.skipBytes(2); + } else { + /* type and class */ + dpm.skipBytes(4); + } + /* ttl */ + dpm.skipBytes(4); + dpm.skipRData(); + } + const uint16_t nscount = ntohs(dh->nscount); + for(size_t n = 0; n < nscount; ++n) { + dpm.skipDomainName(); + if (section == 2) { + uint16_t dnstype = dpm.get16BitInt(); + if (dnstype == type) { + result++; + } + /* class */ + dpm.skipBytes(2); + } else { + /* type and class */ + dpm.skipBytes(4); + } + /* ttl */ + dpm.skipBytes(4); + dpm.skipRData(); + } + const uint16_t arcount = ntohs(dh->arcount); + for(size_t n = 0; n < arcount; ++n) { + dpm.skipDomainName(); + if (section == 3) { + uint16_t dnstype = dpm.get16BitInt(); + if (dnstype == type) { + result++; + } + /* class */ + dpm.skipBytes(2); + } else { + /* type and class */ + dpm.skipBytes(4); + } + /* ttl */ + dpm.skipBytes(4); + dpm.skipRData(); + } + } + catch(...) + { + } + return result; +} + +bool getEDNSUDPPayloadSizeAndZ(const char* packet, size_t length, uint16_t* payloadSize, uint16_t* z) +{ + if (length < sizeof(dnsheader)) { + return false; + } + + *payloadSize = 0; + *z = 0; + + try + { + const dnsheader* dh = (const dnsheader*) packet; + DNSPacketMangler dpm(const_cast(packet), length); + + const uint16_t qdcount = ntohs(dh->qdcount); + for(size_t n = 0; n < qdcount; ++n) { + dpm.skipDomainName(); + /* type and class */ + dpm.skipBytes(4); + } + const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount); + for(size_t n = 0; n < numrecords; ++n) { + dpm.skipDomainName(); + const uint16_t dnstype = dpm.get16BitInt(); + const uint16_t dnsclass = dpm.get16BitInt(); + + if(dnstype == QType::OPT) { + /* skip extended rcode and version */ + dpm.skipBytes(2); + *z = dpm.get16BitInt(); + *payloadSize = dnsclass; + return true; + } + + /* TTL */ + dpm.skipBytes(4); + dpm.skipRData(); + } + } + catch(...) + { + } + + return false; +} diff --git a/pdns/dnsparser.hh b/pdns/dnsparser.hh new file mode 100644 index 0000000..33228bd --- /dev/null +++ b/pdns/dnsparser.hh @@ -0,0 +1,411 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef DNSPARSER_HH +#define DNSPARSER_HH + +#include +#include +#include +#include +#include +#include +// #include +#include "misc.hh" + +#include +#include +#include "dns.hh" +#include "dnswriter.hh" +#include "dnsname.hh" +#include "pdnsexception.hh" +#include "iputils.hh" + +/** DNS records have three representations: + 1) in the packet + 2) parsed in a class, ready for use + 3) in the zone + + We should implement bidirectional transitions between 1&2 and 2&3. + Currently we have: 1 -> 2 + 2 -> 3 + + We can add: 2 -> 1 easily by reversing the packetwriter + And we might be able to reverse 2 -> 3 as well +*/ + +#include "namespaces.hh" +#include "namespaces.hh" + +class MOADNSException : public runtime_error +{ +public: + MOADNSException(const string& str) : runtime_error(str) + {} +}; + + +class MOADNSParser; + +class PacketReader +{ +public: + PacketReader(const std::string& content, uint16_t initialPos=sizeof(dnsheader)) + : d_pos(initialPos), d_startrecordpos(initialPos), d_content(content) + { + if(content.size() > std::numeric_limits::max()) + throw std::out_of_range("packet too large"); + + d_recordlen = (uint16_t) content.size(); + not_used = 0; + } + + uint32_t get32BitInt(); + uint16_t get16BitInt(); + uint8_t get8BitInt(); + + void xfr48BitInt(uint64_t& val); + + void xfr32BitInt(uint32_t& val) + { + val=get32BitInt(); + } + + void xfrIP(uint32_t& val) + { + xfr32BitInt(val); + val=htonl(val); + } + + void xfrIP6(std::string &val) { + xfrBlob(val, 16); + } + + void xfrCAWithoutPort(uint8_t version, ComboAddress &val) { + string blob; + if (version == 4) xfrBlob(blob, 4); + else if (version == 6) xfrBlob(blob, 16); + else throw runtime_error("invalid IP protocol"); + val = makeComboAddressFromRaw(version, blob); + } + + void xfrCAPort(ComboAddress &val) { + uint16_t port; + xfr16BitInt(port); + val.sin4.sin_port = port; + } + + void xfrTime(uint32_t& val) + { + xfr32BitInt(val); + } + + + void xfr16BitInt(uint16_t& val) + { + val=get16BitInt(); + } + + void xfrType(uint16_t& val) + { + xfr16BitInt(val); + } + + + void xfr8BitInt(uint8_t& val) + { + val=get8BitInt(); + } + + + void xfrName(DNSName &name, bool compress=false, bool noDot=false) + { + name=getName(); + } + + void xfrText(string &text, bool multi=false, bool lenField=true) + { + text=getText(multi, lenField); + } + + void xfrUnquotedText(string &text, bool lenField){ + text=getUnquotedText(lenField); + } + + void xfrBlob(string& blob); + void xfrBlobNoSpaces(string& blob, int len); + void xfrBlob(string& blob, int length); + void xfrHexBlob(string& blob, bool keepReading=false); + + void getDnsrecordheader(struct dnsrecordheader &ah); + void copyRecord(vector& dest, uint16_t len); + void copyRecord(unsigned char* dest, uint16_t len); + + DNSName getName(); + string getText(bool multi, bool lenField); + string getUnquotedText(bool lenField); + + + bool eof() { return true; }; + const string getRemaining() const { + return ""; + }; + + uint16_t getPosition() const + { + return d_pos; + } + + void skip(uint16_t n) + { + d_pos += n; + } + +private: + uint16_t d_pos; + uint16_t d_startrecordpos; // needed for getBlob later on + uint16_t d_recordlen; // ditto + uint16_t not_used; // Aligns the whole class on 8-byte boundries + const std::string& d_content; +}; + +struct DNSRecord; + +class DNSRecordContent +{ +public: + static std::shared_ptr mastermake(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t opcode); + static std::shared_ptr mastermake(uint16_t qtype, uint16_t qclass, const string& zone); + + virtual std::string getZoneRepresentation(bool noDot=false) const = 0; + virtual ~DNSRecordContent() {} + virtual void toPacket(DNSPacketWriter& pw)=0; + virtual string serialize(const DNSName& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard + { + vector packet; + DNSPacketWriter pw(packet, g_rootdnsname, 1); + if(canonic) + pw.setCanonic(true); + + if(lowerCase) + pw.setLowercase(true); + + pw.startRecord(qname, this->getType()); + this->toPacket(pw); + + string record; + pw.getRecordPayload(record); // needs to be called before commit() + return record; + } + + virtual bool operator==(const DNSRecordContent& rhs) const + { + return typeid(*this)==typeid(rhs) && this->getZoneRepresentation() == rhs.getZoneRepresentation(); + } + + static shared_ptr unserialize(const DNSName& qname, uint16_t qtype, const string& serialized); + + void doRecordCheck(const struct DNSRecord&){} + + typedef std::shared_ptr makerfunc_t(const struct DNSRecord& dr, PacketReader& pr); + typedef std::shared_ptr zmakerfunc_t(const string& str); + + static void regist(uint16_t cl, uint16_t ty, makerfunc_t* f, zmakerfunc_t* z, const char* name) + { + if(f) + getTypemap()[make_pair(cl,ty)]=f; + if(z) + getZmakermap()[make_pair(cl,ty)]=z; + + getT2Namemap().insert(make_pair(make_pair(cl,ty), name)); + getN2Typemap().insert(make_pair(name, make_pair(cl,ty))); + } + + static void unregist(uint16_t cl, uint16_t ty) + { + pair key=make_pair(cl, ty); + getTypemap().erase(key); + getZmakermap().erase(key); + } + + static uint16_t TypeToNumber(const string& name) + { + n2typemap_t::const_iterator iter = getN2Typemap().find(toUpper(name)); + if(iter != getN2Typemap().end()) + return iter->second.second; + + if(boost::starts_with(name, "TYPE") || boost::starts_with(name, "type")) + return (uint16_t) pdns_stou(name.substr(4)); + + throw runtime_error("Unknown DNS type '"+name+"'"); + } + + static const string NumberToType(uint16_t num, uint16_t classnum=1) + { + t2namemap_t::const_iterator iter = getT2Namemap().find(make_pair(classnum, num)); + if(iter == getT2Namemap().end()) + return "TYPE" + std::to_string(num); + // throw runtime_error("Unknown DNS type with numerical id "+std::to_string(num)); + return iter->second; + } + + virtual uint16_t getType() const = 0; + +protected: + typedef std::map, makerfunc_t* > typemap_t; + typedef std::map, zmakerfunc_t* > zmakermap_t; + typedef std::map, string > t2namemap_t; + typedef std::map > n2typemap_t; + static typemap_t& getTypemap(); + static t2namemap_t& getT2Namemap(); + static n2typemap_t& getN2Typemap(); + static zmakermap_t& getZmakermap(); +}; + +struct DNSRecord +{ + DNSRecord() : d_type(0), d_class(QClass::IN), d_ttl(0), d_clen(0), d_place(DNSResourceRecord::ANSWER) + {} + explicit DNSRecord(const DNSResourceRecord& rr); + DNSName d_name; + std::shared_ptr d_content; + uint16_t d_type; + uint16_t d_class; + uint32_t d_ttl; + uint16_t d_clen; + DNSResourceRecord::Place d_place; + + bool operator<(const DNSRecord& rhs) const + { + if(tie(d_name, d_type, d_class, d_ttl) < tie(rhs.d_name, rhs.d_type, rhs.d_class, rhs.d_ttl)) + return true; + + if(tie(d_name, d_type, d_class, d_ttl) != tie(rhs.d_name, rhs.d_type, rhs.d_class, rhs.d_ttl)) + return false; + + string lzrp, rzrp; + if(d_content) + lzrp=toLower(d_content->getZoneRepresentation()); + if(rhs.d_content) + rzrp=toLower(rhs.d_content->getZoneRepresentation()); + + return lzrp < rzrp; + } + + // this orders in canonical order and keeps the SOA record on top + static bool prettyCompare(const DNSRecord& a, const DNSRecord& b) + { + auto aType = (a.d_type == QType::SOA) ? 0 : a.d_type; + auto bType = (b.d_type == QType::SOA) ? 0 : b.d_type; + + if(a.d_name.canonCompare(b.d_name)) + return true; + if(b.d_name.canonCompare(a.d_name)) + return false; + + if(tie(aType, a.d_class, a.d_ttl) < tie(bType, b.d_class, b.d_ttl)) + return true; + + if(tie(aType, a.d_class, a.d_ttl) != tie(bType, b.d_class, b.d_ttl)) + return false; + + string lzrp, rzrp; + if(a.d_content) + lzrp=toLower(a.d_content->getZoneRepresentation()); + if(b.d_content) + rzrp=toLower(b.d_content->getZoneRepresentation()); + + return lzrp < rzrp; + } + + + bool operator==(const DNSRecord& rhs) const + { + if(d_type != rhs.d_type || d_class != rhs.d_class || d_name != rhs.d_name) + return false; + + return *d_content == *rhs.d_content; + } +}; + +struct DNSZoneRecord +{ + int domain_id{-1}; + uint8_t scopeMask{0}; + int signttl{0}; + DNSName wildcardname; + bool auth{true}; + DNSRecord dr; +}; + + +//! This class can be used to parse incoming packets, and is copyable +class MOADNSParser : public boost::noncopyable +{ +public: + //! Parse from a string + MOADNSParser(bool query, const string& buffer): d_tsigPos(0) + { + init(query, buffer); + } + + //! Parse from a pointer and length + MOADNSParser(bool query, const char *packet, unsigned int len) : d_tsigPos(0) + { + init(query, std::string(packet, len)); + } + + DNSName d_qname; + uint16_t d_qclass, d_qtype; + //uint8_t d_rcode; + dnsheader d_header; + + typedef vector > answers_t; + + //! All answers contained in this packet (everything *but* the question section) + answers_t d_answers; + + uint16_t getTSIGPos() const + { + return d_tsigPos; + } +private: + void init(bool query, const std::string& packet); + uint16_t d_tsigPos; +}; + +string simpleCompress(const string& label, const string& root=""); +void ageDNSPacket(char* packet, size_t length, uint32_t seconds); +void ageDNSPacket(std::string& packet, uint32_t seconds); +void editDNSPacketTTL(char* packet, size_t length, std::function visitor); +uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA=nullptr); +uint32_t getDNSPacketLength(const char* packet, size_t length); +uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t section, uint16_t type); +bool getEDNSUDPPayloadSizeAndZ(const char* packet, size_t length, uint16_t* payloadSize, uint16_t* z); + +template +std::shared_ptr getRR(const DNSRecord& dr) +{ + return std::dynamic_pointer_cast(dr.d_content); +} + +#endif diff --git a/pdns/dnspcap.cc b/pdns/dnspcap.cc new file mode 100644 index 0000000..3924a69 --- /dev/null +++ b/pdns/dnspcap.cc @@ -0,0 +1,246 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define __FAVOR_BSD +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnspcap.hh" +#include +#include + +#include "namespaces.hh" +PcapPacketReader::PcapPacketReader(const string& fname) : d_fname(fname) +{ + d_fp=fopen(fname.c_str(),"r"); + if(!d_fp) + unixDie("Unable to open file " + fname); + + int flags=fcntl(fileno(d_fp),F_GETFL,0); + fcntl(fileno(d_fp), F_SETFL,flags&(~O_NONBLOCK)); // bsd needs this in stdin (??) + + checkedFread(&d_pfh); + + if(d_pfh.magic != 2712847316UL) + throw runtime_error((format("PCAP file %s has bad magic %x, should be %x") % fname % d_pfh.magic % 2712847316UL).str()); + + if( d_pfh.linktype==1) { + d_skipMediaHeader=sizeof(struct ether_header); + } + else if(d_pfh.linktype==101) { + d_skipMediaHeader=0; + } + else if(d_pfh.linktype==113) { + d_skipMediaHeader=16; + } + else throw runtime_error((format("Unsupported link type %d") % d_pfh.linktype).str()); + + d_runts = d_oversized = d_correctpackets = d_nonetheripudp = 0; +} + +PcapPacketReader::~PcapPacketReader() +{ + fclose(d_fp); +} + + +void PcapPacketReader::checkedFreadSize(void* ptr, size_t size) +{ + int ret=fread(ptr, 1, size, d_fp); + if(ret < 0) + unixDie( (format("Error reading %d bytes from %s") % size % d_fname).str()); + + if(!ret) + throw EofException(); + + if((size_t)ret != size) + throw EofException((format("Incomplete read from '%s', got only %d bytes") % d_fname % ret).str()); +} + +bool PcapPacketReader::getUDPPacket() +try +{ + for(;;) { + checkedFread(&d_pheader); + if(!d_pheader.caplen) { + d_runts++; + continue; + } + + if(d_pheader.caplen > sizeof(d_buffer)) { + d_oversized++; + throw runtime_error((format("Can't handle a %d byte packet, have space for %d") % d_pheader.caplen % sizeof(d_buffer)).str()); + } + + checkedFreadSize(d_buffer, d_pheader.caplen); + + if(d_pheader.caplen < d_pheader.len) { + d_runts++; + continue; + } + + if (d_pheader.caplen < d_skipMediaHeader) { + d_runts++; + continue; + } + + d_ip=reinterpret_cast(d_buffer + d_skipMediaHeader); + d_ip6=reinterpret_cast(d_buffer + d_skipMediaHeader); + uint16_t contentCode=0; + + if(d_pfh.linktype==1) { + if (d_pheader.caplen < sizeof(*d_ether)) { + d_runts++; + continue; + } + d_ether=reinterpret_cast(d_buffer); + contentCode=ntohs(d_ether->ether_type); + } + else if(d_pfh.linktype==101) { + if (d_pheader.caplen < (d_skipMediaHeader + sizeof(*d_ip))) { + d_runts++; + continue; + } + if(d_ip->ip_v==4) + contentCode = 0x0800; + else + contentCode = 0x86dd; + } + else if(d_pfh.linktype==113) { + if (d_pheader.caplen < sizeof(*d_lcc)) { + d_runts++; + continue; + } + d_lcc=reinterpret_cast(d_buffer); + contentCode=ntohs(d_lcc->lcc_protocol); + } + + if(contentCode==0x0800 && (d_pheader.caplen >= (d_skipMediaHeader + sizeof(*d_ip))) && d_ip->ip_p==17) { // udp + if (d_pheader.caplen < (d_skipMediaHeader + (4 * d_ip->ip_hl) + sizeof(*d_udp))) { + d_runts++; + continue; + } + d_udp=reinterpret_cast(d_buffer + d_skipMediaHeader + 4 * d_ip->ip_hl); + d_payload = (unsigned char*)d_udp + sizeof(struct udphdr); + d_len = ntohs(d_udp->uh_ulen) - sizeof(struct udphdr); + if (d_pheader.caplen < (d_skipMediaHeader + (4 * d_ip->ip_hl) + sizeof(*d_udp) + d_len)) { + d_runts++; + continue; + } + if((const char*)d_payload + d_len > d_buffer + d_pheader.caplen) { + d_runts++; + continue; + } + d_correctpackets++; + return true; + } + else if(contentCode==0x86dd && (d_pheader.caplen >= (d_skipMediaHeader + sizeof(*d_ip6))) && d_ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt==17) { // udpv6, we ignore anything with extension hdr + if (d_pheader.caplen < (d_skipMediaHeader + sizeof(struct ip6_hdr) + sizeof(struct udphdr))) { + d_runts++; + continue; + } + d_udp=reinterpret_cast(d_buffer + d_skipMediaHeader + sizeof(struct ip6_hdr)); + d_payload = (unsigned char*)d_udp + sizeof(struct udphdr); + d_len = ntohs(d_udp->uh_ulen) - sizeof(struct udphdr); + if (d_pheader.caplen < (d_skipMediaHeader + sizeof(struct ip6_hdr) + sizeof(struct udphdr) + d_len)) { + d_runts++; + continue; + } + if((const char*)d_payload + d_len > d_buffer + d_pheader.caplen) { + d_runts++; + continue; + } + + d_correctpackets++; + return true; + } + else { + d_nonetheripudp++; + } + } +} +catch(const EofException&) { + return false; +} + +ComboAddress PcapPacketReader::getSource() const +{ + ComboAddress ret; + if(d_ip->ip_v == 4) { + ret.sin4.sin_family = AF_INET; + ret.sin4.sin_addr = d_ip->ip_src; + ret.sin4.sin_port = d_udp->uh_sport; // should deal with TCP too! + } else { + ret.sin6.sin6_family = AF_INET6; + ret.sin6.sin6_addr = d_ip6->ip6_src; + ret.sin6.sin6_port = d_udp->uh_sport; // should deal with TCP too! + } + return ret; +} + +ComboAddress PcapPacketReader::getDest() const +{ + ComboAddress ret; + if(d_ip->ip_v == 4) { + ret.sin4.sin_family = AF_INET; + ret.sin4.sin_addr = d_ip->ip_dst; + ret.sin4.sin_port = d_udp->uh_dport; // should deal with TCP too! + } else { + ret.sin6.sin6_family = AF_INET6; + ret.sin6.sin6_addr = d_ip6->ip6_dst; + ret.sin6.sin6_port = d_udp->uh_dport; // should deal with TCP too! + } + return ret; +} + +PcapPacketWriter::PcapPacketWriter(const string& fname, const PcapPacketReader& ppr) : PcapPacketWriter(fname) +{ + setPPR(ppr); +} + +PcapPacketWriter::PcapPacketWriter(const string& fname) : d_fname(fname) +{ + d_fp=fopen(fname.c_str(),"w"); + if(!d_fp) + unixDie("Unable to open file"); + + int flags=fcntl(fileno(d_fp),F_GETFL,0); + fcntl(fileno(d_fp), F_SETFL,flags&(~O_NONBLOCK)); // bsd needs this in stdin (??) +} + +void PcapPacketWriter::write() +{ + if (!d_ppr) { + return; + } + + if(d_first) { + fwrite(&d_ppr->d_pfh, 1, sizeof(d_ppr->d_pfh), d_fp); + d_first=false; + } + fwrite(&d_ppr->d_pheader, 1, sizeof(d_ppr->d_pheader), d_fp); + fwrite(d_ppr->d_buffer, 1, d_ppr->d_pheader.caplen, d_fp); +} + +PcapPacketWriter::~PcapPacketWriter() +{ + fclose(d_fp); +} diff --git a/pdns/dnspcap.hh b/pdns/dnspcap.hh new file mode 100644 index 0000000..0eade28 --- /dev/null +++ b/pdns/dnspcap.hh @@ -0,0 +1,147 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNSPCAP_HH +#define PDNS_DNSPCAP_HH + +#include +#include +#include "iputils.hh" +#include +#include "misc.hh" +#include +#define __FAVOR_BSD +#include +#include +#include +#include +#if defined(__NetBSD__) +#include +#include +#elif defined (__OpenBSD__) +#include +#include +#elif defined (__SVR4) && defined (__sun) +#include +#else +#include +#endif +#include +#include +#include "namespaces.hh" + +struct pdns_pcap_file_header { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + uint32_t thiszone; /* gmt to local correction */ + uint32_t sigfigs; /* accuracy of timestamps */ + uint32_t snaplen; /* max length saved portion of each pkt */ + uint32_t linktype; /* data link type (LINKTYPE_*) */ +}; + + +struct pdns_timeval +{ + uint32_t tv_sec{0}; + uint32_t tv_usec{0}; +}; + +struct pdns_pcap_pkthdr { + struct pdns_timeval ts; /* time stamp */ + uint32_t caplen{0}; /* length of portion present */ + uint32_t len{0}; /* length this packet (off wire) */ +}; + +struct pdns_lcc_header { + uint16_t lcc_pkttype;/* packet type */ + uint16_t lcc_hatype;/* link-layer address type */ + uint16_t lcc_halen;/* link-layer address length */ + uint8_t lcc_addr[8];/* link-layer address */ + uint16_t lcc_protocol;/* protocol */ +}; + +class PcapPacketReader +{ +public: + class EofException : public runtime_error + { + public: + EofException(const string& str="") : runtime_error(str) + { + } + }; + + PcapPacketReader(const string& fname); + + ~PcapPacketReader(); + + template + void checkedFread(T* ptr) + { + checkedFreadSize(ptr, sizeof(*ptr)); + } + + void checkedFreadSize(void* ptr, size_t size) ; + + bool getUDPPacket(); + + ComboAddress getSource() const; + ComboAddress getDest() const; + + struct pdns_lcc_header* d_lcc{nullptr}; + struct ether_header* d_ether{nullptr}; + struct ip *d_ip{nullptr}; + struct ip6_hdr *d_ip6{nullptr}; + const struct tcphdr *d_tcp{nullptr}; + const struct udphdr *d_udp{nullptr}; + const uint8_t* d_payload{nullptr}; + unsigned int d_len{0}; + struct pdns_pcap_pkthdr d_pheader; + + pdns_pcap_file_header d_pfh; + unsigned int d_runts, d_oversized, d_correctpackets, d_nonetheripudp; + char d_buffer[32768]; +private: + FILE* d_fp; + string d_fname; + unsigned int d_skipMediaHeader; +}; + +class PcapPacketWriter +{ +public: + PcapPacketWriter(const string& fname, const PcapPacketReader& ppr); + PcapPacketWriter(const string& fname); + + void write(); + void setPPR(const PcapPacketReader& ppr) { d_ppr = &ppr; } + ~PcapPacketWriter(); + +private: + string d_fname; + const PcapPacketReader* d_ppr{nullptr}; + + FILE *d_fp; + bool d_first{true}; +}; + +#endif // DNSPCAP_HH diff --git a/pdns/dnspcap2calidns.cc b/pdns/dnspcap2calidns.cc new file mode 100644 index 0000000..c64b1ae --- /dev/null +++ b/pdns/dnspcap2calidns.cc @@ -0,0 +1,121 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "iputils.hh" +#include "misc.hh" +#include "dns.hh" +#include "dnspcap.hh" +#include "dnsparser.hh" + +#include "statbag.hh" +StatBag S; + +static void usage() +{ + cerr<<"This program reads DNS queries from a PCAP file and outputs them in the calidns format."<(pr.d_payload); + if (!dh->qdcount) { + continue; + } + + if (!dh->rd) { + continue; + } + + if (dh->qr) { + continue; + } + + uint16_t qtype, qclass; + DNSName qname; + try { + qname=DNSName(reinterpret_cast(pr.d_payload), pr.d_len, sizeof(dnsheader), false, &qtype, &qclass); + } + catch(const std::exception& e) { + cerr<<"Error while parsing qname: "< + +#include "iputils.hh" +#include "misc.hh" +#include "protobuf.hh" +#include "dns.hh" +#include "dnspcap.hh" +#include "dnsparser.hh" +#include "protobuf.hh" +#include "uuid-utils.hh" + +#include "statbag.hh" +StatBag S; + +static void usage() +{ + cerr<<"This program reads DNS queries and responses from a PCAP file and stores them into our protobuf format."< > ids; + try { + while (pr.getUDPPacket()) { + const dnsheader* dh=(dnsheader*)pr.d_payload; + if (!dh->qdcount) + continue; + + if (pr.d_len < sizeof(dnsheader)) + continue; + + if(!dh->rd) + continue; + + uint16_t qtype, qclass; + DNSName qname; + try { + qname=DNSName((const char*)pr.d_payload, pr.d_len, sizeof(dnsheader), false, &qtype, &qclass); + } + catch(const std::exception& e) { + cerr<<"Error while parsing qname: "<qr) { + queryTime.tv_sec = pr.d_pheader.ts.tv_sec; + queryTime.tv_usec = pr.d_pheader.ts.tv_usec; + uniqueId = getUniqueID(); + ids[dh->id] = std::make_pair(uniqueId, queryTime); + } + else { + const auto& it = ids.find(dh->id); + if (it != ids.end()) { + uniqueId = it->second.first; + queryTime = it->second.second; + hasQueryTime = true; + } + else { + uniqueId = getUniqueID(); + } + } + + const ComboAddress requestor = dh->qr ? pr.getDest() : pr.getSource(); + const ComboAddress responder = dh->qr ? pr.getSource() : pr.getDest(); + *((char*)&requestor.sin4.sin_addr.s_addr)|=ind; + *((char*)&responder.sin4.sin_addr.s_addr)|=ind; + + DNSProtoBufMessage message(dh->qr ? DNSProtoBufMessage::DNSProtoBufMessageType::Response : DNSProtoBufMessage::DNSProtoBufMessageType::Query, uniqueId, &requestor, &responder, qname, qtype, qclass, dh->id, false, pr.d_len); + message.setTime(pr.d_pheader.ts.tv_sec, pr.d_pheader.ts.tv_usec); + + if (dh->qr) { + message.setResponseCode(dh->rcode); + if (hasQueryTime) { + message.setQueryTime(queryTime.tv_sec, queryTime.tv_usec); + } + + try { + message.addRRsFromPacket((const char*) dh, pr.d_len, true); + } + catch(std::exception& e) + { + cerr<<"Error parsing response records: "< +#include +#include "dns.hh" +#include "logger.hh" +#include "statbag.hh" +#include "dns_random.hh" +#include "stubresolver.hh" +#include "arguments.hh" +#include "threadname.hh" + +extern StatBag S; + +DNSProxy::DNSProxy(const string &remote) +{ + pthread_mutex_init(&d_lock,0); + d_resanswers=S.getPointer("recursing-answers"); + d_resquestions=S.getPointer("recursing-questions"); + d_udpanswers=S.getPointer("udp-answers"); + + vector addresses; + stringtok(addresses, remote, " ,\t"); + d_remote = ComboAddress(addresses[0], 53); + + if((d_sock=socket(d_remote.sin4.sin_family, SOCK_DGRAM,0))<0) { + throw PDNSException(string("socket: ")+strerror(errno)); + } + + ComboAddress local; + if(d_remote.sin4.sin_family==AF_INET) { + local = ComboAddress("0.0.0.0"); + } + else { + local = ComboAddress("::"); + } + + unsigned int n=0; + for(;n<10;n++) { + local.sin4.sin_port = htons(10000+dns_random(50000)); + + if(::bind(d_sock, (struct sockaddr *)&local, local.getSocklen()) >= 0) + break; + } + if(n==10) { + closesocket(d_sock); + d_sock=-1; + throw PDNSException(string("binding dnsproxy socket: ")+strerror(errno)); + } + + if(connect(d_sock, (sockaddr *)&d_remote, d_remote.getSocklen())<0) { + throw PDNSException("Unable to UDP connect to remote nameserver "+d_remote.toStringWithPort()+": "+stringerror()); + } + + d_xor=dns_random(0xffff); + g_log<qtype, plonk it in the answer section of 'r' with name aname +bool DNSProxy::completePacket(DNSPacket *r, const DNSName& target,const DNSName& aname, const uint8_t scopeMask) +{ + if(r->d_tcp) { + vector ips; + int ret1 = 0, ret2 = 0; + + if(r->qtype == QType::A || r->qtype == QType::ANY) + ret1 = stubDoResolve(target, QType::A, ips); + if(r->qtype == QType::AAAA || r->qtype == QType::ANY) + ret2 = stubDoResolve(target, QType::AAAA, ips); + + if(ret1 != RCode::NoError || ret2 != RCode::NoError) { + g_log<clearRecords(); + r->setRcode(RCode::ServFail); + } else { + for (auto &ip : ips) + { + ip.dr.d_name = aname; + r->addRecord(ip); + } + } + + uint16_t len=htons(r->getString().length()); + string buffer((const char*)&len, 2); + buffer.append(r->getString()); + writen2WithTimeout(r->getSocket(), buffer.c_str(), buffer.length(), ::arg().asNum("tcp-idle-timeout")); + + return true; + } + + uint16_t id; + { + Lock l(&d_lock); + id=getID_locked(); + + ConntrackEntry ce; + ce.id = r->d.id; + ce.remote = r->d_remote; + ce.outsock = r->getSocket(); + ce.created = time( NULL ); + ce.qtype = r->qtype.getCode(); + ce.qname = target; + ce.anyLocal = r->d_anyLocal; + ce.complete = r; + ce.aname=aname; + ce.anameScopeMask = scopeMask; + d_conntrack[id]=ce; + } + + vector packet; + DNSPacketWriter pw(packet, target, r->qtype.getCode()); + pw.getHeader()->rd=true; + pw.getHeader()->id=id ^ d_xor; + + if(send(d_sock,&packet[0], packet.size() , 0)<0) { // zoom + g_log<second.createdsecond.created) { + g_log<second.remote.toStringWithPort()<<" with internal id "<second.complete; + S.inc("recursion-unanswered"); + } + return n; + } + } +} + +void DNSProxy::mainloop(void) +{ + setThreadName("pdns/dnsproxy"); + try { + char buffer[1500]; + ssize_t len; + + struct msghdr msgh; + struct iovec iov; + char cbuf[256]; + ComboAddress fromaddr; + + for(;;) { + socklen_t fromaddrSize = sizeof(fromaddr); + len=recvfrom(d_sock, buffer, sizeof(buffer),0, (struct sockaddr*) &fromaddr, &fromaddrSize); // answer from our backend + if(len<(ssize_t)sizeof(dnsheader)) { + if(len<0) + g_log<second.id; + memcpy(buffer,&d,sizeof(d)); // commit spoofed id + + DNSPacket p(false),q(false); + p.parse(buffer,(size_t)len); + q.parse(buffer,(size_t)len); + + if(p.qtype.getCode() != i->second.qtype || p.qdomain != i->second.qname) { + g_log<second.qtype<<", "<second.qname<<")"<first.d_place-1<<" "<first.d_label<<" " << DNSRecordContent::NumberToType(j->first.d_type)<<" "<first.d_content->getZoneRepresentation()<first.d_place == DNSResourceRecord::ANSWER || (j->first.d_place == DNSResourceRecord::AUTHORITY && j->first.d_type == QType::SOA)) { + + if(j->first.d_type == i->second.qtype || (i->second.qtype == QType::ANY && (j->first.d_type == QType::A || j->first.d_type == QType::AAAA))) { + DNSZoneRecord dzr; + dzr.dr.d_name=i->second.aname; + dzr.dr.d_type = j->first.d_type; + dzr.dr.d_ttl=j->first.d_ttl; + dzr.dr.d_place= j->first.d_place; + dzr.dr.d_content=j->first.d_content; + i->second.complete->addRecord(dzr); + } + } + } + i->second.complete->setRcode(mdp.d_header.rcode); + } else { + g_log<second.aname<<" ALIAS "<second.qname<<" over UDP, "<second.qtype).getName()<<"-record query returned "<second.complete->clearRecords(); + i->second.complete->setRcode(RCode::ServFail); + } + reply=i->second.complete->getString(); + iov.iov_base = (void*)reply.c_str(); + iov.iov_len = reply.length(); + delete i->second.complete; + i->second.complete=0; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_name = (struct sockaddr*)&i->second.remote; + msgh.msg_namelen = i->second.remote.getSocklen(); + msgh.msg_control=NULL; + + if(i->second.anyLocal) { + addCMsgSrcAddr(&msgh, cbuf, i->second.anyLocal.get_ptr(), 0); + } + if(sendmsg(i->second.outsock, &msgh, 0) < 0) + g_log<second.created=0; + } + } + } + catch(PDNSException &ae) { + g_log<-1) { + try { + closesocket(d_sock); + } + catch(const PDNSException& e) { + } + } + + d_sock=-1; +} diff --git a/pdns/dnsproxy.hh b/pdns/dnsproxy.hh new file mode 100644 index 0000000..4478ef4 --- /dev/null +++ b/pdns/dnsproxy.hh @@ -0,0 +1,95 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNSPROXY +#define PDNS_DNSPROXY +#include +#include +#include +#include +#include +#include "dnspacket.hh" +#include "lock.hh" +#include "iputils.hh" + +#include "namespaces.hh" + +/** + +how will this work. + +This is a thread that just throws packets around. Should handle ~1000 packets/second. + +Consists of a thread receiving packets back from the backend and retransmitting them to the original client. + +Furthermore, it provides a member function that reports the packet to the connection tracker and actually sends it out. + +The sending happens from a source port that is determined by the constructor, but IS random. Furthermore, the ID is XOR-ed with a random value +to make sure outside parties can't spoof us. + +To fix: how to remove the stale entries that will surely accumulate +*/ + +class DNSProxy +{ +public: + DNSProxy(const string &ip); //!< creates socket + ~DNSProxy(); //(p)->mainloop(); + return 0; + } + bool recurseFor(DNSPacket* p); +private: + struct ConntrackEntry + { + time_t created; + boost::optional anyLocal; + DNSName qname; + DNSPacket* complete; + DNSName aname; + uint8_t anameScopeMask; + ComboAddress remote; + uint16_t id; + uint16_t qtype; + int outsock; + }; + + typedef map map_t; + + // Data + ComboAddress d_remote; + AtomicCounter* d_resanswers; + AtomicCounter* d_udpanswers; + AtomicCounter* d_resquestions; + pthread_mutex_t d_lock; + map_t d_conntrack; + int d_sock; + int getID_locked(); + uint16_t d_xor; +}; + +#endif diff --git a/pdns/dnsrecords.cc b/pdns/dnsrecords.cc new file mode 100644 index 0000000..aa5ae30 --- /dev/null +++ b/pdns/dnsrecords.cc @@ -0,0 +1,708 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include "dnsrecords.hh" +#include "iputils.hh" + + +void DNSResourceRecord::setContent(const string &cont) { + content = cont; + switch(qtype.getCode()) { + case QType::SRV: + case QType::MX: + if (content.size() >= 2 && *(content.rbegin()+1) == ' ') + return; + /* Falls through. */ + case QType::CNAME: + case QType::DNAME: + case QType::NS: + case QType::PTR: + if (content.size() >= 2 && *(content.rbegin()) == '.') + boost::erase_tail(content, 1); + } +} + +string DNSResourceRecord::getZoneRepresentation(bool noDot) const { + ostringstream ret; + vector parts; + string last; + + switch(qtype.getCode()) { + case QType::SRV: + case QType::MX: + stringtok(parts, content); + if (!parts.size()) + return ""; + last = *parts.rbegin(); + ret << content; + if (last == ".") + break; + if (*(last.rbegin()) != '.' && !noDot) + ret << "."; + break; + case QType::CNAME: + case QType::DNAME: + case QType::NS: + case QType::PTR: + ret< parts; + stringtok(parts, d_code, "\""); + string ret; + for(const auto& p : parts) { + ret += p; + ret.append(1, ' '); + } + return ret; +} +#endif + +void OPTRecordContent::getData(vector >& options) +{ + string::size_type pos=0; + uint16_t code, len; + while(d_data.size() >= 4 + pos) { + code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1]; + len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3]; + pos+=4; + + if(pos + len > d_data.size()) + break; + + string field(d_data.c_str() + pos, len); + pos+=len; + options.push_back(make_pair(code, field)); + } +} + +boilerplate_conv(TSIG, QType::TSIG, + conv.xfrName(d_algoName); + conv.xfr48BitInt(d_time); + conv.xfr16BitInt(d_fudge); + uint16_t size=d_mac.size(); + conv.xfr16BitInt(size); + if (size>0) conv.xfrBlobNoSpaces(d_mac, size); + conv.xfr16BitInt(d_origID); + conv.xfr16BitInt(d_eRcode); + size=d_otherData.size(); + conv.xfr16BitInt(size); + if (size>0) conv.xfrBlobNoSpaces(d_otherData, size); + ); + +MXRecordContent::MXRecordContent(uint16_t preference, const DNSName& mxname): d_preference(preference), d_mxname(mxname) +{ +} + +boilerplate_conv(MX, QType::MX, + conv.xfr16BitInt(d_preference); + conv.xfrName(d_mxname, true); + ) + +boilerplate_conv(KX, QType::KX, + conv.xfr16BitInt(d_preference); + conv.xfrName(d_exchanger, false); + ) + +boilerplate_conv(IPSECKEY, QType::IPSECKEY, + conv.xfr8BitInt(d_preference); + conv.xfr8BitInt(d_gatewaytype); + conv.xfr8BitInt(d_algorithm); + + // now we need to determine values + switch(d_gatewaytype) { + case 0: // NO KEY + break; + case 1: // IPv4 GW + conv.xfrIP(d_ip4); + break; + case 2: // IPv6 GW + conv.xfrIP6(d_ip6); + break; + case 3: // DNS label + conv.xfrName(d_gateway, false); + break; + default: + throw MOADNSException("Parsing record content: invalid gateway type"); + }; + + switch(d_algorithm) { + case 0: + break; + case 1: + case 2: + conv.xfrBlob(d_publickey); + break; + default: + throw MOADNSException("Parsing record content: invalid algorithm type"); + } +) + +boilerplate_conv(DHCID, 49, + conv.xfrBlob(d_content); + ) + + +boilerplate_conv(AFSDB, QType::AFSDB, + conv.xfr16BitInt(d_subtype); + conv.xfrName(d_hostname); + ) + + +boilerplate_conv(NAPTR, QType::NAPTR, + conv.xfr16BitInt(d_order); conv.xfr16BitInt(d_preference); + conv.xfrText(d_flags); conv.xfrText(d_services); conv.xfrText(d_regexp); + conv.xfrName(d_replacement); + ) + + +SRVRecordContent::SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const DNSName& target) +: d_weight(weight), d_port(port), d_target(target), d_preference(preference) +{} + +boilerplate_conv(SRV, QType::SRV, + conv.xfr16BitInt(d_preference); conv.xfr16BitInt(d_weight); conv.xfr16BitInt(d_port); + conv.xfrName(d_target); + ) + +SOARecordContent::SOARecordContent(const DNSName& mname, const DNSName& rname, const struct soatimes& st) +: d_mname(mname), d_rname(rname), d_st(st) +{ +} + +boilerplate_conv(SOA, QType::SOA, + conv.xfrName(d_mname, true); + conv.xfrName(d_rname, true); + conv.xfr32BitInt(d_st.serial); + conv.xfr32BitInt(d_st.refresh); + conv.xfr32BitInt(d_st.retry); + conv.xfr32BitInt(d_st.expire); + conv.xfr32BitInt(d_st.minimum); + ); +#undef KEY +boilerplate_conv(KEY, QType::KEY, + conv.xfr16BitInt(d_flags); + conv.xfr8BitInt(d_protocol); + conv.xfr8BitInt(d_algorithm); + conv.xfrBlob(d_certificate); + ); + +boilerplate_conv(CERT, 37, + conv.xfr16BitInt(d_type); + if (d_type == 0) throw MOADNSException("CERT type 0 is reserved"); + + conv.xfr16BitInt(d_tag); + conv.xfr8BitInt(d_algorithm); + conv.xfrBlob(d_certificate); + ) + +boilerplate_conv(TLSA, 52, + conv.xfr8BitInt(d_certusage); + conv.xfr8BitInt(d_selector); + conv.xfr8BitInt(d_matchtype); + conv.xfrHexBlob(d_cert, true); + ) + +boilerplate_conv(OPENPGPKEY, 61, + conv.xfrBlob(d_keyring); + ) + +boilerplate_conv(SMIMEA, 53, + conv.xfr8BitInt(d_certusage); + conv.xfr8BitInt(d_selector); + conv.xfr8BitInt(d_matchtype); + conv.xfrHexBlob(d_cert, true); + ) + +DSRecordContent::DSRecordContent() {} +boilerplate_conv(DS, 43, + conv.xfr16BitInt(d_tag); + conv.xfr8BitInt(d_algorithm); + conv.xfr8BitInt(d_digesttype); + conv.xfrHexBlob(d_digest, true); // keep reading across spaces + ) + +CDSRecordContent::CDSRecordContent() {} +boilerplate_conv(CDS, 59, + conv.xfr16BitInt(d_tag); + conv.xfr8BitInt(d_algorithm); + conv.xfr8BitInt(d_digesttype); + conv.xfrHexBlob(d_digest, true); // keep reading across spaces + ) + +DLVRecordContent::DLVRecordContent() {} +boilerplate_conv(DLV,32769 , + conv.xfr16BitInt(d_tag); + conv.xfr8BitInt(d_algorithm); + conv.xfr8BitInt(d_digesttype); + conv.xfrHexBlob(d_digest, true); // keep reading across spaces + ) + + +boilerplate_conv(SSHFP, 44, + conv.xfr8BitInt(d_algorithm); + conv.xfr8BitInt(d_fptype); + conv.xfrHexBlob(d_fingerprint, true); + ) + +boilerplate_conv(RRSIG, 46, + conv.xfrType(d_type); + conv.xfr8BitInt(d_algorithm); + conv.xfr8BitInt(d_labels); + conv.xfr32BitInt(d_originalttl); + conv.xfrTime(d_sigexpire); + conv.xfrTime(d_siginception); + conv.xfr16BitInt(d_tag); + conv.xfrName(d_signer); + conv.xfrBlob(d_signature); + ) + +RRSIGRecordContent::RRSIGRecordContent() {} + +boilerplate_conv(DNSKEY, 48, + conv.xfr16BitInt(d_flags); + conv.xfr8BitInt(d_protocol); + conv.xfr8BitInt(d_algorithm); + conv.xfrBlob(d_key); + ) +DNSKEYRecordContent::DNSKEYRecordContent() {} + +boilerplate_conv(CDNSKEY, 60, + conv.xfr16BitInt(d_flags); + conv.xfr8BitInt(d_protocol); + conv.xfr8BitInt(d_algorithm); + conv.xfrBlob(d_key); + ) +CDNSKEYRecordContent::CDNSKEYRecordContent() {} + +boilerplate_conv(RKEY, 57, + conv.xfr16BitInt(d_flags); + conv.xfr8BitInt(d_protocol); + conv.xfr8BitInt(d_algorithm); + conv.xfrBlob(d_key); + ) +RKEYRecordContent::RKEYRecordContent() {} + +/* EUI48 start */ +void EUI48RecordContent::report(void) +{ + regist(1, QType::EUI48, &make, &make, "EUI48"); +} +std::shared_ptr EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + if(dr.d_clen!=6) + throw MOADNSException("Wrong size for EUI48 record"); + + auto ret=std::make_shared(); + pr.copyRecord((uint8_t*) &ret->d_eui48, 6); + return ret; +} +std::shared_ptr EUI48RecordContent::make(const string& zone) +{ + // try to parse + auto ret=std::make_shared(); + // format is 6 hex bytes and dashes + if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", + ret->d_eui48, ret->d_eui48+1, ret->d_eui48+2, + ret->d_eui48+3, ret->d_eui48+4, ret->d_eui48+5) != 6) { + throw MOADNSException("Asked to encode '"+zone+"' as an EUI48 address, but does not parse"); + } + return ret; +} +void EUI48RecordContent::toPacket(DNSPacketWriter& pw) +{ + string blob(d_eui48, d_eui48+6); + pw.xfrBlob(blob); +} +string EUI48RecordContent::getZoneRepresentation(bool noDot) const +{ + char tmp[18]; + snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x", + d_eui48[0], d_eui48[1], d_eui48[2], + d_eui48[3], d_eui48[4], d_eui48[5]); + return tmp; +} + +/* EUI48 end */ + +/* EUI64 start */ + +void EUI64RecordContent::report(void) +{ + regist(1, QType::EUI64, &make, &make, "EUI64"); +} +std::shared_ptr EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + if(dr.d_clen!=8) + throw MOADNSException("Wrong size for EUI64 record"); + + auto ret=std::make_shared(); + pr.copyRecord((uint8_t*) &ret->d_eui64, 8); + return ret; +} +std::shared_ptr EUI64RecordContent::make(const string& zone) +{ + // try to parse + auto ret=std::make_shared(); + // format is 8 hex bytes and dashes + if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", + ret->d_eui64, ret->d_eui64+1, ret->d_eui64+2, + ret->d_eui64+3, ret->d_eui64+4, ret->d_eui64+5, + ret->d_eui64+6, ret->d_eui64+7) != 8) { + throw MOADNSException("Asked to encode '"+zone+"' as an EUI64 address, but does not parse"); + } + return ret; +} +void EUI64RecordContent::toPacket(DNSPacketWriter& pw) +{ + string blob(d_eui64, d_eui64+8); + pw.xfrBlob(blob); +} +string EUI64RecordContent::getZoneRepresentation(bool noDot) const +{ + char tmp[24]; + snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", + d_eui64[0], d_eui64[1], d_eui64[2], + d_eui64[3], d_eui64[4], d_eui64[5], + d_eui64[6], d_eui64[7]); + return tmp; +} + +/* EUI64 end */ + +boilerplate_conv(TKEY, QType::TKEY, + conv.xfrName(d_algo); + conv.xfr32BitInt(d_inception); + conv.xfr32BitInt(d_expiration); + conv.xfr16BitInt(d_mode); + conv.xfr16BitInt(d_error); + conv.xfr16BitInt(d_keysize); + if (d_keysize>0) conv.xfrBlobNoSpaces(d_key, d_keysize); + conv.xfr16BitInt(d_othersize); + if (d_othersize>0) conv.xfrBlobNoSpaces(d_other, d_othersize); + ) +TKEYRecordContent::TKEYRecordContent() { d_othersize = 0; } // fix CID#1288932 + +boilerplate_conv(URI, QType::URI, + conv.xfr16BitInt(d_priority); + conv.xfr16BitInt(d_weight); + conv.xfrText(d_target, true, false); + ) + +boilerplate_conv(CAA, QType::CAA, + conv.xfr8BitInt(d_flags); + conv.xfrUnquotedText(d_tag, true); + conv.xfrText(d_value, true, false); /* no lenField */ + ) + +static uint16_t makeTag(const std::string& data) +{ + const unsigned char* key=(const unsigned char*)data.c_str(); + unsigned int keysize=data.length(); + + unsigned long ac; /* assumed to be 32 bits or larger */ + unsigned int i; /* loop index */ + + for ( ac = 0, i = 0; i < keysize; ++i ) + ac += (i & 1) ? key[i] : key[i] << 8; + ac += (ac >> 16) & 0xFFFF; + return ac & 0xFFFF; +} + +uint16_t DNSKEYRecordContent::getTag() const +{ + DNSKEYRecordContent tmp(*this); + return makeTag(tmp.serialize(DNSName())); // this can't be const for some reason +} + +uint16_t DNSKEYRecordContent::getTag() +{ + return makeTag(this->serialize(DNSName())); +} + + +/* + * Fills `eo` by parsing the EDNS(0) OPT RR (RFC 6891) + */ +bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo) +{ + eo->d_extFlags=0; + if(mdp.d_header.arcount && !mdp.d_answers.empty()) { + for(const MOADNSParser::answers_t::value_type& val : mdp.d_answers) { + if(val.first.d_place == DNSResourceRecord::ADDITIONAL && val.first.d_type == QType::OPT) { + eo->d_packetsize=val.first.d_class; + + EDNS0Record stuff; + uint32_t ttl=ntohl(val.first.d_ttl); + static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t)"); + memcpy(&stuff, &ttl, sizeof(stuff)); + + eo->d_extRCode=stuff.extRCode; + eo->d_version=stuff.version; + eo->d_extFlags = ntohs(stuff.extFlags); + auto orc = getRR(val.first); + if(orc == nullptr) + return false; + orc->getData(eo->d_options); + return true; + } + } + } + return false; +} + +DNSRecord makeOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t extFlags) +{ + EDNS0Record stuff; + stuff.extRCode=0; + stuff.version=0; + stuff.extFlags=htons(extFlags); + DNSRecord dr; + static_assert(sizeof(EDNS0Record) == sizeof(dr.d_ttl), "sizeof(EDNS0Record) must match sizeof(DNSRecord.d_ttl)"); + memcpy(&dr.d_ttl, &stuff, sizeof(stuff)); + dr.d_ttl=ntohl(dr.d_ttl); + dr.d_name=g_rootdnsname; + dr.d_type = QType::OPT; + dr.d_class=udpsize; + dr.d_place=DNSResourceRecord::ADDITIONAL; + dr.d_content = std::make_shared(); + // if we ever do options, I think we stuff them into OPTRecordContent::data + return dr; +} + +void reportBasicTypes() +{ + ARecordContent::report(); + AAAARecordContent::report(); + NSRecordContent::report(); + CNAMERecordContent::report(); + MXRecordContent::report(); + SOARecordContent::report(); + SRVRecordContent::report(); + PTRRecordContent::report(); + DNSRecordContent::regist(QClass::CHAOS, QType::TXT, &TXTRecordContent::make, &TXTRecordContent::make, "TXT"); + TXTRecordContent::report(); +#ifdef HAVE_LUA_RECORDS + LUARecordContent::report(); +#endif + DNSRecordContent::regist(QClass::IN, QType::ANY, 0, 0, "ANY"); + DNSRecordContent::regist(QClass::IN, QType::AXFR, 0, 0, "AXFR"); + DNSRecordContent::regist(QClass::IN, QType::IXFR, 0, 0, "IXFR"); +} + +void reportOtherTypes() +{ + MBRecordContent::report(); + MGRecordContent::report(); + MRRecordContent::report(); + AFSDBRecordContent::report(); + DNAMERecordContent::report(); + ALIASRecordContent::report(); + SPFRecordContent::report(); + NAPTRRecordContent::report(); + KXRecordContent::report(); + LOCRecordContent::report(); + ENTRecordContent::report(); + HINFORecordContent::report(); + RPRecordContent::report(); + KEYRecordContent::report(); + DNSKEYRecordContent::report(); + DHCIDRecordContent::report(); + CDNSKEYRecordContent::report(); + RKEYRecordContent::report(); + RRSIGRecordContent::report(); + DSRecordContent::report(); + CDSRecordContent::report(); + SSHFPRecordContent::report(); + CERTRecordContent::report(); + NSECRecordContent::report(); + NSEC3RecordContent::report(); + NSEC3PARAMRecordContent::report(); + TLSARecordContent::report(); + SMIMEARecordContent::report(); + OPENPGPKEYRecordContent::report(); + DLVRecordContent::report(); + DNSRecordContent::regist(QClass::ANY, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG"); + DNSRecordContent::regist(QClass::ANY, QType::TKEY, &TKEYRecordContent::make, &TKEYRecordContent::make, "TKEY"); + //TSIGRecordContent::report(); + OPTRecordContent::report(); + EUI48RecordContent::report(); + EUI64RecordContent::report(); + MINFORecordContent::report(); + URIRecordContent::report(); + CAARecordContent::report(); +} + +void reportAllTypes() +{ + reportBasicTypes(); + reportOtherTypes(); +} + +ComboAddress getAddr(const DNSRecord& dr, uint16_t defport) +{ + if(auto addr=getRR(dr)) { + return addr->getCA(defport); + } + else + return getRR(dr)->getCA(defport); +} + +/** + * Check if the DNSNames that should be hostnames, are hostnames + */ +void checkHostnameCorrectness(const DNSResourceRecord& rr) +{ + if (rr.qtype.getCode() == QType::NS || rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) { + DNSName toCheck; + if (rr.qtype.getCode() == QType::SRV) { + vector parts; + stringtok(parts, rr.getZoneRepresentation()); + if (parts.size() == 4) toCheck = DNSName(parts[3]); + } else if (rr.qtype.getCode() == QType::MX) { + vector parts; + stringtok(parts, rr.getZoneRepresentation()); + if (parts.size() == 2) toCheck = DNSName(parts[1]); + } else { + toCheck = DNSName(rr.content); + } + + if (toCheck.empty()) { + throw std::runtime_error("unable to extract hostname from content"); + } + else if ((rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) && toCheck == g_rootdnsname) { + // allow null MX/SRV + } else if(!toCheck.isHostname()) { + throw std::runtime_error(boost::str(boost::format("non-hostname content %s") % toCheck.toString())); + } + } +} + +#if 0 +static struct Reporter +{ + Reporter() + { + reportAllTypes(); + } +} reporter __attribute__((init_priority(65535))); +#endif diff --git a/pdns/dnsrecords.hh b/pdns/dnsrecords.hh new file mode 100644 index 0000000..1031ddf --- /dev/null +++ b/pdns/dnsrecords.hh @@ -0,0 +1,906 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNSRECORDS_HH +#define PDNS_DNSRECORDS_HH + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dnsparser.hh" +#include "dnswriter.hh" +#include "rcpgenerator.hh" +#include +#include +#include "namespaces.hh" +#include "iputils.hh" + +#define includeboilerplate(RNAME) RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr); \ + RNAME##RecordContent(const string& zoneData); \ + static void report(void); \ + static void unreport(void); \ + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); \ + static std::shared_ptr make(const string& zonedata); \ + string getZoneRepresentation(bool noDot=false) const override; \ + void toPacket(DNSPacketWriter& pw) override; \ + uint16_t getType() const override { return QType::RNAME; } \ + template void xfrPacket(Convertor& conv, bool noDot=false); + +class NAPTRRecordContent : public DNSRecordContent +{ +public: + NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement); + + includeboilerplate(NAPTR) + template void xfrRecordContent(Convertor& conv); +private: + uint16_t d_order, d_preference; + string d_flags, d_services, d_regexp; + DNSName d_replacement; +}; + + +class ARecordContent : public DNSRecordContent +{ +public: + explicit ARecordContent(const ComboAddress& ca); + explicit ARecordContent(uint32_t ip); + includeboilerplate(A) + void doRecordCheck(const DNSRecord& dr); + ComboAddress getCA(int port=0) const; + bool operator==(const DNSRecordContent& rhs) const override + { + if(typeid(*this) != typeid(rhs)) + return false; + return d_ip == dynamic_cast(rhs).d_ip; + } +private: + uint32_t d_ip; +}; + +class AAAARecordContent : public DNSRecordContent +{ +public: + AAAARecordContent(std::string &val); + explicit AAAARecordContent(const ComboAddress& ca); + includeboilerplate(AAAA) + ComboAddress getCA(int port=0) const; + bool operator==(const DNSRecordContent& rhs) const override + { + if(typeid(*this) != typeid(rhs)) + return false; + return d_ip6 == dynamic_cast(&rhs)->d_ip6; + } +private: + string d_ip6; // why?? +}; + +class MXRecordContent : public DNSRecordContent +{ +public: + MXRecordContent(uint16_t preference, const DNSName& mxname); + + includeboilerplate(MX) + + uint16_t d_preference; + DNSName d_mxname; + + bool operator==(const DNSRecordContent& rhs) const override + { + if(typeid(*this) != typeid(rhs)) + return false; + auto rrhs =dynamic_cast(&rhs); + return std::tie(d_preference, d_mxname) == std::tie(rrhs->d_preference, rrhs->d_mxname); + } + +}; + +class KXRecordContent : public DNSRecordContent +{ +public: + KXRecordContent(uint16_t preference, const DNSName& exchanger); + + includeboilerplate(KX) + +private: + uint16_t d_preference; + DNSName d_exchanger; +}; + +class IPSECKEYRecordContent : public DNSRecordContent +{ +public: + IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey); + + includeboilerplate(IPSECKEY) + +private: + uint32_t d_ip4; + DNSName d_gateway; + string d_publickey; + string d_ip6; + uint8_t d_preference, d_gatewaytype, d_algorithm; +}; + +class DHCIDRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(DHCID) + +private: + string d_content; +}; + + +class SRVRecordContent : public DNSRecordContent +{ +public: + SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const DNSName& target); + + includeboilerplate(SRV) + + uint16_t d_weight, d_port; + DNSName d_target; + uint16_t d_preference; +}; + +class TSIGRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(TSIG) + TSIGRecordContent() {} + + uint16_t d_origID{0}; + uint16_t d_fudge{0}; + + DNSName d_algoName; + string d_mac; + string d_otherData; + uint64_t d_time{0}; + // uint16_t d_macSize; + uint16_t d_eRcode{0}; + // uint16_t d_otherLen +}; + + +class TXTRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(TXT) + + string d_text; +}; + +#ifdef HAVE_LUA_RECORDS +class LUARecordContent : public DNSRecordContent +{ +public: + includeboilerplate(LUA) + string getCode() const; + uint16_t d_type; + string d_code; +}; +#endif + +class ENTRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(ENT) +}; + +class SPFRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(SPF) + const std::string& getText() const + { + return d_text; + } + +private: + string d_text; +}; + + +class NSRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(NS) + explicit NSRecordContent(const DNSName& content) : d_content(content){} + const DNSName& getNS() const { return d_content; } + bool operator==(const DNSRecordContent& rhs) const override + { + if(typeid(*this) != typeid(rhs)) + return false; + auto rrhs =dynamic_cast(&rhs); + return d_content == rrhs->d_content; + } + +private: + DNSName d_content; +}; + +class PTRRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(PTR) + explicit PTRRecordContent(const DNSName& content) : d_content(content){} + const DNSName& getContent() const { return d_content; } +private: + DNSName d_content; +}; + +class CNAMERecordContent : public DNSRecordContent +{ +public: + includeboilerplate(CNAME) + CNAMERecordContent(const DNSName& content) : d_content(content){} + DNSName getTarget() const { return d_content; } +private: + DNSName d_content; +}; + +class ALIASRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(ALIAS) + + DNSName d_content; +}; + + +class DNAMERecordContent : public DNSRecordContent +{ +public: + includeboilerplate(DNAME) + DNAMERecordContent(const DNSName& content) : d_content(content){} + const DNSName& getTarget() const { return d_content; } +private: + DNSName d_content; +}; + + +class MBRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(MB) + +private: + DNSName d_madname; +}; + +class MGRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(MG) + +private: + DNSName d_mgmname; +}; + +class MRRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(MR) + +private: + DNSName d_alias; +}; + +class MINFORecordContent : public DNSRecordContent +{ +public: + includeboilerplate(MINFO) + +private: + DNSName d_rmailbx; + DNSName d_emailbx; +}; + +class OPTRecordContent : public DNSRecordContent +{ +public: + OPTRecordContent(){} + includeboilerplate(OPT) + void getData(vector > &opts); +private: + string d_data; +}; + + +class HINFORecordContent : public DNSRecordContent +{ +public: + includeboilerplate(HINFO) + +private: + string d_cpu, d_host; +}; + +class RPRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(RP) + +private: + DNSName d_mbox, d_info; +}; + + +class DNSKEYRecordContent : public DNSRecordContent +{ +public: + DNSKEYRecordContent(); + includeboilerplate(DNSKEY) + uint16_t getTag() const; + uint16_t getTag(); + + uint16_t d_flags{0}; + uint8_t d_protocol{0}; + uint8_t d_algorithm{0}; + string d_key; + bool operator<(const DNSKEYRecordContent& rhs) const + { + return tie(d_flags, d_protocol, d_algorithm, d_key) < + tie(rhs.d_flags, rhs.d_protocol, rhs.d_algorithm, rhs.d_key); + } +}; + +class CDNSKEYRecordContent : public DNSRecordContent +{ +public: + CDNSKEYRecordContent(); + includeboilerplate(CDNSKEY) + uint16_t getTag(); + + uint16_t d_flags{0}; + uint8_t d_protocol{0}; + uint8_t d_algorithm{0}; + string d_key; +}; + +class DSRecordContent : public DNSRecordContent +{ +public: + DSRecordContent(); + bool operator==(const DNSRecordContent& rhs) const override + { + if(typeid(*this) != typeid(rhs)) + return false; + auto rrhs =dynamic_cast(&rhs); + return tie(d_tag, d_algorithm, d_digesttype, d_digest) == + tie(rrhs->d_tag, rrhs->d_algorithm, rrhs->d_digesttype, rrhs->d_digest); + } + bool operator<(const DSRecordContent& rhs) const + { + return tie(d_tag, d_algorithm, d_digesttype, d_digest) < + tie(rhs.d_tag, rhs.d_algorithm, rhs.d_digesttype, rhs.d_digest); + } + + includeboilerplate(DS) + + uint16_t d_tag{0}; + uint8_t d_algorithm{0}, d_digesttype{0}; + string d_digest; +}; + +class CDSRecordContent : public DNSRecordContent +{ +public: + CDSRecordContent(); + includeboilerplate(CDS) + + uint16_t d_tag{0}; + uint8_t d_algorithm{0}, d_digesttype{0}; + string d_digest; +}; + +class DLVRecordContent : public DNSRecordContent +{ +public: + DLVRecordContent(); + includeboilerplate(DLV) + + uint16_t d_tag{0}; + uint8_t d_algorithm{0}, d_digesttype{0}; + string d_digest; +}; + + +class SSHFPRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(SSHFP) + +private: + uint8_t d_algorithm, d_fptype; + string d_fingerprint; +}; + +class KEYRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(KEY) + +private: + uint16_t d_flags; + uint8_t d_protocol, d_algorithm; + string d_certificate; +}; + +class AFSDBRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(AFSDB) + +private: + uint16_t d_subtype; + DNSName d_hostname; +}; + + +class CERTRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(CERT) + +private: + uint16_t d_type, d_tag; + string d_certificate; + uint8_t d_algorithm; +}; + +class TLSARecordContent : public DNSRecordContent +{ +public: + includeboilerplate(TLSA) + +private: + uint8_t d_certusage, d_selector, d_matchtype; + string d_cert; +}; + +class SMIMEARecordContent : public DNSRecordContent +{ +public: + includeboilerplate(SMIMEA) + +private: + uint8_t d_certusage, d_selector, d_matchtype; + string d_cert; +}; + +class OPENPGPKEYRecordContent : public DNSRecordContent +{ +public: + includeboilerplate(OPENPGPKEY) + +private: + string d_keyring; +}; + + +class RRSIGRecordContent : public DNSRecordContent +{ +public: + RRSIGRecordContent(); + includeboilerplate(RRSIG) + + uint16_t d_type{0}; + uint16_t d_tag{0}; + DNSName d_signer; + string d_signature; + uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0}; + uint8_t d_algorithm{0}, d_labels{0}; +}; + +//namespace { + struct soatimes + { + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; + }; +//} + +class RKEYRecordContent : public DNSRecordContent +{ +public: + RKEYRecordContent(); + includeboilerplate(RKEY) + uint16_t d_flags{0}; + uint8_t d_protocol{0}, d_algorithm{0}; + string d_key; +}; + +class SOARecordContent : public DNSRecordContent +{ +public: + includeboilerplate(SOA) + SOARecordContent(const DNSName& mname, const DNSName& rname, const struct soatimes& st); + + DNSName d_mname; + DNSName d_rname; + struct soatimes d_st; +}; + +class NSECBitmap +{ +public: + NSECBitmap(): d_bitset(nullptr) + { + } + NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set) + { + if (rhs.d_bitset) { + d_bitset = std::unique_ptr>(new std::bitset(*(rhs.d_bitset))); + } + } + NSECBitmap& operator=(const NSECBitmap& rhs) + { + d_set = rhs.d_set; + + if (rhs.d_bitset) { + d_bitset = std::unique_ptr>(new std::bitset(*(rhs.d_bitset))); + } + + return *this; + } + NSECBitmap(NSECBitmap&& rhs): d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set)) + { + } + bool isSet(uint16_t type) const + { + if (d_bitset) { + return d_bitset->test(type); + } + return d_set.count(type); + } + void set(uint16_t type) + { + if (!d_bitset) { + if (d_set.size() >= 200) { + migrateToBitSet(); + } + } + if (d_bitset) { + d_bitset->set(type); + } + else { + d_set.insert(type); + } + } + size_t count() const + { + if (d_bitset) { + return d_bitset->count(); + } + else { + return d_set.size(); + } + } + + void fromPacket(PacketReader& pr); + void toPacket(DNSPacketWriter& pw); + std::string getZoneRepresentation() const; + + static constexpr size_t const nbTypes = 65536; + +private: + + void migrateToBitSet() + { + d_bitset = std::unique_ptr>(new std::bitset()); + for (const auto& type : d_set) { + d_bitset->set(type); + } + d_set.clear(); + } + /* using a dynamic set is very efficient for a small number of + types covered (~200), but uses a lot of memory (up to 3MB) + when there are a lot of them. + So we start with the set, but allocate and switch to a bitset + if the number of covered types increases a lot */ + std::unique_ptr> d_bitset; + std::set d_set; +}; + +class NSECRecordContent : public DNSRecordContent +{ +public: + static void report(void); + NSECRecordContent() + {} + NSECRecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone? + + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override + { + return QType::NSEC; + } + bool isSet(uint16_t type) const + { + return d_bitmap.isSet(type); + } + void set(uint16_t type) + { + d_bitmap.set(type); + } + void set(const NSECBitmap& bitmap) + { + d_bitmap = bitmap; + } + size_t numberOfTypesSet() const + { + return d_bitmap.count(); + } + + DNSName d_next; +private: + NSECBitmap d_bitmap; +}; + +class NSEC3RecordContent : public DNSRecordContent +{ +public: + static void report(void); + NSEC3RecordContent() + {} + NSEC3RecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone? + + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + + uint8_t d_algorithm{0}, d_flags{0}; + uint16_t d_iterations{0}; + string d_salt; + string d_nexthash; + + uint16_t getType() const override + { + return QType::NSEC3; + } + bool isSet(uint16_t type) const + { + return d_bitmap.isSet(type); + } + void set(uint16_t type) + { + d_bitmap.set(type); + } + void set(const NSECBitmap& bitmap) + { + d_bitmap = bitmap; + } + size_t numberOfTypesSet() const + { + return d_bitmap.count(); + } + +private: + NSECBitmap d_bitmap; +}; + + +class NSEC3PARAMRecordContent : public DNSRecordContent +{ +public: + static void report(void); + NSEC3PARAMRecordContent() + {} + NSEC3PARAMRecordContent(const string& content, const string& zone=""); // FIXME400: DNSName& zone? + + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + + uint16_t getType() const override + { + return QType::NSEC3PARAM; + } + + + uint8_t d_algorithm{0}, d_flags{0}; + uint16_t d_iterations{0}; + string d_salt; +}; + + +class LOCRecordContent : public DNSRecordContent +{ +public: + static void report(void); + LOCRecordContent() + {} + LOCRecordContent(const string& content, const string& zone=""); + + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + + uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0}; + uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0}; + uint16_t getType() const override + { + return QType::LOC; + } + +private: +}; + +class EUI48RecordContent : public DNSRecordContent +{ +public: + EUI48RecordContent() {}; + static void report(void); + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& zone); // FIXME400: DNSName& zone? + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override { return QType::EUI48; } +private: + // storage for the bytes + uint8_t d_eui48[6]; +}; + +class EUI64RecordContent : public DNSRecordContent +{ +public: + EUI64RecordContent() {}; + static void report(void); + static std::shared_ptr make(const DNSRecord &dr, PacketReader& pr); + static std::shared_ptr make(const string& zone); // FIXME400: DNSName& zone? + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override { return QType::EUI64; } +private: + // storage for the bytes + uint8_t d_eui64[8]; +}; + +class TKEYRecordContent : public DNSRecordContent +{ +public: + TKEYRecordContent(); + includeboilerplate(TKEY) + + // storage for the bytes + uint16_t d_othersize{0}; + uint16_t d_mode{0}; + uint32_t d_inception{0}; + uint32_t d_expiration{0}; + + DNSName d_algo; + string d_key; + string d_other; + + uint16_t d_error{0}; + uint16_t d_keysize{0}; +private: +}; + +class URIRecordContent : public DNSRecordContent { + public: + includeboilerplate(URI) + private: + uint16_t d_priority, d_weight; + string d_target; +}; + +class CAARecordContent : public DNSRecordContent { + public: + includeboilerplate(CAA) + private: + uint8_t d_flags; + string d_tag, d_value; +}; + +#define boilerplate(RNAME, RTYPE) \ +std::shared_ptr RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \ +{ \ + return std::make_shared(dr, pr); \ +} \ + \ +RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \ +{ \ + doRecordCheck(dr); \ + xfrPacket(pr); \ +} \ + \ +std::shared_ptr RNAME##RecordContent::make(const string& zonedata) \ +{ \ + return std::make_shared(zonedata); \ +} \ + \ +void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) \ +{ \ + this->xfrPacket(pw); \ +} \ + \ +void RNAME##RecordContent::report(void) \ +{ \ + regist(1, RTYPE, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \ + regist(254, RTYPE, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \ +} \ +void RNAME##RecordContent::unreport(void) \ +{ \ + unregist(1, RTYPE); \ + unregist(254, RTYPE); \ +} \ + \ +RNAME##RecordContent::RNAME##RecordContent(const string& zoneData) \ +{ \ + try { \ + RecordTextReader rtr(zoneData); \ + xfrPacket(rtr); \ + } \ + catch(RecordTextException& rte) { \ + throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what())); \ + } \ +} \ + \ +string RNAME##RecordContent::getZoneRepresentation(bool noDot) const \ +{ \ + string ret; \ + RecordTextWriter rtw(ret, noDot); \ + const_cast(this)->xfrPacket(rtw); \ + return ret; \ +} + + +#define boilerplate_conv(RNAME, TYPE, CONV) \ +boilerplate(RNAME, TYPE) \ +template \ +void RNAME##RecordContent::xfrPacket(Convertor& conv, bool noDot) \ +{ \ + CONV; \ + if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \ +} \ + +struct EDNSOpts +{ + enum zFlags { DNSSECOK=32768 }; + vector > d_options; + uint16_t d_packetsize{0}; + uint16_t d_extFlags{0}; + uint8_t d_extRCode, d_version; +}; +//! Convenience function that fills out EDNS0 options, and returns true if there are any + +class MOADNSParser; +bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo); +DNSRecord makeOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t extFlags); +void reportBasicTypes(); +void reportOtherTypes(); +void reportAllTypes(); +ComboAddress getAddr(const DNSRecord& dr, uint16_t defport=0); +void checkHostnameCorrectness(const DNSResourceRecord& rr); +#endif diff --git a/pdns/dnsreplay.cc b/pdns/dnsreplay.cc new file mode 100644 index 0000000..aa0f4e1 --- /dev/null +++ b/pdns/dnsreplay.cc @@ -0,0 +1,848 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/** +Replay all recursion-desired DNS questions to a specified IP address. + +Track all outgoing questions, remap id to one of ours. +Also track all recorded answers, and map them to that same id, the 'expectation'. + +When we see a question, parse it, give it a QuestionIdentifier, and and an id from the free-id list. + +When we see an answer in the tcpdump, parse it, make QI, and add it to the original QI + and check + +When we see an answer from the socket, use the id to match it up to the original QI + and check + +There is one central object, which has (when complete) + our assigned id + QI + Original answer + Socket answer + +What to do with timeouts. We keep around at most 65536 outstanding answers. +*/ + +/* + mental_clock=0; + for(;;) { + + do { + read a packet + send a packet + } while(time_of_last_packet_sent < mental_clock) + mental_clock=time_of_last_packet_sent; + + wait for a response packet for 0.1 seconds + note how much time has passed + mental_clock+=time_passed; + } + + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "statbag.hh" +#include "dnspcap.hh" +#include "sstuff.hh" +#include "anadns.hh" +#include +#include "dnsrecords.hh" +#include "ednssubnet.hh" +#include "ednsoptions.hh" + +#include +#include + +#include +#include +#include +#include +#include + +#include "namespaces.hh" +using namespace ::boost::multi_index; +#include "namespaces.hh" + +StatBag S; +bool g_quiet=true; +int g_timeoutMsec=0; + +namespace po = boost::program_options; + +po::variables_map g_vm; + +const struct timeval operator*(float fact, const struct timeval& rhs) +{ + // cout<<"In: "< d_available; + +} s_idmanager; + + +void setSocketBuffer(int fd, int optname, uint32_t size) +{ + uint32_t psize=0; + socklen_t len=sizeof(psize); + + if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) { + cerr<<"Not decreasing socket buffer size from "<, BOOST_MULTI_INDEX_MEMBER(QuestionData, QuestionIdentifier, d_qi) > , + ordered_unique, BOOST_MULTI_INDEX_MEMBER(QuestionData, int, d_assignedID) > + > +> qids_t; + +qids_t qids; +bool g_throttled; + +unsigned int s_questions, s_origanswers, s_weanswers, s_wetimedout, s_perfect, s_mostly, s_origtimedout; +unsigned int s_wenever, s_orignever; +unsigned int s_webetter, s_origbetter, s_norecursionavailable; +unsigned int s_weunmatched, s_origunmatched; +unsigned int s_wednserrors, s_origdnserrors, s_duplicates; + + + +void WeOrigSlowQueriesDelta(int& weOutstanding, int& origOutstanding, int& weSlow, int& origSlow) +{ + struct timeval now; + gettimeofday(&now, 0); + + weOutstanding=origOutstanding=weSlow=origSlow=0; + + for(qids_t::iterator i=qids.begin(); i!=qids.end(); ++i) { + double dt=DiffTime(i->d_resentTime, now); + if(dt < 2.0) { + if(i->d_newRcode == -1) + weOutstanding++; + if(i->d_origRcode == -1) + origOutstanding++; + } + else { + if(i->d_newRcode == -1) { + weSlow++; + if(!i->d_newlate) { + QuestionData qd=*i; + qd.d_newlate=true; + qids.replace(i, qd); + + s_wetimedout++; + } + } + if(i->d_origRcode == -1) { + origSlow++; + if(!i->d_origlate) { + QuestionData qd=*i; + qd.d_origlate=true; + qids.replace(i, qd); + + s_origtimedout++; + } + } + } + } +} + +void compactAnswerSet(MOADNSParser::answers_t orig, set& compacted) +{ + for(MOADNSParser::answers_t::const_iterator i=orig.begin(); i != orig.end(); ++i) + if(i->first.d_place==DNSResourceRecord::ANSWER) + compacted.insert(i->first); +} + +bool isRcodeOk(int rcode) +{ + return rcode==0 || rcode==3; +} + +set > s_origbetterset; + +bool isRootReferral(const MOADNSParser::answers_t& answers) +{ + if(answers.empty()) + return false; + + bool ok=true; + for(MOADNSParser::answers_t::const_iterator iter = answers.begin(); iter != answers.end(); ++iter) { + // cerr<<(int)iter->first.d_place<<", "<first.d_name<<" "<first.d_type<<", # "<first.d_place!=2) + ok=false; + if(!iter->first.d_name.isRoot() || iter->first.d_type!=QType::NS) + ok=false; + } + return ok; +} + +vector flightTimes; +void accountFlightTime(qids_t::const_iterator iter) +{ + if(flightTimes.empty()) + flightTimes.resize(2050); + + struct timeval now; + gettimeofday(&now, 0); + unsigned int mdiff = 1000*DiffTime(iter->d_resentTime, now); + if(mdiff > flightTimes.size()-2) + mdiff= flightTimes.size()-1; + + flightTimes[mdiff]++; +} + +uint64_t countLessThan(unsigned int msec) +{ + uint64_t ret=0; + for(unsigned int i = 0 ; i < msec && i < flightTimes.size() ; ++i) { + ret += flightTimes[i]; + } + return ret; +} + +void emitFlightTimes() +{ + uint64_t totals = countLessThan(flightTimes.size()); + unsigned int limits[]={1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100, 200, 500, 1000, (unsigned int) flightTimes.size()}; + uint64_t sofar=0; + cout.setf(std::ios::fixed); + cout.precision(2); + for(unsigned int i =0 ; i < sizeof(limits)/sizeof(limits[0]); ++i) { + if(limits[i]!=flightTimes.size()) + cout<<"Within "< canonicOrig, canonicNew; + compactAnswerSet(qd.d_origAnswers, canonicOrig); + compactAnswerSet(qd.d_newAnswers, canonicNew); + + if(!g_quiet) { + cout<::const_iterator i=canonicOrig.begin(); i!=canonicOrig.end(); ++i) + cout<<"\t"<d_name<<"\t"<d_type)<<"\t'" << (i->d_content ? i->d_content->getZoneRepresentation() : "") <<"'\n"; + cout<<"new: rcode="<::const_iterator i=canonicNew.begin(); i!=canonicNew.end(); ++i) + cout<<"\t"<d_name<<"\t"<d_type)<<"\t'" << (i->d_content ? i->d_content->getZoneRepresentation() : "") <<"'\n"; + cout<<"\n"; + cout<<"-\n"; + + } + } + + int releaseID=qd.d_assignedID; + qids.erase(iter); // qd invalid now + s_idmanager.releaseID(releaseID); +} + + +Socket *s_socket; + +void receiveFromReference() +try +{ + string packet; + ComboAddress remote; + int res=waitForData(s_socket->getHandle(), g_timeoutMsec/1000, 1000*(g_timeoutMsec%1000)); + + if(res < 0 || res==0) + return; + + while(s_socket->recvFromAsync(packet, remote)) { + try { + s_weanswers++; + MOADNSParser mdp(false, packet.c_str(), packet.length()); + if(!mdp.d_header.qr) { + cout<<"Received a question from our reference nameserver!"<::type qids_by_id_index_t; + qids_by_id_index_t& idindex=qids.get(); + qids_by_id_index_t::const_iterator found=idindex.find(ntohs(mdp.d_header.id)); + if(found == idindex.end()) { + if(!g_quiet) + cout<<"Received an answer ("<(found); + measureResultAndClean(iter); + } + } + catch(const MOADNSException &mde) + { + s_wednserrors++; + } + catch(std::out_of_range &e) + { + s_wednserrors++; + } + catch(std::exception& e) + { + s_wednserrors++; + } + } +} +catch(std::exception& e) +{ + cerr<<"Receiver function died: "<d_resentTime, now) < 10) + ++i; + else { + s_idmanager.releaseID(i->d_assignedID); + if(i->d_newRcode==-1) { + s_wenever++; + } + if(i->d_origRcode==-1) { + s_orignever++; + } + + qids.erase(i++); + } + } +} + +void printStats(uint64_t origWaitingFor=0, uint64_t weWaitingFor=0) +{ + format headerfmt ("%|9t|Questions - Pend. - Drop = Answers = (On time + Late) = (Err + Ok)\n"); + format datafmt("%s%|9t|%d %|21t|%d %|29t|%d %|36t|%d %|47t|%d %|57t|%d %|66t|%d %|72t|%d\n"); + + cerr< 1000) { + cerr<<"Too many questions ("<arcount); + /* does it fit in the existing buffer? */ + if (packetSize > *len && (packetSize - *len) > EDNSRR.size()) { + arcount++; + dh->arcount = htons(arcount); + memcpy(packet + *len, EDNSRR.c_str(), EDNSRR.size()); + *len += EDNSRR.size(); + } +} + +static bool g_rdSelector; +static uint16_t g_pcapDnsPort; + +static bool sendPacketFromPR(PcapPacketReader& pr, const ComboAddress& remote, int stamp) +{ + bool sent=false; + if (pr.d_len <= sizeof(dnsheader)) { + return sent; + } + if (pr.d_len > std::numeric_limits::max()) { + /* too large for an DNS UDP query, something is not right */ + return false; + } + dnsheader* dh=const_cast(reinterpret_cast(pr.d_payload)); + if((ntohs(pr.d_udp->uh_dport)!=g_pcapDnsPort && ntohs(pr.d_udp->uh_sport)!=g_pcapDnsPort) || dh->rd != g_rdSelector) + return sent; + + QuestionData qd; + try { + // yes, we send out ALWAYS. Even if we don't do anything with it later, + if(!dh->qr) { // this is to stress out the reference server with all the pain + s_questions++; + qd.d_assignedID = s_idmanager.getID(); + uint16_t tmp=dh->id; + dh->id=htons(qd.d_assignedID); + // dh->rd=1; // useful to replay traffic to auths to a recursor + uint16_t dlen = pr.d_len; + + if (stamp >= 0) { + static_assert(sizeof(pr.d_buffer) >= 1500, "The size of the underlying buffer should be at least 1500 bytes"); + if (dlen > 1500) { + /* the existing packet is larger than the maximum size we are willing to send, and it won't get better by adding ECS */ + return false; + } + addECSOption((char*)pr.d_payload, 1500, &dlen, pr.getSource(), stamp); + pr.d_len=dlen; + } + + s_socket->sendTo((const char*)pr.d_payload, dlen, remote); + sent=true; + dh->id=tmp; + } + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); + QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), mdp); + + if(!mdp.d_header.qr) { + + if(qids.count(qi)) { + if(!g_quiet) + cout<<"Saw an exact duplicate question in PCAP "<ra) { + s_norecursionavailable++; + eqd.d_norecursionavailable=true; + } + qids.replace(iter, eqd); + + if(eqd.d_newRcode!=-1) { + measureResultAndClean(iter); + } + + return sent; + } + else { + s_origunmatched++; + if(!g_quiet) + cout<<"Unmatched original answer "<()->default_value(0), "stop after this many packets") + ("pcap-dns-port", po::value()->default_value(53), "look at packets from or to this port in the PCAP (defaults to 53)") + ("quiet", po::value()->default_value(true), "don't be too noisy") + ("recursive", po::value()->default_value(true), "look at recursion desired packets, or not (defaults true)") + ("speedup", po::value()->default_value(1), "replay at this speedup") + ("timeout-msec", po::value()->default_value(500), "wait at least this many milliseconds for a reply") + ("ecs-stamp", "Add original IP address to ECS in replay") + ("ecs-mask", po::value(), "Replace first octet of src IP address with this value in ECS") + ("source-ip", po::value()->default_value(""), "IP to send the replayed packet from") + ("source-port", po::value()->default_value(0), "Port to send the replayed packet from"); + + po::options_description alloptions; + po::options_description hidden("hidden options"); + hidden.add_options() + ("pcap-source", po::value(), "PCAP source file") + ("target-ip", po::value()->default_value("127.0.0.1"), "target-ip") + ("target-port", po::value()->default_value(5300), "target port"); + + alloptions.add(desc).add(hidden); + po::positional_options_description p; + p.add("pcap-source", 1); + p.add("target-ip", 1); + p.add("target-port", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + reportAllTypes(); + + if (g_vm.count("help")) { + usage(desc); + return EXIT_SUCCESS; + } + + if (g_vm.count("version")) { + cerr<<"dnsreplay "<(); + + g_rdSelector = g_vm["recursive"].as(); + g_pcapDnsPort = g_vm["pcap-dns-port"].as(); + + g_quiet = g_vm["quiet"].as(); + + signal(SIGINT, pleaseQuitHandler); + float speedup=g_vm["speedup"].as(); + g_timeoutMsec=g_vm["timeout-msec"].as(); + + PcapPacketReader pr(g_vm["pcap-source"].as()); + s_socket= new Socket(AF_INET, SOCK_DGRAM); + + s_socket->setNonBlocking(); + + if(g_vm.count("source-ip") && !g_vm["source-ip"].as().empty()) + s_socket->bind(ComboAddress(g_vm["source-ip"].as(), g_vm["source-port"].as())); + + setSocketReceiveBuffer(s_socket->getHandle(), 2000000); + setSocketSendBuffer(s_socket->getHandle(), 2000000); + + ComboAddress remote(g_vm["target-ip"].as(), + g_vm["target-port"].as()); + + int stamp = -1; + if(g_vm.count("ecs-stamp") && g_vm.count("ecs-mask")) + stamp=g_vm["ecs-mask"].as(); + + cerr<<"Replaying packets to: '"<()<<"', port "<()<= packetLimit) + break; + + mental_time=packet_ts; + struct timeval then, now; + gettimeofday(&then,0); + + receiveFromReference(); + + gettimeofday(&now, 0); + + mental_time= mental_time + speedup * (now-then); + } + out:; + sleep(1); + receiveFromReference(); + printStats(); + emitFlightTimes(); +} +catch(std::exception& e) +{ + cerr<<"Fatal: "< +#include "statbag.hh" +#include "dnspcap.hh" +#include "sstuff.hh" +#include "anadns.hh" + + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" +using namespace ::boost::multi_index; +#include "namespaces.hh" +StatBag S; + +void usage() { + cerr<<"syntax: dnsscan INFILE ..."< 2 ? argv[2] : "127.0.0.1", + argc > 3 ? atoi(argv[3]) : 5300); + + */ + + if(argc<2) { + usage(); + exit(EXIT_SUCCESS); + } + + for(int n=1; n < argc; ++n) { + if ((string) argv[n] == "--help") { + usage(); + return EXIT_SUCCESS; + } + + if ((string) argv[n] == "--version") { + cerr<<"dnsscan "< +#include +#include +#include +#include +#include +#include "anadns.hh" +#include +#include +#include +#include "arguments.hh" +#include "namespaces.hh" +#include "dnsrecords.hh" +#include "statnode.hh" + +namespace po = boost::program_options; +po::variables_map g_vm; + +ArgvMap& arg() +{ + static ArgvMap theArg; + return theArg; +} +StatBag S; + + + +struct QuestionData +{ + QuestionData() : d_qcount(0), d_answercount(0) + { + d_firstquestiontime.tv_sec=0; + } + + int d_qcount; + int d_answercount; + + struct pdns_timeval d_firstquestiontime; +}; + +typedef map statmap_t; +statmap_t statmap; + +unsigned int liveQuestions() +{ + unsigned int ret=0; + for(statmap_t::value_type& val : statmap) { + if(!val.second.d_answercount) + ret++; + // if(val.second.d_qcount > val.second.d_answercount) + // ret+= val.second.d_qcount - val.second.d_answercount; + } + return ret; +} + +struct LiveCounts +{ + unsigned int questions; + unsigned int answers; + unsigned int outstanding; + + LiveCounts() + { + questions=answers=outstanding=0; + } + + LiveCounts operator-(const LiveCounts& rhs) + { + LiveCounts ret; + ret.questions = questions - rhs.questions; + ret.answers = answers - rhs.answers; + ret.outstanding = outstanding; + return ret; + } +}; + +void visitor(const StatNode* node, const StatNode::Stat& selfstat, const StatNode::Stat& childstat) +{ + // 20% servfails, >100 children, on average less than 2 copies of a query + // >100 different subqueries + double dups=1.0*childstat.queries/node->children.size(); + if(dups > 2.0) + return; + if(1.0*childstat.servfails / childstat.queries > 0.2 && node->children.size()>100) { + cout<fullname<<", servfails: "<children.size()<<", childstat.queries: "<fullname<<"\t"<(lhs.tv_usec)}, b{rhs.tv_sec, static_cast(rhs.tv_usec)}; + return operator-(a,b); +} + + +int main(int argc, char** argv) +try +{ + po::options_description desc("Allowed options"), hidden, alloptions; + desc.add_options() + ("help,h", "produce help message") + ("version", "print version number") + ("rd", po::value(), "If set to true, only process RD packets, to false only non-RD, unset: both") + ("ipv4", po::value()->default_value(true), "Process IPv4 packets") + ("ipv6", po::value()->default_value(true), "Process IPv6 packets") +#if HAVE_BOOST_GE_148 + ("log-histogram", "Write a log-histogram to file 'log-histogram'") + ("full-histogram", po::value(), "Write a log-histogram to file 'full-histogram' with this millisecond bin size") +#endif + ("filter-name,f", po::value(), "Do statistics only for queries within this domain") + ("load-stats,l", po::value()->default_value(""), "if set, emit per-second load statistics (questions, answers, outstanding)") + ("no-servfail-stats", "Don't include servfails in response time stats") + ("servfail-tree", "Figure out subtrees that generate servfails") + ("stats-dir", po::value()->default_value("."), "Directory where statistics will be saved") + ("write-failures,w", po::value()->default_value(""), "if set, write weird packets to this PCAP file") + ("verbose,v", "be verbose"); + + hidden.add_options() + ("files", po::value >(), "files"); + + alloptions.add(desc).add(hidden); + + po::positional_options_description p; + p.add("files", -1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + vector files; + if(g_vm.count("files")) + files = g_vm["files"].as >(); + + if(g_vm.count("version")) { + cerr<<"dnsscope "<()); + uint32_t nameMismatch = 0; + + StatNode root; + + bool verbose = g_vm.count("verbose"); + + bool haveRDFilter=0, rdFilter=0; + if(g_vm.count("rd")) { + rdFilter = g_vm["rd"].as(); + haveRDFilter=1; + cout<<"Filtering on recursion desired="<(); + bool doIPv6 = g_vm["ipv6"].as(); + bool doServFailTree = g_vm.count("servfail-tree"); + bool noservfailstats = g_vm.count("no-servfail-stats"); + int dnserrors=0, parsefail=0; + typedef map cumul_t; + cumul_t cumul; + unsigned int untracked=0, errorresult=0, nonRDQueries=0, queries=0; + unsigned int ipv4DNSPackets=0, ipv6DNSPackets=0, fragmented=0, rdNonRAAnswers=0; + unsigned int answers=0, nonDNSIP=0, rdFilterMismatch=0; + unsigned int dnssecOK=0, edns=0; + unsigned int dnssecCD=0, dnssecAD=0; + unsigned int reuses=0; + typedef map rcodes_t; + rcodes_t rcodes; + + time_t lowestTime=2000000000, highestTime=0; + time_t lastsec=0; + LiveCounts lastcounts; + std::unordered_set requestors, recipients, rdnonra; + typedef vector > pcounts_t; + pcounts_t pcounts; + OPTRecordContent::report(); + + for(unsigned int fno=0; fno < files.size(); ++fno) { + PcapPacketReader pr(files[fno]); + PcapPacketWriter* pw=0; + if(!g_vm["write-failures"].as().empty()) + pw=new PcapPacketWriter(g_vm["write-failures"].as(), pr); + + EDNSOpts edo; + while(pr.getUDPPacket()) { + + if((ntohs(pr.d_udp->uh_dport)==5300 || ntohs(pr.d_udp->uh_sport)==5300 || + ntohs(pr.d_udp->uh_dport)==53 || ntohs(pr.d_udp->uh_sport)==53) && + pr.d_len > 12) { + try { + if((pr.d_ip->ip_v == 4 && !doIPv4) || (pr.d_ip->ip_v == 6 && !doIPv6)) + continue; + if(pr.d_ip->ip_v == 4) { + uint16_t frag = ntohs(pr.d_ip->ip_off); + if((frag & IP_MF) || (frag & IP_OFFMASK)) { // more fragments or IS a fragment + fragmented++; + continue; + } + } + uint16_t qtype; + DNSName qname((const char*)pr.d_payload, pr.d_len, 12, false, &qtype); + struct dnsheader header; + memcpy(&header, (struct dnsheader*)pr.d_payload, 12); + + if(haveRDFilter && header.rd != rdFilter) { + rdFilterMismatch++; + continue; + } + + if(!filtername.empty() && !qname.isPartOf(filtername)) { + nameMismatch++; + continue; + } + + if(!header.qr) { + uint16_t udpsize, z; + if(getEDNSUDPPayloadSizeAndZ((const char*)pr.d_payload, pr.d_len, &udpsize, &z)) { + edns++; + if(z & EDNSOpts::DNSSECOK) + dnssecOK++; + if(header.cd) + dnssecCD++; + if(header.ad) + dnssecAD++; + } + } + + if(pr.d_ip->ip_v == 4) + ++ipv4DNSPackets; + else + ++ipv6DNSPackets; + + if(pr.d_pheader.ts.tv_sec != lastsec) { + LiveCounts lc; + if(lastsec) { + lc.questions = queries; + lc.answers = answers; + lc.outstanding = liveQuestions(); + + LiveCounts diff = lc - lastcounts; + pcounts.push_back(make_pair(pr.d_pheader.ts.tv_sec, diff)); + + } + lastsec = pr.d_pheader.ts.tv_sec; + lastcounts = lc; + } + + lowestTime=min((time_t)lowestTime, (time_t)pr.d_pheader.ts.tv_sec); + highestTime=max((time_t)highestTime, (time_t)pr.d_pheader.ts.tv_sec); + + QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), header, qname, qtype); + + if(!header.qr) { // question + // cout<<"Query "<write(); + parsefail++; + continue; + } + } + else { // non-DNS ip + nonDNSIP++; + } + } + cout<<"PCAP contained "<second.d_answercount) { + unanswered++; + } + //openf<< i->first.d_source.toStringWithPort()<<' ' <first.d_dest.toStringWithPort()<<' '<first.d_id<<' '<first.d_qname <<" " <first.d_qtype<< " "<second.d_qcount <<" " <second.d_answercount<first) % i->second % (i->second*100.0/answers))<first<<"\t"<<(sum+=i->second)<<"\n"; + totpairs+=i->second; + tottime+=i->first*i->second; + } + + typedef map done_t; + done_t done; + for(auto a : {50, 100, 200, 300, 400, 800, 1000, 2000, 4000, 8000, 32000, 64000, 256000, 1024000, 2048000}) + done[a]=false; + + cout.setf(std::ios::fixed); + cout.precision(4); + sum=0; + +#if HAVE_BOOST_GE_148 + if(g_vm.count("log-histogram")) { + string fname = g_vm["stats-dir"].as()+"/log-histogram"; + ofstream loglog(fname); + if(!loglog) + throw runtime_error("Unable to write statistics to "+fname); + + writeLogHistogramFile(cumul, loglog); + } + + if(g_vm.count("full-histogram")) { + string fname=g_vm["stats-dir"].as()+"/full-histogram"; + ofstream loglog(fname); + if(!loglog) + throw runtime_error("Unable to write statistics to "+fname); + writeFullHistogramFile(cumul, g_vm["full-histogram"].as(), loglog); + } +#endif + + + sum=0; + double lastperc=0, perc=0; + uint64_t lastsum=0; + + for(cumul_t::const_iterator i=cumul.begin(); i!=cumul.end(); ++i) { + for(done_t::iterator j=done.begin(); j!=done.end(); ++j) { + if(!j->second && i->first > j->first) { + j->second=true; + + perc=sum*100.0/totpairs; + if(j->first < 1024) + cout<< perc <<"% of questions answered within " << j->first << " usec ("; + else + cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec ("; + + cout<second; + } + + for(auto j = done.begin(); j != done.end(); ++j) { + if(!j->second) { + perc=sum*100.0/totpairs; + if(j->first < 1024) + cout<< perc <<"% of questions answered within " << j->first << " usec ("; + else + cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec ("; + + cout<first/1000000.0) <<" seconds"<().empty()) { + ofstream load(g_vm["load-stats"].as().c_str()); + if(!load) + throw runtime_error("Error writing load statistics to "+g_vm["load-stats"].as()); + for(pcounts_t::value_type& val : pcounts) { + load< diff; + set_difference(requestors.begin(), requestors.end(), recipients.begin(), recipients.end(), back_inserter(diff), ComboAddress::addressOnlyLessThan()); + cout<<"Saw "< +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include +#include +#include // for 'operator+=()' +#include +#include "base64.hh" +#include "namespaces.hh" +#ifdef HAVE_P11KIT1 +#include "pkcs11signers.hh" +#endif +#include "gss_context.hh" +#include "misc.hh" + +using namespace boost::assign; + +shared_ptr DNSCryptoKeyEngine::makeFromISCFile(DNSKEYRecordContent& drc, const char* fname) +{ + string sline, isc; + auto fp = std::unique_ptr(fopen(fname, "r"), fclose); + if(!fp) { + throw runtime_error("Unable to read file '"+string(fname)+"' for generating DNS Private Key"); + } + + while(stringfgets(fp.get(), sline)) { + isc += sline; + } + fp.reset(); + + shared_ptr dke = makeFromISCString(drc, isc); + vector checkKeyErrors; + + if(!dke->checkKey(&checkKeyErrors)) { + string reason; + if(checkKeyErrors.size()) { + reason = " ("+boost::algorithm::join(checkKeyErrors, ", ")+")"; + } + throw runtime_error("Invalid DNS Private Key in file '"+string(fname)+"'"+reason); + } + return dke; +} + +shared_ptr DNSCryptoKeyEngine::makeFromISCString(DNSKEYRecordContent& drc, const std::string& content) +{ + bool pkcs11=false; + int algorithm = 0; + string sline, key, value, raw; + std::istringstream str(content); + map stormap; + + while(std::getline(str, sline)) { + tie(key,value)=splitField(sline, ':'); + trim(value); + if(pdns_iequals(key,"algorithm")) { + algorithm = pdns_stou(value); + stormap["algorithm"]=std::to_string(algorithm); + continue; + } else if (pdns_iequals(key,"pin")) { + stormap["pin"]=value; + continue; + } else if (pdns_iequals(key,"engine")) { + stormap["engine"]=value; + pkcs11=true; + continue; + } else if (pdns_iequals(key,"slot")) { + stormap["slot"]=value; + continue; + } else if (pdns_iequals(key,"label")) { + stormap["label"]=value; + continue; + } else if (pdns_iequals(key,"publabel")) { + stormap["publabel"]=value; + continue; + } + else if(pdns_iequals(key, "Private-key-format")) + continue; + raw.clear(); + B64Decode(value, raw); + stormap[toLower(key)]=raw; + } + shared_ptr dpk; + + if (pkcs11) { +#ifdef HAVE_P11KIT1 + if (stormap.find("slot") == stormap.end()) + throw PDNSException("Cannot load PKCS#11 key, no Slot specified"); + // we need PIN to be at least empty + if (stormap.find("pin") == stormap.end()) stormap["pin"] = ""; + dpk = PKCS11DNSCryptoKeyEngine::maker(algorithm); +#else + throw PDNSException("Cannot load PKCS#11 key without support for it"); +#endif + } else { + dpk=make(algorithm); + } + dpk->fromISCMap(drc, stormap); + return dpk; +} + +std::string DNSCryptoKeyEngine::convertToISC() const +{ + storvector_t stormap = this->convertToISCVector(); + ostringstream ret; + ret<<"Private-key-format: v1.2\n"; + for(const stormap_t::value_type& value : stormap) { + if(value.first != "Algorithm" && value.first != "PIN" && + value.first != "Slot" && value.first != "Engine" && + value.first != "Label" && value.first != "PubLabel") + ret< DNSCryptoKeyEngine::make(unsigned int algo) +{ + const makers_t& makers = getMakers(); + makers_t::const_iterator iter = makers.find(algo); + if(iter != makers.cend()) + return (iter->second)(algo); + else { + throw runtime_error("Request to create key object for unknown algorithm number "+std::to_string(algo)); + } +} + +/** + * Returns the supported DNSSEC algorithms with the name of the Crypto Backend used + * + * @return A vector with pairs of (algorithm-number (int), backend-name (string)) + */ +vector> DNSCryptoKeyEngine::listAllAlgosWithBackend() +{ + vector> ret; + for (auto const& value : getMakers()) { + shared_ptr dcke(value.second(value.first)); + ret.push_back(make_pair(value.first, dcke->getName())); + } + return ret; +} + +void DNSCryptoKeyEngine::report(unsigned int algo, maker_t* maker, bool fallback) +{ + getAllMakers()[algo].push_back(maker); + if(getMakers().count(algo) && fallback) { + return; + } + getMakers()[algo]=maker; +} + +bool DNSCryptoKeyEngine::testAll() +{ + bool ret=true; + + for(const allmakers_t::value_type& value : getAllMakers()) + { + for(maker_t* creator : value.second) { + + for(maker_t* signer : value.second) { + // multi_map bestSigner, bestVerifier; + + for(maker_t* verifier : value.second) { + try { + /* pair res=*/ testMakers(value.first, creator, signer, verifier); + } + catch(std::exception& e) + { + cerr< bestSigner, bestVerifier; + + for(maker_t* verifier : getAllMakers()[algo]) { + try { + /* pair res=*/testMakers(algo, creator, signer, verifier); + } + catch(std::exception& e) + { + cerr< DNSCryptoKeyEngine::testMakers(unsigned int algo, maker_t* creator, maker_t* signer, maker_t* verifier) +{ + shared_ptr dckeCreate(creator(algo)); + shared_ptr dckeSign(signer(algo)); + shared_ptr dckeVerify(verifier(algo)); + + cerr<<"Testing algorithm "<getName()<<"' ->'"<getName()<<"' -> '"<getName()<<"' "; + unsigned int bits; + if(algo <= 10) + bits=1024; + else if(algo == DNSSECKeeper::ECCGOST || algo == DNSSECKeeper::ECDSA256 || algo == DNSSECKeeper::ED25519) + bits = 256; + else if(algo == DNSSECKeeper::ECDSA384) + bits = 384; + else if(algo == DNSSECKeeper::ED448) + bits = 456; + else + throw runtime_error("Can't guess key size for algorithm "+std::to_string(algo)); + + dckeCreate->create(bits); + + { // FIXME: this block copy/pasted from makeFromISCString + DNSKEYRecordContent dkrc; + int algorithm = 0; + string sline, key, value, raw; + std::istringstream str(dckeCreate->convertToISC()); + map stormap; + + while(std::getline(str, sline)) { + tie(key,value)=splitField(sline, ':'); + trim(value); + if(pdns_iequals(key,"algorithm")) { + algorithm = pdns_stou(value); + stormap["algorithm"]=std::to_string(algorithm); + continue; + } else if (pdns_iequals(key,"pin")) { + stormap["pin"]=value; + continue; + } else if (pdns_iequals(key,"engine")) { + stormap["engine"]=value; + continue; + } else if (pdns_iequals(key,"slot")) { + int slot = std::stoi(value); + stormap["slot"]=std::to_string(slot); + continue; + } else if (pdns_iequals(key,"label")) { + stormap["label"]=value; + continue; + } + else if(pdns_iequals(key, "Private-key-format")) + continue; + raw.clear(); + B64Decode(value, raw); + stormap[toLower(key)]=raw; + } + dckeSign->fromISCMap(dkrc, stormap); + if(!dckeSign->checkKey()) { + throw runtime_error("Verification of key with creator "+dckeCreate->getName()+" with signer "+dckeSign->getName()+" and verifier "+dckeVerify->getName()+" failed"); + } + } + + string message("Hi! How is life?"); + + string signature; + DTime dt; dt.set(); + for(unsigned int n = 0; n < 100; ++n) + signature = dckeSign->sign(message); + unsigned int udiffSign= dt.udiff()/100, udiffVerify; + + dckeVerify->fromPublicKeyString(dckeSign->getPublicKeyString()); + if (dckeVerify->getPublicKeyString().compare(dckeSign->getPublicKeyString())) { + throw runtime_error("Comparison of public key loaded into verifier produced by signer failed"); + } + dt.set(); + if(dckeVerify->verify(message, signature)) { + udiffVerify = dt.udiff(); + cerr<<"Signature & verify ok, signature "<getName()+" with signer "+dckeSign->getName()+" and verifier "+dckeVerify->getName()+" failed"); + } + return make_pair(udiffSign, udiffVerify); +} + +shared_ptr DNSCryptoKeyEngine::makeFromPublicKeyString(unsigned int algorithm, const std::string& content) +{ + shared_ptr dpk=make(algorithm); + dpk->fromPublicKeyString(content); + return dpk; +} + + +shared_ptr DNSCryptoKeyEngine::makeFromPEMString(DNSKEYRecordContent& drc, const std::string& raw) +{ + + for(const makers_t::value_type& val : getMakers()) + { + shared_ptr ret=nullptr; + try { + ret = val.second(val.first); + ret->fromPEMString(drc, raw); + return ret; + } + catch(...) + { + } + } + return 0; +} + + +static bool sharedDNSSECCompare(const shared_ptr& a, const shared_ptr& b) +{ + return a->serialize(g_rootdnsname, true, true) < b->serialize(g_rootdnsname, true, true); +} + +/** + * Returns the string that should be hashed to create/verify the RRSIG content + * + * @param qname DNSName of the RRSIG's owner name. + * @param rrc The RRSIGRecordContent we take the Type Covered and + * original TTL fields from. + * @param signRecords A vector of DNSRecordContent shared_ptr's that are covered + * by the RRSIG, where we get the RDATA from. + * @param processRRSIGLabels A boolean to trigger processing the RRSIG's "Labels" + * field. This is usually only needed for validation + * purposes, as the authoritative server correctly + * sets qname to the wildcard. + */ +string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, vector >& signRecords, bool processRRSIGLabels) +{ + sort(signRecords.begin(), signRecords.end(), sharedDNSSECCompare); + + string toHash; + toHash.append(const_cast(rrc).serialize(g_rootdnsname, true, true)); + toHash.resize(toHash.size() - rrc.d_signature.length()); // chop off the end, don't sign the signature! + + string nameToHash(qname.toDNSStringLC()); + + if (processRRSIGLabels) { + unsigned int rrsig_labels = rrc.d_labels; + unsigned int fqdn_labels = qname.countLabels(); + + if (rrsig_labels < fqdn_labels) { + DNSName choppedQname(qname); + while (choppedQname.countLabels() > rrsig_labels) + choppedQname.chopOff(); + nameToHash = "\x01*" + choppedQname.toDNSStringLC(); + } else if (rrsig_labels > fqdn_labels) { + // The RRSIG Labels field is a lie (or the qname is wrong) and the RRSIG + // can never be valid + return ""; + } + } + + for(shared_ptr& add : signRecords) { + toHash.append(nameToHash); + uint16_t tmp=htons(rrc.d_type); + toHash.append((char*)&tmp, 2); + tmp=htons(1); // class + toHash.append((char*)&tmp, 2); + uint32_t ttl=htonl(rrc.d_originalttl); + toHash.append((char*)&ttl, 4); + // for NSEC signatures, we should not lowercase the rdata section + string rdata=add->serialize(g_rootdnsname, true, (add->getType() == QType::NSEC) ? false : true); // RFC 6840, 5.1 + tmp=htons(rdata.length()); + toHash.append((char*)&tmp, 2); + toHash.append(rdata); + } + + return toHash; +} + +bool DNSCryptoKeyEngine::isAlgorithmSupported(unsigned int algo) +{ + const makers_t& makers = getMakers(); + makers_t::const_iterator iter = makers.find(algo); + return iter != makers.cend(); +} + +static unsigned int digestToAlgorithmNumber(uint8_t digest) +{ + switch(digest) { + case DNSSECKeeper::SHA1: + return DNSSECKeeper::RSASHA1; + case DNSSECKeeper::SHA256: + return DNSSECKeeper::RSASHA256; + case DNSSECKeeper::GOST: + return DNSSECKeeper::ECCGOST; + case DNSSECKeeper::SHA384: + return DNSSECKeeper::ECDSA384; + default: + throw std::runtime_error("Unknown digest type " + std::to_string(digest)); + } + return 0; +} + +bool DNSCryptoKeyEngine::isDigestSupported(uint8_t digest) +{ + try { + unsigned int algo = digestToAlgorithmNumber(digest); + return isAlgorithmSupported(algo); + } + catch(const std::exception& e) { + return false; + } +} + +DSRecordContent makeDSFromDNSKey(const DNSName& qname, const DNSKEYRecordContent& drc, uint8_t digest) +{ + string toHash; + toHash.assign(qname.toDNSStringLC()); + toHash.append(const_cast(drc).serialize(DNSName(), true, true)); + + DSRecordContent dsrc; + try { + unsigned int algo = digestToAlgorithmNumber(digest); + shared_ptr dpk(DNSCryptoKeyEngine::make(algo)); + dsrc.d_digest = dpk->hash(toHash); + } + catch(const std::exception& e) { + throw std::runtime_error("Asked to create (C)DS record of unknown digest type " + std::to_string(digest)); + } + + dsrc.d_algorithm = drc.d_algorithm; + dsrc.d_digesttype = digest; + dsrc.d_tag = const_cast(drc).getTag(); + + return dsrc; +} + + +static DNSKEYRecordContent makeDNSKEYFromDNSCryptoKeyEngine(const std::shared_ptr& pk, uint8_t algorithm, uint16_t flags) +{ + DNSKEYRecordContent drc; + + drc.d_protocol=3; + drc.d_algorithm = algorithm; + + drc.d_flags=flags; + drc.d_key = pk->getPublicKeyString(); + + return drc; +} + +uint32_t getStartOfWeek() +{ + uint32_t now = time(0); + now -= (now % (7*86400)); + return now; +} + +string hashQNameWithSalt(const NSEC3PARAMRecordContent& ns3prc, const DNSName& qname) +{ + return hashQNameWithSalt(ns3prc.d_salt, ns3prc.d_iterations, qname); +} + +string hashQNameWithSalt(const std::string& salt, unsigned int iterations, const DNSName& qname) +{ + unsigned int times = iterations; + unsigned char hash[20]; + string toHash(qname.toDNSStringLC()); + + for(;;) { + toHash.append(salt); + SHA1((unsigned char*)toHash.c_str(), toHash.length(), hash); + toHash.assign((char*)hash, sizeof(hash)); + if(!times--) + break; + } + return toHash; +} + +void incrementHash(std::string& raw) // I wonder if this is correct, cmouse? ;-) +{ + if(raw.empty()) + return; + + for(string::size_type pos=raw.size(); pos; ) { + --pos; + unsigned char c = (unsigned char)raw[pos]; + ++c; + raw[pos] = (char) c; + if(c) + break; + } +} + +void decrementHash(std::string& raw) // I wonder if this is correct, cmouse? ;-) +{ + if(raw.empty()) + return; + + for(string::size_type pos=raw.size(); pos; ) { + --pos; + unsigned char c = (unsigned char)raw[pos]; + --c; + raw[pos] = (char) c; + if(c != 0xff) + break; + } +} + +DNSKEYRecordContent DNSSECPrivateKey::getDNSKEY() const +{ + return makeDNSKEYFromDNSCryptoKeyEngine(getKey(), d_algorithm, d_flags); +} + +class DEREater +{ +public: + DEREater(const std::string& str) : d_str(str), d_pos(0) + {} + + struct eof{}; + + uint8_t getByte() + { + if(d_pos >= d_str.length()) { + throw eof(); + } + return (uint8_t) d_str[d_pos++]; + } + + uint32_t getLength() + { + uint8_t first = getByte(); + if(first < 0x80) { + return first; + } + first &= ~0x80; + + uint32_t len=0; + for(int n=0; n < first; ++n) { + len *= 0x100; + len += getByte(); + } + return len; + } + + std::string getBytes(unsigned int len) + { + std::string ret; + for(unsigned int n=0; n < len; ++n) + ret.append(1, (char)getByte()); + return ret; + } + + std::string::size_type getOffset() + { + return d_pos; + } +private: + const std::string& d_str; + std::string::size_type d_pos; +}; + +static string calculateHMAC(const std::string& key, const std::string& text, TSIGHashEnum hasher) { + + const EVP_MD* md_type; + unsigned int outlen; + unsigned char hash[EVP_MAX_MD_SIZE]; + switch(hasher) { + case TSIG_MD5: + md_type = EVP_md5(); + break; + case TSIG_SHA1: + md_type = EVP_sha1(); + break; + case TSIG_SHA224: + md_type = EVP_sha224(); + break; + case TSIG_SHA256: + md_type = EVP_sha256(); + break; + case TSIG_SHA384: + md_type = EVP_sha384(); + break; + case TSIG_SHA512: + md_type = EVP_sha512(); + break; + default: + throw PDNSException("Unknown hash algorithm requested from calculateHMAC()"); + } + + unsigned char* out = HMAC(md_type, reinterpret_cast(key.c_str()), key.size(), reinterpret_cast(text.c_str()), text.size(), hash, &outlen); + if (out == NULL || outlen == 0) { + throw PDNSException("HMAC computation failed"); + } + + return string((char*) hash, outlen); +} + +static bool constantTimeStringEquals(const std::string& a, const std::string& b) +{ + if (a.size() != b.size()) { + return false; + } + const size_t size = a.size(); +#if OPENSSL_VERSION_NUMBER >= 0x0090819fL + return CRYPTO_memcmp(a.c_str(), b.c_str(), size) == 0; +#else + const volatile unsigned char *_a = (const volatile unsigned char *) a.c_str(); + const volatile unsigned char *_b = (const volatile unsigned char *) b.c_str(); + unsigned char res = 0; + + for (size_t idx = 0; idx < size; idx++) { + res |= _a[idx] ^ _b[idx]; + } + + return res == 0; +#endif +} + +static string makeTSIGPayload(const string& previous, const char* packetBegin, size_t packetSize, const DNSName& tsigKeyName, const TSIGRecordContent& trc, bool timersonly) +{ + string message; + + if(!previous.empty()) { + uint16_t len = htons(previous.length()); + message.append(reinterpret_cast(&len), sizeof(len)); + message.append(previous); + } + + message.append(packetBegin, packetSize); + + vector signVect; + DNSPacketWriter dw(signVect, DNSName(), 0); + auto pos=signVect.size(); + if(!timersonly) { + dw.xfrName(tsigKeyName, false); + dw.xfr16BitInt(QClass::ANY); // class + dw.xfr32BitInt(0); // TTL + dw.xfrName(trc.d_algoName.makeLowerCase(), false); + } + + uint32_t now = trc.d_time; + dw.xfr48BitInt(now); + dw.xfr16BitInt(trc.d_fudge); // fudge + if(!timersonly) { + dw.xfr16BitInt(trc.d_eRcode); // extended rcode + dw.xfr16BitInt(trc.d_otherData.length()); // length of 'other' data + // dw.xfrBlob(trc->d_otherData); + } + message.append(signVect.begin()+pos, signVect.end()); + return message; +} + +static string makeTSIGMessageFromTSIGPacket(const string& opacket, unsigned int tsigOffset, const DNSName& keyname, const TSIGRecordContent& trc, const string& previous, bool timersonly, unsigned int dnsHeaderOffset=0) +{ + string message; + string packet(opacket); + + packet.resize(tsigOffset); // remove the TSIG record at the end as per RFC2845 3.4.1 + packet[(dnsHeaderOffset + sizeof(struct dnsheader))-1]--; // Decrease ARCOUNT because we removed the TSIG RR in the previous line. + + + // Replace the message ID with the original message ID from the TSIG record. + // This is needed for forwarded DNS Update as they get a new ID when forwarding (section 6.1 of RFC2136). The TSIG record stores the original ID and the + // signature was created with the original ID, so we replace it here to get the originally signed message. + // If the message is not forwarded, we simply override it with the same id. + uint16_t origID = htons(trc.d_origID); + packet.replace(0, 2, (char*)&origID, 2); + + return makeTSIGPayload(previous, packet.data(), packet.size(), keyname, trc, timersonly); +} + +void addTSIG(DNSPacketWriter& pw, TSIGRecordContent& trc, const DNSName& tsigkeyname, const string& tsigsecret, const string& tsigprevious, bool timersonly) +{ + TSIGHashEnum algo; + if (!getTSIGHashEnum(trc.d_algoName, algo)) { + throw PDNSException(string("Unsupported TSIG HMAC algorithm ") + trc.d_algoName.toLogString()); + } + + string toSign = makeTSIGPayload(tsigprevious, reinterpret_cast(pw.getContent().data()), pw.getContent().size(), tsigkeyname, trc, timersonly); + + if (algo == TSIG_GSS) { + if (!gss_add_signature(tsigkeyname, toSign, trc.d_mac)) { + throw PDNSException(string("Could not add TSIG signature with algorithm 'gss-tsig' and key name '")+tsigkeyname.toLogString()+string("'")); + } + } else { + trc.d_mac = calculateHMAC(tsigsecret, toSign, algo); + // trc.d_mac[0]++; // sabotage + } + pw.startRecord(tsigkeyname, QType::TSIG, 0, QClass::ANY, DNSResourceRecord::ADDITIONAL, false); + trc.toPacket(pw); + pw.commit(); +} + +bool validateTSIG(const std::string& packet, size_t sigPos, const TSIGTriplet& tt, const TSIGRecordContent& trc, const std::string& previousMAC, const std::string& theirMAC, bool timersOnly, unsigned int dnsHeaderOffset) +{ + uint64_t delta = std::abs((int64_t)trc.d_time - (int64_t)time(nullptr)); + if(delta > trc.d_fudge) { + throw std::runtime_error("Invalid TSIG time delta " + std::to_string(delta) + " > fudge " + std::to_string(trc.d_fudge)); + } + + TSIGHashEnum algo; + if (!getTSIGHashEnum(trc.d_algoName, algo)) { + throw std::runtime_error("Unsupported TSIG HMAC algorithm " + trc.d_algoName.toLogString()); + } + + TSIGHashEnum expectedAlgo; + if (!getTSIGHashEnum(tt.algo, expectedAlgo)) { + throw std::runtime_error("Unsupported TSIG HMAC algorithm expected " + tt.algo.toLogString()); + } + + if (algo != expectedAlgo) { + throw std::runtime_error("Signature with TSIG key '"+tt.name.toLogString()+"' does not match the expected algorithm (" + tt.algo.toLogString() + " / " + trc.d_algoName.toLogString() + ")"); + } + + string tsigMsg; + tsigMsg = makeTSIGMessageFromTSIGPacket(packet, sigPos, tt.name, trc, previousMAC, timersOnly, dnsHeaderOffset); + + if (algo == TSIG_GSS) { + GssContext gssctx(tt.name); + if (!gss_verify_signature(tt.name, tsigMsg, theirMAC)) { + throw std::runtime_error("Signature with TSIG key '"+tt.name.toLogString()+"' failed to validate"); + } + } else { + string ourMac = calculateHMAC(tt.secret, tsigMsg, algo); + + if(!constantTimeStringEquals(ourMac, theirMAC)) { + throw std::runtime_error("Signature with TSIG key '"+tt.name.toLogString()+"' failed to validate"); + } + } + + return true; +} diff --git a/pdns/dnssecinfra.hh b/pdns/dnssecinfra.hh new file mode 100644 index 0000000..76f16b2 --- /dev/null +++ b/pdns/dnssecinfra.hh @@ -0,0 +1,170 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNSSECINFRA_HH +#define PDNS_DNSSECINFRA_HH + +#include "dnsrecords.hh" + +#include +#include +#include +#include "misc.hh" + +class UeberBackend; + +// rules of the road: Algorithm must be set in 'make' for each KeyEngine, and will NEVER change! + +class DNSCryptoKeyEngine +{ + public: + explicit DNSCryptoKeyEngine(unsigned int algorithm) : d_algorithm(algorithm) {} + virtual ~DNSCryptoKeyEngine() {}; + virtual string getName() const = 0; + + typedef std::map stormap_t; + typedef std::vector > storvector_t; + virtual void create(unsigned int bits)=0; + virtual storvector_t convertToISCVector() const =0; + std::string convertToISC() const ; + virtual std::string sign(const std::string& msg) const =0; + virtual std::string hash(const std::string& msg) const + { + throw std::runtime_error("hash() function not implemented"); + return msg; + } + virtual bool verify(const std::string& msg, const std::string& signature) const =0; + + virtual std::string getPubKeyHash()const =0; + virtual std::string getPublicKeyString()const =0; + virtual int getBits() const =0; + virtual unsigned int getAlgorithm() const + { + return d_algorithm; + } + + virtual void fromISCMap(DNSKEYRecordContent& drc, stormap_t& stormap)=0; + virtual void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) + { + throw std::runtime_error("Can't import from PEM string"); + } + virtual void fromPublicKeyString(const std::string& content) = 0; + virtual bool checkKey(vector *errorMessages = nullptr) const + { + return true; + } + static shared_ptr makeFromISCFile(DNSKEYRecordContent& drc, const char* fname); + static shared_ptr makeFromISCString(DNSKEYRecordContent& drc, const std::string& content); + static shared_ptr makeFromPEMString(DNSKEYRecordContent& drc, const std::string& raw); + static shared_ptr makeFromPublicKeyString(unsigned int algorithm, const std::string& raw); + static shared_ptr make(unsigned int algorithm); + static bool isAlgorithmSupported(unsigned int algo); + static bool isDigestSupported(uint8_t digest); + + typedef shared_ptr maker_t(unsigned int algorithm); + + static void report(unsigned int algorithm, maker_t* maker, bool fallback=false); + static std::pair testMakers(unsigned int algorithm, maker_t* creator, maker_t* signer, maker_t* verifier); + static vector> listAllAlgosWithBackend(); + static bool testAll(); + static bool testOne(int algo); + private: + + typedef std::map makers_t; + typedef std::map > allmakers_t; + static makers_t& getMakers() + { + static makers_t s_makers; + return s_makers; + } + static allmakers_t& getAllMakers() + { + static allmakers_t s_allmakers; + return s_allmakers; + } + protected: + const unsigned int d_algorithm; +}; + +struct DNSSECPrivateKey +{ + uint16_t getTag() const + { + return getDNSKEY().getTag(); + } + + const shared_ptr getKey() const + { + return d_key; + } + + void setKey(const shared_ptr key) + { + d_key = key; + d_algorithm = key->getAlgorithm(); + } + DNSKEYRecordContent getDNSKEY() const; + + uint16_t d_flags; + uint8_t d_algorithm; + +private: + shared_ptr d_key; +}; + + + +struct CanonicalCompare: public std::binary_function +{ + bool operator()(const std::string& a, const std::string& b) { + std::vector avect, bvect; + + stringtok(avect, a, "."); + stringtok(bvect, b, "."); + + reverse(avect.begin(), avect.end()); + reverse(bvect.begin(), bvect.end()); + + return avect < bvect; + } +}; + +string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, std::vector >& signRecords, bool processRRSIGLabels = false); + +DSRecordContent makeDSFromDNSKey(const DNSName& qname, const DNSKEYRecordContent& drc, uint8_t digest); + +class DNSSECKeeper; + +uint32_t getStartOfWeek(); + +string hashQNameWithSalt(const NSEC3PARAMRecordContent& ns3prc, const DNSName& qname); +string hashQNameWithSalt(const std::string& salt, unsigned int iterations, const DNSName& qname); + +void incrementHash(std::string& raw); +void decrementHash(std::string& raw); + +void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const std::set& authMap, vector& rrs); + +void addTSIG(DNSPacketWriter& pw, TSIGRecordContent& trc, const DNSName& tsigkeyname, const string& tsigsecret, const string& tsigprevious, bool timersonly); +bool validateTSIG(const std::string& packet, size_t sigPos, const TSIGTriplet& tt, const TSIGRecordContent& trc, const std::string& previousMAC, const std::string& theirMAC, bool timersOnly, unsigned int dnsHeaderOffset=0); + +uint64_t signatureCacheSize(const std::string& str); +#endif diff --git a/pdns/dnsseckeeper.hh b/pdns/dnsseckeeper.hh new file mode 100644 index 0000000..c0d5526 --- /dev/null +++ b/pdns/dnsseckeeper.hh @@ -0,0 +1,306 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dnssecinfra.hh" +#include "dnsrecords.hh" +#include "ueberbackend.hh" + +using namespace ::boost::multi_index; + +class DNSSECKeeper : public boost::noncopyable +{ +public: + enum keytype_t { KSK, ZSK, CSK }; + enum keyalgorithm_t : uint8_t { + RSAMD5=1, + DH=2, + DSA=3, + RSASHA1=5, + DSANSEC3SHA1=6, + RSASHA1NSEC3SHA1=7, + RSASHA256=8, + RSASHA512=10, + ECCGOST=12, + ECDSA256=13, + ECDSA384=14, + ED25519=15, + ED448=16 + }; + + enum dsdigestalgorithm_t : uint8_t { + SHA1=1, + SHA256=2, + GOST=3, + SHA384=4 + }; + + struct KeyMetaData + { + string fname; + unsigned int id; + bool active; + keytype_t keyType; + bool hasSEPBit; + }; + typedef std::pair keymeta_t; + typedef std::vector keyset_t; + + static string keyTypeToString(const keytype_t &keyType) + { + switch(keyType) { + case DNSSECKeeper::KSK: + return("KSK"); + case DNSSECKeeper::ZSK: + return("ZSK"); + case DNSSECKeeper::CSK: + return("CSK"); + default: + return("UNKNOWN"); + } + } + + /* + * Returns the algorithm number based on the mnemonic (or old PowerDNS value of) a string. + * See https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml for the mapping + */ + static int shorthand2algorithm(const string &algorithm) + { + if (pdns_iequals(algorithm, "rsamd5")) return RSAMD5; + if (pdns_iequals(algorithm, "dh")) return DH; + if (pdns_iequals(algorithm, "dsa")) return DSA; + if (pdns_iequals(algorithm, "rsasha1")) return RSASHA1; + if (pdns_iequals(algorithm, "dsa-nsec3-sha1")) return DSANSEC3SHA1; + if (pdns_iequals(algorithm, "rsasha1-nsec3-sha1")) return RSASHA1NSEC3SHA1; + if (pdns_iequals(algorithm, "rsasha256")) return RSASHA256; + if (pdns_iequals(algorithm, "rsasha512")) return RSASHA512; + if (pdns_iequals(algorithm, "ecc-gost")) return ECCGOST; + if (pdns_iequals(algorithm, "gost")) return ECCGOST; + if (pdns_iequals(algorithm, "ecdsa256")) return ECDSA256; + if (pdns_iequals(algorithm, "ecdsap256sha256")) return ECDSA256; + if (pdns_iequals(algorithm, "ecdsa384")) return ECDSA384; + if (pdns_iequals(algorithm, "ecdsap384sha384")) return ECDSA384; + if (pdns_iequals(algorithm, "ed25519")) return ED25519; + if (pdns_iequals(algorithm, "ed448")) return ED448; + if (pdns_iequals(algorithm, "indirect")) return 252; + if (pdns_iequals(algorithm, "privatedns")) return 253; + if (pdns_iequals(algorithm, "privateoid")) return 254; + return -1; + } + + /* + * Returns the mnemonic from https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml + */ + static string algorithm2name(uint8_t algo) { + switch(algo) { + case 0: + case 4: + case 9: + case 11: + return "Reserved"; + case RSAMD5: + return "RSAMD5"; + case DH: + return "DH"; + case DSA: + return "DSA"; + case RSASHA1: + return "RSASHA1"; + case DSANSEC3SHA1: + return "DSA-NSEC3-SHA1"; + case RSASHA1NSEC3SHA1: + return "RSASHA1-NSEC3-SHA1"; + case RSASHA256: + return "RSASHA256"; + case RSASHA512: + return "RSASHA512"; + case ECCGOST: + return "ECC-GOST"; + case ECDSA256: + return "ECDSAP256SHA256"; + case ECDSA384: + return "ECDSAP384SHA384"; + case ED25519: + return "ED25519"; + case ED448: + return "ED448"; + case 252: + return "INDIRECT"; + case 253: + return "PRIVATEDNS"; + case 254: + return "PRIVATEOID"; + default: + return "Unallocated/Reserved"; + } + } + +private: + UeberBackend* d_keymetadb; + bool d_ourDB; + +public: + DNSSECKeeper() : d_keymetadb( new UeberBackend("key-only")), d_ourDB(true) + { + + } + + DNSSECKeeper(UeberBackend* db) : d_keymetadb(db), d_ourDB(false) + { + } + + ~DNSSECKeeper() + { + if(d_ourDB) + delete d_keymetadb; + } + bool doesDNSSEC(); + bool isSecuredZone(const DNSName& zone); + static uint64_t dbdnssecCacheSizes(const std::string& str); + keyset_t getEntryPoints(const DNSName& zname); + keyset_t getKeys(const DNSName& zone, bool useCache = true); + DNSSECPrivateKey getKeyById(const DNSName& zone, unsigned int id); + bool addKey(const DNSName& zname, bool setSEPBit, int algorithm, int64_t& id, int bits=0, bool active=true); + bool addKey(const DNSName& zname, const DNSSECPrivateKey& dpk, int64_t& id, bool active=true); + bool removeKey(const DNSName& zname, unsigned int id); + bool activateKey(const DNSName& zname, unsigned int id); + bool deactivateKey(const DNSName& zname, unsigned int id); + bool checkKeys(const DNSName& zname, vector* errorMessages = nullptr); + + bool getNSEC3PARAM(const DNSName& zname, NSEC3PARAMRecordContent* n3p=0, bool* narrow=0); + bool checkNSEC3PARAM(const NSEC3PARAMRecordContent& ns3p, string& msg); + bool setNSEC3PARAM(const DNSName& zname, const NSEC3PARAMRecordContent& n3p, const bool& narrow=false); + bool unsetNSEC3PARAM(const DNSName& zname); + void clearAllCaches(); + void clearCaches(const DNSName& name); + bool getPreRRSIGs(UeberBackend& db, const DNSName& signer, const DNSName& qname, const DNSName& wildcardname, const QType& qtype, DNSResourceRecord::Place, vector& rrsigs, uint32_t signTTL); + bool isPresigned(const DNSName& zname); + bool setPresigned(const DNSName& zname); + bool unsetPresigned(const DNSName& zname); + bool setPublishCDNSKEY(const DNSName& zname); + bool unsetPublishCDNSKEY(const DNSName& zname); + bool setPublishCDS(const DNSName& zname, const string& digestAlgos); + bool unsetPublishCDS(const DNSName& zname); + + bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname); + bool getTSIGForAccess(const DNSName& zone, const ComboAddress& master, DNSName* keyname); + + void startTransaction(const DNSName& zone, int zone_id) + { + (*d_keymetadb->backends.begin())->startTransaction(zone, zone_id); + } + + void commitTransaction() + { + (*d_keymetadb->backends.begin())->commitTransaction(); + } + + void getFromMeta(const DNSName& zname, const std::string& key, std::string& value); + void getSoaEdit(const DNSName& zname, std::string& value); + bool unSecureZone(const DNSName& zone, std::string& error, std::string& info); + bool rectifyZone(const DNSName& zone, std::string& error, std::string& info, bool doTransaction); +private: + + + struct KeyCacheEntry + { + typedef vector keys_t; + + uint32_t getTTD() const + { + return d_ttd; + } + + DNSName d_domain; + mutable keys_t d_keys; + unsigned int d_ttd; + }; + + struct METACacheEntry + { + uint32_t getTTD() const + { + return d_ttd; + } + + DNSName d_domain; + mutable std::string d_key, d_value; + unsigned int d_ttd; + + }; + + + typedef multi_index_container< + KeyCacheEntry, + indexed_by< + ordered_unique >, + sequenced<> + > + > keycache_t; + typedef multi_index_container< + METACacheEntry, + indexed_by< + ordered_unique< + composite_key< + METACacheEntry, + member , + member + >, composite_key_compare, CIStringCompare> >, + sequenced<> + > + > metacache_t; + + void cleanup(); + + static keycache_t s_keycache; + static metacache_t s_metacache; + static pthread_rwlock_t s_metacachelock; + static pthread_rwlock_t s_keycachelock; + static AtomicCounter s_ops; + static time_t s_last_prune; + +public: + void preRemoval(const KeyCacheEntry&) + { + } + void preRemoval(const METACacheEntry&) + { + } +}; + +class DNSPacket; +uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq); +// for SOA-EDIT +uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename); +uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename); +// for SOA-EDIT-DNSUPDATE/API +bool increaseSOARecord(DNSResourceRecord& dr, const string& increaseKind, const string& editKind); +bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout); +DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER); diff --git a/pdns/dnssecsigner.cc b/pdns/dnssecsigner.cc new file mode 100644 index 0000000..22abee7 --- /dev/null +++ b/pdns/dnssecsigner.cc @@ -0,0 +1,237 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnssecinfra.hh" +#include "namespaces.hh" + +#include "digests.hh" +#include "dnsseckeeper.hh" +#include "dns_random.hh" +#include "lock.hh" +#include "arguments.hh" +#include "statbag.hh" +extern StatBag S; + +static pthread_rwlock_t g_signatures_lock = PTHREAD_RWLOCK_INITIALIZER; +typedef map, string> signaturecache_t; +static signaturecache_t g_signatures; +static int g_cacheweekno; + +const static std::set g_KSKSignedQTypes {QType::DNSKEY, QType::CDS, QType::CDNSKEY}; +AtomicCounter* g_signatureCount; + +static std::string getLookupKey(const std::string& msg) +{ + try { + return pdns_md5sum(msg); + } + catch(const std::runtime_error& e) { + return pdns_sha1sum(msg); + } +} + +static void fillOutRRSIG(DNSSECPrivateKey& dpk, const DNSName& signQName, RRSIGRecordContent& rrc, vector >& toSign) +{ + if(!g_signatureCount) + g_signatureCount = S.getPointer("signatures"); + + DNSKEYRecordContent drc = dpk.getDNSKEY(); + const std::shared_ptr rc = dpk.getKey(); + rrc.d_tag = drc.getTag(); + rrc.d_algorithm = drc.d_algorithm; + + string msg=getMessageForRRSET(signQName, rrc, toSign); // this is what we will hash & sign + pair lookup(rc->getPubKeyHash(), getLookupKey(msg)); // this hash is a memory saving exercise + + bool doCache=1; + if(doCache) + { + ReadLock l(&g_signatures_lock); + signaturecache_t::const_iterator iter = g_signatures.find(lookup); + if(iter != g_signatures.end()) { + rrc.d_signature=iter->second; + return; + } + // else cerr<<"Miss!"<sign(msg); + (*g_signatureCount)++; + if(doCache) { + /* we add some jitter here so not all your slaves start pruning their caches at the very same millisecond */ + int weekno = (time(0) - dns_random(3600)) / (86400*7); // we just spent milliseconds doing a signature, microsecond more won't kill us + const static int maxcachesize=::arg().asNum("max-signature-cache-entries", INT_MAX); + + WriteLock l(&g_signatures_lock); + if(g_cacheweekno < weekno || g_signatures.size() >= (uint) maxcachesize) { // blunt but effective (C) Habbie, mind04 + g_log< >& toSign, vector& rrcs) +{ + if(toSign.empty()) + return -1; + uint32_t startOfWeek = getStartOfWeek(); + RRSIGRecordContent rrc; + rrc.d_type=signQType; + + rrc.d_labels=signQName.countLabels()-signQName.isWildcard(); + rrc.d_originalttl=signTTL; + rrc.d_siginception=startOfWeek - 7*86400; // XXX should come from zone metadata + rrc.d_sigexpire=startOfWeek + 14*86400; + rrc.d_signer = signer; + rrc.d_tag = 0; + + DNSSECKeeper::keyset_t keys = dk.getKeys(signer); + + for(DNSSECKeeper::keyset_t::value_type& keymeta : keys) { + if(!keymeta.second.active) + continue; + + bool signWithKSK = g_KSKSignedQTypes.count(signQType) != 0; + // Do not sign DNSKEY RRsets with the ZSK + if((signQType == QType::DNSKEY && keymeta.second.keyType == DNSSECKeeper::ZSK) || + // Do not sign any other RRset than DNSKEY, CDS and CDNSKEY with a KSK + (!signWithKSK && keymeta.second.keyType == DNSSECKeeper::KSK)) { + continue; + } + + fillOutRRSIG(keymeta.first, signQName, rrc, toSign); + rrcs.push_back(rrc); + } + return 0; +} + +// this is the entrypoint from DNSPacket +static void addSignature(DNSSECKeeper& dk, UeberBackend& db, const DNSName& signer, const DNSName& signQName, const DNSName& wildcardname, uint16_t signQType, + uint32_t signTTL, DNSResourceRecord::Place signPlace, + vector >& toSign, vector& outsigned, uint32_t origTTL) +{ + //cerr<<"Asked to sign '"< rrcs; + if(dk.isPresigned(signer)) { + //cerr<<"Doing presignatures"<(rrc); + outsigned.push_back(rr); + } + } + toSign.clear(); +} + +uint64_t signatureCacheSize(const std::string& str) +{ + ReadLock l(&g_signatures_lock); + return g_signatures.size(); +} + +static bool rrsigncomp(const DNSZoneRecord& a, const DNSZoneRecord& b) +{ + return tie(a.dr.d_place, a.dr.d_type) < tie(b.dr.d_place, b.dr.d_type); +} + +static bool getBestAuthFromSet(const set& authSet, const DNSName& name, DNSName& auth) +{ + auth.trimToLabels(0); + DNSName sname(name); + do { + if(authSet.find(sname) != authSet.end()) { + auth = sname; + return true; + } + } + while(sname.chopOff()); + + return false; +} + +void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const set& authSet, vector& rrs) +{ + stable_sort(rrs.begin(), rrs.end(), rrsigncomp); + + DNSName signQName, wildcardQName; + uint16_t signQType=0; + uint32_t signTTL=0; + uint32_t origTTL=0; + + DNSResourceRecord::Place signPlace=DNSResourceRecord::ANSWER; + vector > toSign; + + vector signedRecords; + signedRecords.reserve(rrs.size()*1.5); + // cout<dr.d_type || signQName != pos->dr.d_name)) { + if(getBestAuthFromSet(authSet, signQName, signer)) + addSignature(dk, db, signer, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, signedRecords, origTTL); + } + signedRecords.push_back(*pos); + signQName= pos->dr.d_name.makeLowerCase(); + if(!pos->wildcardname.empty()) + wildcardQName = pos->wildcardname.makeLowerCase(); + else + wildcardQName.clear(); + signQType = pos->dr.d_type; + if(pos->signttl) + signTTL = pos->signttl; + else + signTTL = pos->dr.d_ttl; + origTTL = pos->dr.d_ttl; + signPlace = pos->dr.d_place; + if(pos->auth || pos->dr.d_type == QType::DS) { + toSign.push_back(pos->dr.d_content); // so ponder.. should this be a deep copy perhaps? + } + } + if(getBestAuthFromSet(authSet, signQName, signer)) + addSignature(dk, db, signer, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, signedRecords, origTTL); + rrs.swap(signedRecords); +} diff --git a/pdns/dnstcpbench.cc b/pdns/dnstcpbench.cc new file mode 100644 index 0000000..d69b6c6 --- /dev/null +++ b/pdns/dnstcpbench.cc @@ -0,0 +1,316 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include + +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "threadname.hh" +#include +#include +#include + + +StatBag S; +namespace po = boost::program_options; + +po::variables_map g_vm; +bool g_verbose; +bool g_onlyTCP; +bool g_tcpNoDelay; +unsigned int g_timeoutMsec; +AtomicCounter g_networkErrors, g_otherErrors, g_OK, g_truncates, g_authAnswers, g_timeOuts; +ComboAddress g_dest; + +unsigned int makeUsec(const struct timeval& tv) +{ + return 1000000*tv.tv_sec + tv.tv_usec; +} + +/* On Linux, run echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle + to prevent running out of free TCP ports */ + +struct BenchQuery +{ + BenchQuery(const std::string& qname_, uint16_t qtype_) : qname(qname_), qtype(qtype_), udpUsec(0), tcpUsec(0), answerSecond(0) {} + BenchQuery(): qtype(0), udpUsec(0), tcpUsec(0), answerSecond(0) {} + DNSName qname; + uint16_t qtype; + uint32_t udpUsec, tcpUsec; + time_t answerSecond; +}; + +void doQuery(BenchQuery* q) +try +{ + vector packet; + DNSPacketWriter pw(packet, q->qname, q->qtype); + int res; + string reply; + + struct timeval tv, now; + gettimeofday(&tv, 0); + + if(!g_onlyTCP) { + Socket udpsock(g_dest.sin4.sin_family, SOCK_DGRAM); + + udpsock.sendTo(string(packet.begin(), packet.end()), g_dest); + ComboAddress origin; + res = waitForData(udpsock.getHandle(), 0, 1000 * g_timeoutMsec); + if(res < 0) + throw NetworkError("Error waiting for response"); + if(!res) { + g_timeOuts++; + return; + } + + udpsock.recvFrom(reply, origin); + + gettimeofday(&now, 0); + q->udpUsec = makeUsec(now - tv); + tv=now; + + MOADNSParser mdp(false, reply); + if(!mdp.d_header.tc) + return; + g_truncates++; + } + + Socket sock(g_dest.sin4.sin_family, SOCK_STREAM); + int tmp=1; + if(setsockopt(sock.getHandle(),SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) + throw runtime_error("Unable to set socket reuse: "+string(strerror(errno))); + + if(g_tcpNoDelay && setsockopt(sock.getHandle(), IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof tmp)<0) + throw runtime_error("Unable to set socket no delay: "+string(strerror(errno))); + + sock.connect(g_dest); + uint16_t len = htons(packet.size()); + string tcppacket((char*)& len, 2); + tcppacket.append(packet.begin(), packet.end()); + + sock.writen(tcppacket); + + res = waitForData(sock.getHandle(), 0, 1000 * g_timeoutMsec); + if(res < 0) + throw NetworkError("Error waiting for response"); + if(!res) { + g_timeOuts++; + return; + } + + if(sock.read((char *) &len, 2) != 2) + throw PDNSException("tcp read failed"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(ntcpUsec = makeUsec(now - tv); + q->answerSecond = now.tv_sec; + + MOADNSParser mdp(false, reply); + // cout<<"Had correct TCP/IP response, "< g_queries; + +static void* worker(void*) +{ + setThreadName("dnstcpb/worker"); + for(;;) { + unsigned int pos = g_pos++; + if(pos >= g_queries.size()) + break; + + doQuery(&g_queries[pos]); // this is safe as long as nobody *inserts* to g_queries + } + return 0; +} + +void usage(po::options_description &desc) { + cerr<<"Syntax: dnstcpbench REMOTE [PORT] < QUERIES"<(), "source file - if not specified, defaults to stdin") + ("tcp-no-delay", po::value()->default_value(true), "use TCP_NODELAY socket option") + ("timeout-msec", po::value()->default_value(10), "wait for this amount of milliseconds for an answer") + ("workers", po::value()->default_value(100), "number of parallel workers"); + + hidden.add_options() + ("remote-host", po::value(), "remote-host") + ("remote-port", po::value()->default_value(53), "remote-port"); + alloptions.add(desc).add(hidden); + + po::positional_options_description p; + p.add("remote-host", 1); + p.add("remote-port", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + if(g_vm.count("version")) { + cerr<<"dnstcpbench "<(); + + g_onlyTCP = !g_vm.count("udp-first"); + g_verbose = g_vm.count("verbose"); + g_timeoutMsec = g_vm["timeout-msec"].as(); + + reportAllTypes(); + + if(g_vm["remote-host"].empty()) { + usage(desc); + exit(EXIT_FAILURE); + } + + g_dest = ComboAddress(g_vm["remote-host"].as().c_str(), g_vm["remote-port"].as()); + + unsigned int numworkers=g_vm["workers"].as(); + + if(g_verbose) { + cout<<"Sending queries to: "< workers(numworkers); + + FILE* fp; + if(!g_vm.count("file")) + fp=fdopen(0, "r"); + else { + fp=fopen(g_vm["file"].as().c_str(), "r"); + if(!fp) + unixDie("Unable to open "+g_vm["file"].as()+" for input"); + } + pair q; + string line; + while(stringfgets(fp, line)) { + trim_right(line); + q=splitField(line, ' '); + g_queries.push_back(BenchQuery(q.first, DNSRecordContent::TypeToNumber(q.second))); + } + fclose(fp); + + for(unsigned int n = 0; n < numworkers; ++n) { + pthread_create(&workers[n], 0, worker, 0); + } + for(unsigned int n = 0; n < numworkers; ++n) { + void* status; + pthread_join(workers[n], &status); + } + + using namespace boost::accumulators; + typedef accumulator_set< + double + , stats + > acc_t; + + acc_t udpspeeds, tcpspeeds, qps; + + typedef map counts_t; + counts_t counts; + + for(const BenchQuery& bq : g_queries) { + counts[bq.answerSecond]++; + udpspeeds(bq.udpUsec); + tcpspeeds(bq.tcpUsec); + } + + for(const counts_t::value_type& val : counts) { + qps(val.second); + } + + cout<<"Average qps: "< +#include "base64.hh" + +StatBag S; + +namespace po = boost::program_options; +po::variables_map g_vm; + + +class IPObfuscator +{ +public: + virtual ~IPObfuscator() + { + } + virtual uint32_t obf4(uint32_t orig)=0; + virtual struct in6_addr obf6(const struct in6_addr& orig)=0; +}; + +class IPSeqObfuscator : public IPObfuscator +{ +public: + IPSeqObfuscator() : d_romap(d_ipmap), d_ro6map(d_ip6map), d_counter(0) + { + } + + ~IPSeqObfuscator() + {} + + static std::unique_ptr make() + { + return std::unique_ptr(new IPSeqObfuscator()); + } + + uint32_t obf4(uint32_t orig) override + { + if(d_romap.count(orig)) + return d_ipmap[orig]; + else { + return d_ipmap[orig]=d_counter++; + } + } + + struct in6_addr obf6(const struct in6_addr& orig) override + { + uint32_t val; + if(d_ro6map.count(orig)) + val=d_ip6map[orig]; + else { + val=d_ip6map[orig]=d_counter++; + } + struct in6_addr ret; + + val=htonl(val); + memset(&ret, 0, sizeof(ret)); + memcpy(((char*)&ret)+12, &val, 4); + return ret; + } + +private: + map d_ipmap; + const decltype(d_ipmap)& d_romap; + + struct cmp { + bool operator()(const struct in6_addr&a , const struct in6_addr&b) const + { + return memcmp(&a, &b, sizeof(a)) < 0; + } + }; + // For IPv6 addresses + map d_ip6map; + const decltype(d_ip6map)& d_ro6map; + + // The counter that we'll convert to an IP address + uint32_t d_counter; +}; + +class IPCipherObfuscator : public IPObfuscator +{ +public: + IPCipherObfuscator(const std::string& key, bool decrypt) : d_key(key), d_decrypt(decrypt) + { + if(d_key.size()!=16) { + throw std::runtime_error("IPCipher requires a 128 bit key"); + } + } + + ~IPCipherObfuscator() + {} + static std::unique_ptr make(std::string key, bool decrypt) + { + return std::unique_ptr(new IPCipherObfuscator(key, decrypt)); + } + + uint32_t obf4(uint32_t orig) override + { + ComboAddress ca; + ca.sin4.sin_family = AF_INET; + ca.sin4.sin_addr.s_addr = orig; + ca = d_decrypt ? decryptCA(ca, d_key) : encryptCA(ca, d_key); + return ca.sin4.sin_addr.s_addr; + + } + + struct in6_addr obf6(const struct in6_addr& orig) override + { + ComboAddress ca; + ca.sin4.sin_family = AF_INET6; + ca.sin6.sin6_addr = orig; + ca = d_decrypt ? decryptCA(ca, d_key) : encryptCA(ca, d_key); + return ca.sin6.sin6_addr; + } + +private: + std::string d_key; + bool d_decrypt; +}; + + +void usage() { + cerr<<"Syntax: dnswasher INFILE1 [INFILE2..] OUTFILE"<(), "base64 encoded 128 bit key for ipcipher") + ("passphrase,p", po::value(), "passphrase for ipcipher (will be used to derive key)") + ("decrypt,d", "decrypt IP addresses with ipcipher"); + + po::options_description alloptions; + po::options_description hidden("hidden options"); + hidden.add_options() + ("infiles", po::value>(), "PCAP source file(s)") + ("outfile", po::value(), "outfile"); + + + alloptions.add(desc).add(hidden); + po::positional_options_description p; + p.add("infiles", 1); + p.add("outfile", 1); + + po::store(po::command_line_parser(argc, argv).options(alloptions).positional(p).run(), g_vm); + po::notify(g_vm); + + if(g_vm.count("help")) { + usage(); + cout<()); + std::unique_ptr ipo; + + if(!g_vm.count("key") && !g_vm.count("passphrase")) + ipo = IPSeqObfuscator::make(); + else if(g_vm.count("key") && !g_vm.count("passphrase")) { + string key; + if(B64Decode(g_vm["key"].as(), key) < 0) { + cerr<<"Invalidly encoded base64 key provided"<()); + + ipo = IPCipherObfuscator::make(key, doDecrypt); + } + else { + cerr<<"Can't specify both 'key' and 'passphrase'"<>()) { + PcapPacketReader pr(inf); + pw.setPPR(pr); + + while(pr.getUDPPacket()) { + if(ntohs(pr.d_udp->uh_dport)==53 || (ntohs(pr.d_udp->uh_sport)==53 && pr.d_len > sizeof(dnsheader))) { + dnsheader* dh=(dnsheader*)pr.d_payload; + + if (pr.d_ip->ip_v == 4){ + uint32_t *src=(uint32_t*)&pr.d_ip->ip_src; + uint32_t *dst=(uint32_t*)&pr.d_ip->ip_dst; + + if(dh->qr) + *dst=ipo->obf4(*dst); + else + *src=ipo->obf4(*src); + + pr.d_ip->ip_sum=0; + } else if (pr.d_ip->ip_v == 6) { + auto src=&pr.d_ip6->ip6_src; + auto dst=&pr.d_ip6->ip6_dst; + + if(dh->qr) + *dst=ipo->obf6(*dst); + else + *src=ipo->obf6(*src); + // IPv6 checksum does not cover source/destination addresses + } + pw.write(); + } + } + cerr<<"Saw "< +#if BOOST_VERSION >= 105400 +#include +#endif +#include "dnswriter.hh" +#include "misc.hh" +#include "dnsparser.hh" + +#include + +/* d_content: <---- d_stuff ----> + v d_truncatemarker + dnsheader | qname | qtype | qclass | {recordname| dnsrecordheader | record } + ^ d_rollbackmarker ^ d_sor + + +*/ + + +DNSPacketWriter::DNSPacketWriter(vector& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode) + : d_content(content), d_qname(qname), d_canonic(false), d_lowerCase(false) +{ + d_content.clear(); + dnsheader dnsheader; + + memset(&dnsheader, 0, sizeof(dnsheader)); + dnsheader.id=0; + dnsheader.qdcount=htons(1); + dnsheader.opcode=opcode; + + const uint8_t* ptr=(const uint8_t*)&dnsheader; + uint32_t len=d_content.size(); + d_content.resize(len + sizeof(dnsheader)); + uint8_t* dptr=(&*d_content.begin()) + len; + + memcpy(dptr, ptr, sizeof(dnsheader)); + d_namepositions.reserve(16); + xfrName(qname, false); + xfr16BitInt(qtype); + xfr16BitInt(qclass); + + d_truncatemarker=d_content.size(); + d_sor = 0; + d_rollbackmarker = 0; +} + +dnsheader* DNSPacketWriter::getHeader() +{ + return reinterpret_cast(&*d_content.begin()); +} + + +void DNSPacketWriter::startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl, uint16_t qclass, DNSResourceRecord::Place place, bool compress) +{ + d_compress = compress; + commit(); + d_rollbackmarker=d_content.size(); + + if(compress && !name.isRoot() && d_qname==name) { // don't do the whole label compression thing if we *know* we can get away with "see question" - except when compressing the root + static unsigned char marker[2]={0xc0, 0x0c}; + d_content.insert(d_content.end(), (const char *) &marker[0], (const char *) &marker[2]); + } + else { + xfrName(name, compress); + } + xfr16BitInt(qtype); + xfr16BitInt(qclass); + xfr32BitInt(ttl); + xfr16BitInt(0); // this will be the record size + d_recordplace = place; + d_sor=d_content.size(); // this will remind us where to stuff the record size +} + +void DNSPacketWriter::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version) +{ + uint32_t ttl=0; + + EDNS0Record stuff; + + stuff.version = version; + stuff.extFlags = htons(ednsFlags); + + /* RFC 6891 section 4 on the Extended RCode wire format + * EXTENDED-RCODE + * Forms the upper 8 bits of extended 12-bit RCODE (together with the + * 4 bits defined in [RFC1035]. Note that EXTENDED-RCODE value 0 + * indicates that an unextended RCODE is in use (values 0 through 15). + */ + // XXX Should be check for extRCode > 1<<12 ? + stuff.extRCode = extRCode>>4; + if (extRCode != 0) { // As this trumps the existing RCODE + getHeader()->rcode = extRCode; + } + + static_assert(sizeof(EDNS0Record) == sizeof(ttl), "sizeof(EDNS0Record) must match sizeof(ttl)"); + memcpy(&ttl, &stuff, sizeof(stuff)); + + ttl=ntohl(ttl); // will be reversed later on + + startRecord(g_rootdnsname, QType::OPT, ttl, udpsize, DNSResourceRecord::ADDITIONAL, false); + for(auto const &option : options) { + xfr16BitInt(option.first); + xfr16BitInt(option.second.length()); + xfrBlob(option.second); + } +} + +void DNSPacketWriter::xfr48BitInt(uint64_t val) +{ + unsigned char bytes[6]; + uint16_t theLeft = htons((val >> 32)&0xffffU); + uint32_t theRight = htonl(val & 0xffffffffU); + memcpy(bytes, (void*)&theLeft, sizeof(theLeft)); + memcpy(bytes+2, (void*)&theRight, sizeof(theRight)); + + d_content.insert(d_content.end(), bytes, bytes + sizeof(bytes)); +} + + +void DNSPacketWriter::xfr32BitInt(uint32_t val) +{ + uint32_t rval=htonl(val); + uint8_t* ptr=reinterpret_cast(&rval); + d_content.insert(d_content.end(), ptr, ptr+4); +} + +void DNSPacketWriter::xfr16BitInt(uint16_t val) +{ + uint16_t rval=htons(val); + uint8_t* ptr=reinterpret_cast(&rval); + d_content.insert(d_content.end(), ptr, ptr+2); +} + +void DNSPacketWriter::xfr8BitInt(uint8_t val) +{ + d_content.push_back(val); +} + + +/* input: + if lenField is true + "" -> 0 + "blah" -> 4blah + "blah" "blah" -> output 4blah4blah + "verylongstringlongerthan256....characters" \xffverylongstring\x23characters (autosplit) + "blah\"blah" -> 9blah"blah + "blah\97" -> 5blahb + + if lenField is false + "blah" -> blah + "blah\"blah" -> blah"blah + */ +void DNSPacketWriter::xfrText(const string& text, bool, bool lenField) +{ + if(text.empty()) { + d_content.push_back(0); + return; + } + vector segments = segmentDNSText(text); + for(const string& str : segments) { + if(lenField) + d_content.push_back(str.length()); + d_content.insert(d_content.end(), str.c_str(), str.c_str() + str.length()); + } +} + +void DNSPacketWriter::xfrUnquotedText(const string& text, bool lenField) +{ + if(text.empty()) { + d_content.push_back(0); + return; + } + if(lenField) + d_content.push_back(text.length()); + d_content.insert(d_content.end(), text.c_str(), text.c_str() + text.length()); +} + + +static constexpr bool l_verbose=false; +static constexpr uint16_t maxCompressionOffset=16384; +uint16_t DNSPacketWriter::lookupName(const DNSName& name, uint16_t* matchLen) +{ + // iterate over the written labels, see if we find a match + const auto& raw = name.getStorage(); + + /* name might be a.root-servers.net, we need to be able to benefit from finding: + b.root-servers.net, or even: + b\xc0\x0c + */ + unsigned int bestpos=0; + *matchLen=0; +#if BOOST_VERSION >= 105400 + boost::container::static_vector nvect, pvect; +#else + vector nvect, pvect; +#endif + + try { + for(auto riter= raw.cbegin(); riter < raw.cend(); ) { + if(!*riter) + break; + nvect.push_back(riter - raw.cbegin()); + riter+=*riter+1; + } + } + catch(std::bad_alloc& ba) { + if(l_verbose) + cout<<"Domain "<= maxCompressionOffset) break; // compression pointers cannot point here + pvect.push_back(offset); + iter+=*iter+1; + } + } + catch(std::bad_alloc& ba) { + if(l_verbose) + cout<<"Domain "<> 8)); + d_content.push_back((char)(offset & 0xff)); + } + else { + unsigned int pos=d_content.size(); + if(l_verbose) + cout<<"Found nothing, we are at pos "< lc; + if(d_lowerCase) + lc = make_unique(name.makeLowerCase()); + + const DNSName::string_t& raw = (lc ? *lc : name).getStorage(); + if(l_verbose) + cout<<"Writing out the whole thing "<(blob.c_str()); + d_content.insert(d_content.end(), ptr, ptr+blob.size()); +} + +void DNSPacketWriter::xfrBlobNoSpaces(const string& blob, int ) +{ + xfrBlob(blob); +} + +void DNSPacketWriter::xfrHexBlob(const string& blob, bool keepReading) +{ + xfrBlob(blob); +} + +// call __before commit__ +void DNSPacketWriter::getRecordPayload(string& records) +{ + records.assign(d_content.begin() + d_sor, d_content.end()); +} + +uint32_t DNSPacketWriter::size() +{ + return d_content.size(); +} + +void DNSPacketWriter::rollback() +{ + d_content.resize(d_rollbackmarker); + d_sor = 0; +} + +void DNSPacketWriter::truncate() +{ + d_content.resize(d_truncatemarker); + dnsheader* dh=reinterpret_cast( &*d_content.begin()); + dh->ancount = dh->nscount = dh->arcount = 0; +} + +void DNSPacketWriter::commit() +{ + if(!d_sor) + return; + uint16_t rlen = d_content.size() - d_sor; + d_content[d_sor-2]=rlen >> 8; + d_content[d_sor-1]=rlen & 0xff; + d_sor=0; + dnsheader* dh=reinterpret_cast( &*d_content.begin()); + switch(d_recordplace) { + case DNSResourceRecord::QUESTION: + dh->qdcount = htons(ntohs(dh->qdcount) + 1); + break; + case DNSResourceRecord::ANSWER: + dh->ancount = htons(ntohs(dh->ancount) + 1); + break; + case DNSResourceRecord::AUTHORITY: + dh->nscount = htons(ntohs(dh->nscount) + 1); + break; + case DNSResourceRecord::ADDITIONAL: + dh->arcount = htons(ntohs(dh->arcount) + 1); + break; + } + +} diff --git a/pdns/dnswriter.hh b/pdns/dnswriter.hh new file mode 100644 index 0000000..16048f1 --- /dev/null +++ b/pdns/dnswriter.hh @@ -0,0 +1,177 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DNSWRITER_HH +#define PDNS_DNSWRITER_HH + +#include +#include +#include +#include "dns.hh" +#include "dnsname.hh" +#include "namespaces.hh" +#include "iputils.hh" +#include + + +/** this class can be used to write DNS packets. It knows about DNS in the sense that it makes + the packet header and record headers. + + The model is: + + packetheader (recordheader recordcontent)* + + The packetheader needs to be updated with the amount of packets of each kind (answer, auth, additional) + + Each recordheader contains the length of a dns record. + + Calling convention: + + vector content; + DNSPacketWriter dpw(content, const string& qname, uint16_t qtype, uint16_t qclass=QClass:IN); // sets the question + dpw.startrecord("this.is.an.ip.address.", ns_t_a); // does nothing, except store qname and qtype + dpw.xfr32BitInt(0x01020304); // adds 4 bytes (0x01020304) to the record buffer + dpw.startrecord("this.is.an.ip.address.", ns_t_a); // aha! writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer, which gets emptied + // new qname and qtype are stored + dpw.xfr32BitInt(0x04030201); // adds 4 bytes (0x04030201) to the record buffer + dpw.commit(); // writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer + + // content now contains the ready packet, with 1 question and 2 answers + +*/ + +class DNSPacketWriter : public boost::noncopyable +{ + +public: + //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass + DNSPacketWriter(vector& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0); + + /** Start a new DNS record within this packet for namq, qtype, ttl, class and in the requested place. Note that packets can only be written in natural order - + ANSWER, AUTHORITY, ADDITIONAL */ + void startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl=3600, uint16_t qclass=QClass::IN, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, bool compress=true); + + /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */ + typedef vector > optvect_t; + void addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options=optvect_t(), const uint8_t version=0); + + /** needs to be called after the last record is added, but can be called again and again later on. Is called internally by startRecord too. + The content of the vector<> passed to the constructor is inconsistent until commit is called. + */ + void commit(); + + uint32_t size(); // needs to be 32 bit because otherwise we don't see the wrap coming when it happened! + + /** Should the packet have grown too big for the writer's liking, rollback removes the record currently being written */ + void rollback(); + + /** Discard all content except the question section */ + void truncate(); + + void xfr48BitInt(uint64_t val); + void xfr32BitInt(uint32_t val); + void xfr16BitInt(uint16_t val); + void xfrType(uint16_t val) + { + xfr16BitInt(val); + } + void xfrIP(const uint32_t& val) + { + xfr32BitInt(htonl(val)); + } + void xfrIP6(const std::string& val) + { + xfrBlob(val,16); + } + + void xfrCAWithoutPort(uint8_t version, ComboAddress &val) + { + if (version == 4) xfrIP(val.sin4.sin_addr.s_addr); + else if (version == 6) { + string blob; + blob.assign((const char*)val.sin6.sin6_addr.s6_addr, 16); + xfrBlob(blob, 16); + } + else throw runtime_error("invalid IP protocol"); + } + + void xfrCAPort(ComboAddress &val) + { + uint16_t port; + port = val.sin4.sin_port; + xfr16BitInt(port); + } + + void xfrTime(const uint32_t& val) + { + xfr32BitInt(val); + } + + void xfr8BitInt(uint8_t val); + + void xfrName(const DNSName& label, bool compress=false, bool noDot=false); + void xfrText(const string& text, bool multi=false, bool lenField=true); + void xfrUnquotedText(const string& text, bool lenField); + void xfrBlob(const string& blob, int len=-1); + void xfrBlobNoSpaces(const string& blob, int len=-1); + void xfrHexBlob(const string& blob, bool keepReading=false); + + dnsheader* getHeader(); + void getRecordPayload(string& records); // call __before commit__ + + void setCanonic(bool val) + { + d_canonic=val; + } + + void setLowercase(bool val) + { + d_lowerCase=val; + } + vector & getContent() + { + return d_content; + } + bool eof() { return true; } // we don't know how long the record should be + + const string getRemaining() const { + return ""; + } +private: + uint16_t lookupName(const DNSName& name, uint16_t* matchlen); + vector d_namepositions; + // We declare 1 uint_16 in the public section, these 3 align on a 8-byte boundry + uint16_t d_sor; + uint16_t d_rollbackmarker; // start of last complete packet, for rollback + + vector & d_content; + DNSName d_qname; + + uint16_t d_truncatemarker; // end of header, for truncate + DNSResourceRecord::Place d_recordplace; + bool d_canonic, d_lowerCase, d_compress{false}; +}; + +typedef vector > labelparts_t; +// bool labeltokUnescape(labelparts_t& parts, const DNSName& label); +std::vector segmentDNSText(const string& text); // from dnslabeltext.rl +std::deque segmentDNSName(const string& input ); // from dnslabeltext.rl +#endif diff --git a/pdns/doh.hh b/pdns/doh.hh new file mode 100644 index 0000000..2fa36fa --- /dev/null +++ b/pdns/doh.hh @@ -0,0 +1,68 @@ +#pragma once +#include "iputils.hh" + +struct DOHServerConfig; + +struct DOHFrontend +{ + std::shared_ptr d_dsc{nullptr}; + std::vector> d_certKeyPairs; + std::string d_ciphers; + std::string d_ciphers13; + std::string d_serverTokens{"h2o/dnsdist"}; + ComboAddress d_local; + + uint32_t d_idleTimeout{30}; // HTTP idle timeout in seconds + std::vector d_urls; + + std::atomic d_httpconnects; // number of TCP/IP connections established + std::atomic d_http1queries; // valid DNS queries received via HTTP1 + std::atomic d_http2queries; // valid DNS queries received via HTTP2 + std::atomic d_tls10queries; // valid DNS queries received via TLSv1.0 + std::atomic d_tls11queries; // valid DNS queries received via TLSv1.1 + std::atomic d_tls12queries; // valid DNS queries received via TLSv1.2 + std::atomic d_tls13queries; // valid DNS queries received via TLSv1.3 + std::atomic d_tlsUnknownqueries; // valid DNS queries received via unknown TLS version + + std::atomic d_getqueries; // valid DNS queries received via GET + std::atomic d_postqueries; // valid DNS queries received via POST + std::atomic d_badrequests; // request could not be converted to dns query + std::atomic d_errorresponses; // dnsdist set 'error' on response + std::atomic d_validresponses; // valid responses sent out + +#ifndef HAVE_DNS_OVER_HTTPS + void setup() + { + } + + void reloadCertificates() + { + } +#else + void setup(); + void reloadCertificates(); +#endif /* HAVE_DNS_OVER_HTTPS */ +}; + +#ifndef HAVE_DNS_OVER_HTTPS +struct DOHUnit +{ +}; + +#else /* HAVE_DNS_OVER_HTTPS */ +struct st_h2o_req_t; + +struct DOHUnit +{ + std::string query; + ComboAddress remote; + ComboAddress dest; + st_h2o_req_t* req{nullptr}; + DOHUnit** self{nullptr}; + int rsock; + uint16_t qtype; + bool error{false}; + bool ednsAdded{false}; +}; + +#endif /* HAVE_DNS_OVER_HTTPS */ diff --git a/pdns/dumresp.cc b/pdns/dumresp.cc new file mode 100644 index 0000000..5d457dc --- /dev/null +++ b/pdns/dumresp.cc @@ -0,0 +1,226 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "iputils.hh" +#include "sstuff.hh" +#include "statbag.hh" +#include +#include +#include +StatBag S; + +static std::atomic* g_counter; + +static void printStatus() +{ + auto prev= g_counter->load(); + for(;;) { + sleep(1); + cout<load()-prev<<"\t"<load()<load(); + } +} + +static void usage() { + cerr<<"Syntax: dumresp LOCAL-ADDRESS LOCAL-PORT NUMBER-OF-PROCESSES [tcp]"<qr=1; + dh->ad=0; +} + +static void tcpConnectionHandler(int sock) +try +{ + char buffer[1500]; + auto dh = reinterpret_cast(buffer); + + for (;;) { + uint16_t len = 0; + ssize_t got = read(sock, &len, sizeof(len)); + + if (got == 0) { + break; + } + + if (got != sizeof(len)) + unixDie("read 1"); + + len = ntohs(len); + + if (len < sizeof(dnsheader)) + unixDie("too small"); + + if (len > sizeof(buffer)) + unixDie("too large"); + + got = read(sock, buffer, len); + if (got != len) + unixDie("read 2: " + std::to_string(got) + " / " + std::to_string(len)); + + if (dh->qr) + continue; + + turnQueryIntoResponse(dh); + + uint16_t wirelen = htons(len); + if (write(sock, &wirelen, sizeof(wirelen)) != sizeof(wirelen)) + unixDie("send 1"); + + if (write(sock, buffer, len) < 0) + unixDie("send 2"); + } + + close(sock); +} +catch(const std::exception& e) { + cerr<<"TCP connection handler got an exception: "<(&rem), &socklen); + if (sock == -1) { + continue; + } + + std::thread connectionHandler(tcpConnectionHandler, sock); + connectionHandler.detach(); + } +} + +int main(int argc, char** argv) +try +{ + bool tcp = false; + + for(int i = 1; i < argc; i++) { + if(std::string(argv[i]) == "--help"){ + usage(); + return(EXIT_SUCCESS); + } + + if(std::string(argv[i]) == "--version"){ + cerr<<"dumresp "<), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + g_counter = new(ptr) std::atomic(); + + int numberOfListeners = atoi(argv[3]); + ComboAddress local(argv[1], atoi(argv[2])); + + int i=1; + for(; i < numberOfListeners; ++i) { + if(!fork()) + break; + } + + if (i==1) { + std::thread t(printStatus); + t.detach(); + + if (tcp) { + for (int j = 0; j < numberOfListeners; j++) { + cout<<"Listening to TCP "<(buffer); + + for(;;) { + ssize_t len = recvfrom(s.getHandle(), buffer, sizeof(buffer), 0, reinterpret_cast(&rem), &socklen); + + if(len < 0) + unixDie("recvfrom"); + + if (static_cast(len) < sizeof(dnsheader)) + unixDie("too small " + std::to_string(len)); + + if(dh->qr) + continue; + + turnQueryIntoResponse(dh); + + if(sendto(s.getHandle(), buffer, len, 0, reinterpret_cast(&rem), socklen) < 0) + unixDie("sendto"); + } +} +catch(const std::exception& e) +{ + cerr<<"Fatal error: "< +#include "misc.hh" +#include "communicator.hh" +#include "dnsseckeeper.hh" +#include "nameserver.hh" +#include "responsestats.hh" +#include "ueberbackend.hh" +#include "common_startup.hh" + +extern ResponseStats g_rs; + +static bool s_pleasequit; +static string d_status; + +bool DLQuitPlease() +{ + return s_pleasequit; +} + +string DLQuitHandler(const vector&parts, Utility::pid_t ppid) +{ + string ret="No return value"; + if(parts[0]=="QUIT") { + s_pleasequit=true; + ret="Scheduling exit"; + g_log<&parts, Utility::pid_t ppid) +{ + return ::arg().configstring(true); +} + +string DLRQuitHandler(const vector&parts, Utility::pid_t ppid) +{ + signal(SIGALRM, dokill); + alarm(1); + return "Exiting"; +} + +string DLPingHandler(const vector&parts, Utility::pid_t ppid) +{ + return "PONG"; +} + +string DLShowHandler(const vector&parts, Utility::pid_t ppid) { + try { + extern StatBag S; + string ret("Wrong number of parameters"); + if (parts.size() == 2) { + if (parts[1] == "*") + ret = S.directory(); + else + ret = S.getValueStr(parts[1]); + } + + return ret; + } + catch (...) { + return "Unknown"; + } +} + +void setStatus(const string &str) +{ + d_status=str; +} + +string DLStatusHandler(const vector&parts, Utility::pid_t ppid) +{ + ostringstream os; + os<&parts, Utility::pid_t ppid) +{ + ostringstream os; + os<&parts, Utility::pid_t ppid) +{ + DNSSECKeeper dk; + ostringstream os; + int ret=0; + + if(parts.size()>1) { + for (vector::const_iterator i=++parts.begin();i&parts, Utility::pid_t ppid) +{ + extern AuthPacketCache PC; + extern AuthQueryCache QC; + map counts=QC.getCounts(); + uint64_t packetEntries = PC.size(); + ostringstream os; + bool first=true; + for(map::const_iterator i=counts.begin();i!=counts.end();++i) { + if(!first) + os<<", "; + first=false; + + if(i->first=='!') + os<<"negative queries: "; + else if(i->first=='Q') + os<<"queries: "; + else + os<<"unknown: "; + + os<second; + } + os<<"packets: "<&parts, Utility::pid_t ppid) +{ + return g_rs.getQTypeReport(); +} + +string DLRSizesHandler(const vector&parts, Utility::pid_t ppid) +{ + typedef map respsizes_t; + respsizes_t respsizes = g_rs.getSizeResponseCounts(); + ostringstream os; + boost::format fmt("%d\t%d\n"); + for(const respsizes_t::value_type& val : respsizes) { + os << (fmt % val.first % val.second).str(); + } + return os.str(); +} + +string DLRemotesHandler(const vector&parts, Utility::pid_t ppid) +{ + extern StatBag S; + typedef vector > totals_t; + totals_t totals = S.getRing("remotes"); + string ret; + boost::format fmt("%s\t%d\n"); + for(totals_t::value_type& val : totals) { + ret += (fmt % val.first % val.second).str(); + } + return ret; +} + +string DLSettingsHandler(const vector&parts, Utility::pid_t ppid) +{ + static const char *whitelist[]={"query-logging",0}; + const char **p; + + if(parts.size()!=3) { + return "Syntax: set variable value"; + } + + for(p=whitelist;*p;p++) + if(*p==parts[1]) + break; + if(*p) { + ::arg().set(parts[1])=parts[2]; + return "done"; + } + else + return "This setting cannot be changed at runtime, or no such setting"; + +} + +string DLVersionHandler(const vector&parts, Utility::pid_t ppid) +{ + return VERSION; +} + +string DLNotifyRetrieveHandler(const vector&parts, Utility::pid_t ppid) +{ + extern CommunicatorClass Communicator; + ostringstream os; + if(parts.size()!=2) + return "syntax: retrieve domain"; + + DNSName domain; + try { + domain = DNSName(parts[1]); + } catch (...) { + return "Failed to parse domain as valid DNS name"; + } + + DomainInfo di; + UeberBackend B; + if(!B.getDomainInfo(domain, di)) + return "Domain '"+domain.toString()+"' unknown"; + + if(di.kind != DomainInfo::Slave || di.masters.empty()) + return "Domain '"+domain.toString()+"' is not a slave domain (or has no master defined)"; + + random_shuffle(di.masters.begin(), di.masters.end()); + Communicator.addSuckRequest(domain, di.masters.front()); + return "Added retrieval request for '"+domain.toString()+"' from master "+di.masters.front().toLogString(); +} + +string DLNotifyHostHandler(const vector&parts, Utility::pid_t ppid) +{ + extern CommunicatorClass Communicator; + ostringstream os; + if(parts.size()!=3) + return "syntax: notify-host domain ip"; + if(!::arg().mustDo("master") && !(::arg().mustDo("slave") && ::arg().mustDo("slave-renotify"))) + return "PowerDNS not configured as master or slave with re-notifications"; + + DNSName domain; + try { + domain = DNSName(parts[1]); + } catch (...) { + return "Failed to parse domain as valid DNS name"; + } + + try { + ComboAddress ca(parts[2]); + } catch(...) + { + return "Unable to convert '"+parts[2]+"' to an IP address"; + } + + g_log<&parts, Utility::pid_t ppid) +{ + extern CommunicatorClass Communicator; + UeberBackend B; + if(parts.size()!=2) + return "syntax: notify domain"; + if(!::arg().mustDo("master") && !(::arg().mustDo("slave") && ::arg().mustDo("slave-renotify"))) + return "PowerDNS not configured as master or slave with re-notifications"; + g_log< domains; + B.getAllDomains(&domains); + + int total = 0; + int notified = 0; + for (const auto& di : domains) { + if (di.kind == DomainInfo::Master || di.kind == DomainInfo::Slave) { // MASTER and Slave if slave-renotify is enabled + total++; + if(Communicator.notifyDomain(di.zone, &B)) + notified++; + } + } + + if (total != notified) + return itoa(notified)+" out of "+itoa(total)+" zones added to queue - see log"; + return "Added "+itoa(total)+" MASTER/SLAVE zones to queue"; + } else { + DNSName domain; + try { + domain = DNSName(parts[1]); + } catch (...) { + return "Failed to parse domain as valid DNS name"; + } + if(!Communicator.notifyDomain(DNSName(parts[1]), &B)) + return "Failed to add to the queue - see log"; + return "Added to queue"; + } +} + +string DLRediscoverHandler(const vector&parts, Utility::pid_t ppid) +{ + UeberBackend B; + try { + g_log<&parts, Utility::pid_t ppid) +{ + UeberBackend B; + B.reload(); + g_log<&parts, Utility::pid_t ppid) +{ + UeberBackend B; + g_log< domains; + B.getAllDomains(&domains); + ostringstream ret; + int kindFilter = -1; + if (parts.size() > 1) { + if (toUpper(parts[1]) == "MASTER") + kindFilter = 0; + else if (toUpper(parts[1]) == "SLAVE") + kindFilter = 1; + else if (toUpper(parts[1]) == "NATIVE") + kindFilter = 2; + } + + int count = 0; + + for (const auto& di: domains) { + if (di.kind == kindFilter || kindFilter == -1) { + ret<&parts, Utility::pid_t ppid) +{ +#ifndef HAVE_P11KIT1 + return "PKCS#11 support not compiled in"; +#else + if (parts.size() != 4) { + return "invalid number of parameters, needs 4, got " + std::to_string(parts.size()); + } + + if (PKCS11ModuleSlotLogin(parts[1], parts[2], parts[3])) { + return "logged in"; + } else { + return "could not log in, check logs"; + } +#endif +} diff --git a/pdns/dynhandler.hh b/pdns/dynhandler.hh new file mode 100644 index 0000000..6a7ab6e --- /dev/null +++ b/pdns/dynhandler.hh @@ -0,0 +1,60 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DYNHANDLER_HH +#define PDNS_DYNHANDLER_HH + +#include +#include +#include +#include + +#include + +#include "namespaces.hh" + + +bool DLQuitPlease(); +void setStatus(const string &str); +string DLQuitHandler(const vector&parts, Utility::pid_t ppid); +string DLRQuitHandler(const vector&parts, Utility::pid_t ppid); +string DLPingHandler(const vector&parts, Utility::pid_t ppid); +string DLShowHandler(const vector&parts, Utility::pid_t ppid); +string DLUptimeHandler(const vector&parts, Utility::pid_t ppid); +string DLSettingsHandler(const vector&parts, Utility::pid_t ppid); +string DLRespSizeHandler(const vector&parts, Utility::pid_t ppid); +string DLCCHandler(const vector&parts, Utility::pid_t ppid); +string DLQTypesHandler(const vector&parts, Utility::pid_t ppid); +string DLRSizesHandler(const vector&parts, Utility::pid_t ppid); +string DLRemotesHandler(const vector&parts, Utility::pid_t ppid); +string DLStatusHandler(const vector&parts, Utility::pid_t ppid); +string DLNotifyHandler(const vector&parts, Utility::pid_t ppid); +string DLNotifyHostHandler(const vector&parts, Utility::pid_t ppid); +string DLReloadHandler(const vector&parts, Utility::pid_t ppid); +string DLRediscoverHandler(const vector&parts, Utility::pid_t ppid); +string DLVersionHandler(const vector&parts, Utility::pid_t ppid); +string DLPurgeHandler(const vector&parts, Utility::pid_t ppid); +string DLNotifyRetrieveHandler(const vector&parts, Utility::pid_t ppid); +string DLCurrentConfigHandler(const vector&parts, Utility::pid_t ppid); +string DLListZones(const vector&parts, Utility::pid_t ppid); +string DLTokenLogin(const vector&parts, Utility::pid_t ppid); +uint64_t udpErrorStats(const std::string& str); +#endif /* PDNS_DYNHANDLER_HH */ diff --git a/pdns/dynlistener.cc b/pdns/dynlistener.cc new file mode 100644 index 0000000..c3a1dc7 --- /dev/null +++ b/pdns/dynlistener.cc @@ -0,0 +1,415 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "misc.hh" +#include "dns.hh" +#include "arguments.hh" +#include "dnsbackend.hh" +#include "dynlistener.hh" +#include "dnspacket.hh" +#include "logger.hh" +#include "statbag.hh" +#include "threadname.hh" + +extern StatBag S; + +DynListener::g_funkdb_t DynListener::s_funcdb; +DynListener::g_funk_t* DynListener::s_restfunc; + +DynListener::~DynListener() +{ + if(!d_socketname.empty()) + unlink(d_socketname.c_str()); +} + +void DynListener::createSocketAndBind(int family, struct sockaddr*local, size_t len) +{ + d_s=socket(family, SOCK_STREAM,0); + setCloseOnExec(d_s); + + if(d_s < 0) { + if (family == AF_UNIX) + g_log<sun_path<<"', reason: "<toStringWithPort()<<"', reason: "<sun_path<<"', reason: "<toStringWithPort()<<"', reason: "<(-1),Utility::makeGidNumeric(arg()["setgid"]))<0) + g_log<(p); + us->theListener(); + g_log< mesg; + mesg.resize(1024000); + + ssize_t len; + + ComboAddress remote; + socklen_t remlen=remote.getSocklen(); + + if(d_nonlocal) { + for(;;) { + d_client=accept(d_s,(sockaddr*)&remote,&remlen); + if(d_client<0) { + if(errno!=EINTR) + g_log< fp=std::shared_ptr(fdopen(dup(d_client), "r"), fclose); + if(d_tcp) { + if(!fgets(&mesg[0], mesg.size(), fp.get())) { + g_log<(len) == mesg.size()) + throw PDNSException("Line on control console was too long"); + + mesg[len]=0; + } + + return &mesg[0]; +} + +void DynListener::sendlines(const string &l) +{ + if(d_nonlocal) { + unsigned int sent=0; + int ret; + while(sent < l.length()) { + ret=send(d_client, l.c_str()+sent, l.length()-sent, 0); + + if(ret<0 || !ret) { + g_log<parts; + stringtok(parts,line," "); + if(parts.empty()) { + sendlines("Empty line"); + continue; + } + + try { + parts[0] = toUpper( parts[0] ); + if(s_funcdb.count(parts[0])) + sendlines((*(s_funcdb[parts[0]].func))(parts,d_ppid)); + else if (parts[0] == "HELP") + sendlines(getHelp()); + else if(s_restfunc) + sendlines((*s_restfunc)(parts,d_ppid)); + else + sendlines("Unknown command: '"+parts[0]+"'"); + } + catch(PDNSException &AE) { + g_log< funcs; + string rest; + + // s_restfunc, when in guardian mode, is the function that + // can pass commands on to the guarded instance + // we just pass it HELP and merge it with our own list + if(s_restfunc) + { + vector parts; + parts.push_back("HELP"); + rest=((*s_restfunc)(parts,d_ppid)); + boost::split(funcs, rest, boost::is_any_of("\n")); + } + + const boost::format fmter("%|-32| %||"); + + for(g_funkdb_t::const_iterator i=s_funcdb.begin();i!=s_funcdb.end();++i) { + funcs.push_back(str(boost::format(fmter) % (toLower(i->first)+" "+i->second.args) % i->second.usage)); + } + sort(funcs.begin(), funcs.end()); + + // hack: this removes the duplicate quit method + funcs.resize(unique(funcs.begin(), funcs.end()) - funcs.begin()); + return boost::join(funcs, "\n"); +} diff --git a/pdns/dynlistener.hh b/pdns/dynlistener.hh new file mode 100644 index 0000000..62fc6fc --- /dev/null +++ b/pdns/dynlistener.hh @@ -0,0 +1,82 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_DYNLISTENER +#define PDNS_DYNLISTENER + +#include +#include +#include +#include +#include +#include +#include +#include "iputils.hh" +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" + +class DynListener : public boost::noncopyable +{ +public: + explicit DynListener(const string &pname=""); + explicit DynListener(const ComboAddress& addr); + ~DynListener(); + void go(); + void theListener(); + static void *theListenerHelper(void *p); + + typedef string g_funk_t(const vector &parts, Utility::pid_t ppid); // guido! + typedef struct { g_funk_t *func; string args; string usage; } g_funkwithusage_t; + typedef map g_funkdb_t; + + static void registerFunc(const string &name, g_funk_t *gf, const string &usage="", const string &args=""); + static void registerRestFunc(g_funk_t *gf); + static g_funk_t* getFunc(const string& fname) { return s_funcdb[fname].func; } +private: + void sendlines(const string &lines); + string getHelp(); + string getLine(); + + void listenOnUnixDomain(const std::string& fname); + void listenOnTCP(const ComboAddress&); + void createSocketAndBind(int family, struct sockaddr*local, size_t len); + + NetmaskGroup d_tcprange; + int d_s{-1}; + int d_client{-1}; + pthread_t d_tid{0}; + bool d_nonlocal; + bool d_tcp{false}; + pid_t d_ppid{0}; + + string d_socketname; + ComboAddress d_socketaddress; + static g_funkdb_t s_funcdb; + static g_funk_t* s_restfunc; + bool testLive(const string& fname); +}; +#endif /* PDNS_DYNLISTENER */ diff --git a/pdns/dynloader.cc b/pdns/dynloader.cc new file mode 100644 index 0000000..23bb80b --- /dev/null +++ b/pdns/dynloader.cc @@ -0,0 +1,186 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "pdnsexception.hh" +#include "misc.hh" +#include "dynmessenger.hh" +#include "arguments.hh" +#include "statbag.hh" +#include "misc.hh" +#include "namespaces.hh" +#include "namespaces.hh" + +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +} + +StatBag S; + +int main(int argc, char **argv) +{ + string s_programname="pdns"; + + ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR; + ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )=""; + ::arg().set("remote-address","Remote address to query"); + ::arg().set("remote-port","Remote port to query")="53000"; + ::arg().set("secret","Secret needed to connect to remote PowerDNS"); + + ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; + ::arg().setCmd("no-config","Don't parse configuration file"); + ::arg().set("chroot","")=""; + ::arg().setCmd("help","Provide a helpful message"); + ::arg().laxParse(argc,argv); + + if(::arg().mustDo("help")) { + cout<<"syntax:"<commands=::arg().getCommands(); + + if(commands.empty()) { + cerr<<"No command passed"< D; + if(::arg()["remote-address"].empty()) + D=shared_ptr(new DynMessenger(socketname)); + else { + uint16_t port; + try { + port = static_cast(pdns_stou(::arg()["remote-port"])); + } + catch(...) { + cerr<<"Unable to convert '"<<::arg()["remote-port"]<<"' to a port number for connecting to remote PowerDNS\n"; + exit(99); + } + + D=shared_ptr(new DynMessenger(ComboAddress(::arg()["remote-address"], port), ::arg()["secret"])); + } + + string message; + for(vector::const_iterator i=commands.begin();i!=commands.end();++i) { + if(i!=commands.begin()) + message+=" "; + message+=*i; + } + + if(command=="show") { + message="SHOW "; + for(unsigned int n=1;nsend(message)<0) { + cerr<<"Error sending command"<receive(); + if(resp.compare(0, 7, "Unknown") == 0) { + cerr< +#include "utility.hh" +#include +#include +#include +#include +#include +#include + +DynMessenger::DynMessenger(const string &fname, + int timeout_sec, + int timeout_usec) +{ + d_s=socket(AF_UNIX,SOCK_STREAM,0); + setCloseOnExec(d_s); + + if(d_s<0) { + throw PDNSException(string("socket")+strerror(errno)); + } + + try { + if(makeUNsockaddr(fname, &d_remote)) + throw PDNSException("Unable to connect to remote '"+fname+"': Path is not a valid UNIX socket path."); + + struct timeval timeout; + timeout.tv_sec = timeout_sec; + timeout.tv_usec = timeout_usec; + + if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror()); + + if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror()); + + int ret = Utility::timed_connect(d_s,(sockaddr*)&d_remote,sizeof(d_remote), timeout_sec, timeout_usec); + + if (ret == 0) + throw TimeoutException("Unable to connect to remote '"+fname+"': "+stringerror()); + else if (ret < 0) + throw PDNSException("Unable to connect to remote '"+fname+"': "+stringerror()); + + } catch(...) { + close(d_s); + d_s=-1; + throw; + } +} + +DynMessenger::DynMessenger(const ComboAddress& remote, + const string &secret, + int timeout_sec, + int timeout_usec) +{ + d_s=socket(AF_INET, SOCK_STREAM,0); + setCloseOnExec(d_s); + + if(d_s<0) { + throw PDNSException(string("socket")+strerror(errno)); + } + + try { + struct timeval timeout; + timeout.tv_sec = timeout_sec; + timeout.tv_usec = timeout_usec; + + if (setsockopt (d_s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + throw PDNSException("Unable to set SO_RCVTIMEO option on socket: " + stringerror()); + + if (setsockopt (d_s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + throw PDNSException("Unable to set SO_SNDTIMEO option on socket: " + stringerror()); + + int ret = Utility::timed_connect(d_s, (sockaddr*)&remote, remote.getSocklen(), timeout_sec, timeout_usec); + + if (ret == 0) + throw TimeoutException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno))); + else if (ret < 0) + throw PDNSException("Unable to connect to remote '"+remote.toStringWithPort()+"': "+string(strerror(errno))); + + string login=secret+"\n"; + writen2(d_s, login); + } catch(...) { + close(d_s); + d_s=-1; + throw; + } +} + +DynMessenger::~DynMessenger() +{ + if (d_s > 0) + close(d_s); +} + +int DynMessenger::send(const string &msg) const +{ + try { + writen2(d_s, msg+"\n"); + return 0; + } catch(std::runtime_error& e) { + if (errno == EAGAIN) + throw TimeoutException("Error from remote in send(): " + string(e.what())); + else + throw PDNSException("Error from remote in send(): " + string(e.what())); + } +} + +string DynMessenger::receive() const +{ + char buffer[1500]; + + int retlen; + string answer; + for(;;) { + retlen=recv(d_s,buffer,sizeof(buffer),0); + if(retlen<0) { + if (errno == EAGAIN) + throw TimeoutException("Error from remote in receive(): " + string(strerror(errno))); + else + throw PDNSException("Error from remote in receive(): " + string(strerror(errno))); + } + + answer.append(buffer,retlen); + if (retlen == 0) + break; + } + + return answer; +} + diff --git a/pdns/dynmessenger.hh b/pdns/dynmessenger.hh new file mode 100644 index 0000000..c9e60d5 --- /dev/null +++ b/pdns/dynmessenger.hh @@ -0,0 +1,66 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef DYNMESSENGER_HH +#define DYNMESSENGER_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include "iputils.hh" +#include "pdnsexception.hh" + +#include "namespaces.hh" + +//! The DynMessenger can send messages to UNIX domain sockets and TCP sockets +class DynMessenger +{ + int d_s; + + struct sockaddr_un d_remote; // our remote address + + DynMessenger(const DynMessenger &); // NOT IMPLEMENTED + +public: + // CREATORS + + DynMessenger(const string &filename, + int timeout_sec = 7, + int timeout_usec = 0); //!< Create a DynMessenger sending to this file + + DynMessenger(const ComboAddress& remote, + const string &password, + int timeout_sec = 7, + int timeout_usec = 0); //!< Create a DynMessenger sending to this file + + ~DynMessenger(); + + // ACCESSORS + int send(const string &message) const; //!< Send a message to a DynListener + string receive() const; //!< receive an answer from a DynListener +}; + +#endif diff --git a/pdns/ednscookies.cc b/pdns/ednscookies.cc new file mode 100644 index 0000000..5e20819 --- /dev/null +++ b/pdns/ednscookies.cc @@ -0,0 +1,51 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "ednscookies.hh" + +bool getEDNSCookiesOptFromString(const string& option, EDNSCookiesOpt* eco) +{ + return getEDNSCookiesOptFromString(option.c_str(), option.length(), eco); +} + +bool getEDNSCookiesOptFromString(const char* option, unsigned int len, EDNSCookiesOpt* eco) +{ + if(len != 8 && len < 16) + return false; + eco->client = string(option, 8); + if (len > 8) { + eco->server = string(option + 8, len - 8); + } + return true; +} + +string makeEDNSCookiesOptString(const EDNSCookiesOpt& eco) +{ + string ret; + if (eco.client.length() != 8) + return ret; + if (eco.server.length() != 0 && (eco.server.length() < 8 || eco.server.length() > 32)) + return ret; + ret.assign(eco.client); + if (eco.server.length() != 0) + ret.append(eco.server); + return ret; +} diff --git a/pdns/ednscookies.hh b/pdns/ednscookies.hh new file mode 100644 index 0000000..7dce62b --- /dev/null +++ b/pdns/ednscookies.hh @@ -0,0 +1,36 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_EDNSCOOKIES_HH +#define PDNS_EDNSCOOKIES_HH + +#include "namespaces.hh" + +struct EDNSCookiesOpt +{ + string client; + string server; +}; + +bool getEDNSCookiesOptFromString(const char* option, unsigned int len, EDNSCookiesOpt* eco); +bool getEDNSCookiesOptFromString(const string& option, EDNSCookiesOpt* eco); +string makeEDNSCookiesOptString(const EDNSCookiesOpt& eco); +#endif diff --git a/pdns/ednsoptions.cc b/pdns/ednsoptions.cc new file mode 100644 index 0000000..6b4ec10 --- /dev/null +++ b/pdns/ednsoptions.cc @@ -0,0 +1,115 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "dns.hh" +#include "ednsoptions.hh" +#include "iputils.hh" + +/* extract a specific EDNS0 option from a pointer on the beginning rdLen of the OPT RR */ +int getEDNSOption(char* optRR, const size_t len, uint16_t wantedOption, char ** optionValue, size_t * optionValueSize) +{ + assert(optRR != NULL); + assert(optionValue != NULL); + assert(optionValueSize != NULL); + size_t pos = 0; + if (len < DNS_RDLENGTH_SIZE) + return EINVAL; + + const uint16_t rdLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + size_t rdPos = 0; + pos += DNS_RDLENGTH_SIZE; + if ((pos + rdLen) > len) { + return EINVAL; + } + + while(len >= (pos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE) && + rdLen >= (rdPos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) { + const uint16_t optionCode = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + pos += EDNS_OPTION_CODE_SIZE; + rdPos += EDNS_OPTION_CODE_SIZE; + const uint16_t optionLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + pos += EDNS_OPTION_LENGTH_SIZE; + rdPos += EDNS_OPTION_LENGTH_SIZE; + if (optionLen > (rdLen - rdPos) || optionLen > (len - pos)) + return EINVAL; + + if (optionCode == wantedOption) { + *optionValue = optRR + pos - (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE); + *optionValueSize = optionLen + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE; + return 0; + } + else { + /* skip this option */ + pos += optionLen; + rdPos += optionLen; + } + } + + return ENOENT; +} + +/* extract all EDNS0 options from a pointer on the beginning rdLen of the OPT RR */ +int getEDNSOptions(const char* optRR, const size_t len, EDNSOptionViewMap& options) +{ + assert(optRR != NULL); + size_t pos = 0; + if (len < DNS_RDLENGTH_SIZE) + return EINVAL; + + const uint16_t rdLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + size_t rdPos = 0; + pos += DNS_RDLENGTH_SIZE; + if ((pos + rdLen) > len) { + return EINVAL; + } + + while(len >= (pos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE) && + rdLen >= (rdPos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) { + const uint16_t optionCode = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + pos += EDNS_OPTION_CODE_SIZE; + rdPos += EDNS_OPTION_CODE_SIZE; + const uint16_t optionLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]); + pos += EDNS_OPTION_LENGTH_SIZE; + rdPos += EDNS_OPTION_LENGTH_SIZE; + if (optionLen > (rdLen - rdPos) || optionLen > (len - pos)) + return EINVAL; + + EDNSOptionViewValue value; + value.content = optRR + pos; + value.size = optionLen; + options[optionCode].values.push_back(std::move(value)); + + /* skip this option */ + pos += optionLen; + rdPos += optionLen; + } + + return 0; +} + +void generateEDNSOption(uint16_t optionCode, const std::string& payload, std::string& res) +{ + const uint16_t ednsOptionCode = htons(optionCode); + const uint16_t payloadLen = htons(payload.length()); + res.append((const char *) &ednsOptionCode, sizeof ednsOptionCode); + res.append((const char *) &payloadLen, sizeof payloadLen); + res.append(payload); +} diff --git a/pdns/ednsoptions.hh b/pdns/ednsoptions.hh new file mode 100644 index 0000000..019ac9b --- /dev/null +++ b/pdns/ednsoptions.hh @@ -0,0 +1,53 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_EDNSOPTIONS_HH +#define PDNS_EDNSOPTIONS_HH + +#include "namespaces.hh" + +struct EDNSOptionCode +{ + enum EDNSOptionCodeEnum {NSID=3, DAU=5, DHU=6, N3U=7, ECS=8, EXPIRE=9, COOKIE=10, TCPKEEPALIVE=11, PADDING=12, CHAIN=13, KEYTAG=14}; +}; + +/* extract a specific EDNS0 option from a pointer on the beginning rdLen of the OPT RR */ +int getEDNSOption(char* optRR, size_t len, uint16_t wantedOption, char ** optionValue, size_t * optionValueSize); + +struct EDNSOptionViewValue +{ + const char* content{nullptr}; + uint16_t size{0}; +}; + +struct EDNSOptionView +{ + std::vector values; +}; + +typedef std::map EDNSOptionViewMap; + +/* extract all EDNS0 options from a pointer on the beginning rdLen of the OPT RR */ +int getEDNSOptions(const char* optRR, size_t len, EDNSOptionViewMap& options); + +void generateEDNSOption(uint16_t optionCode, const std::string& payload, std::string& res); + +#endif diff --git a/pdns/ednssubnet.cc b/pdns/ednssubnet.cc new file mode 100644 index 0000000..cf78ecf --- /dev/null +++ b/pdns/ednssubnet.cc @@ -0,0 +1,108 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "ednssubnet.hh" +#include "dns.hh" + +namespace { + struct EDNSSubnetOptsWire + { + uint16_t family; + uint8_t sourceMask; + uint8_t scopeMask; + } GCCPACKATTRIBUTE; // BRRRRR + +} + +bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso) +{ + //cerr<<"options.size:"< 0 ? (((esow.sourceMask - 1)>> 3)+1) : 0; + //cerr<<"octetsin:"< sizeof(address.sin4.sin_addr.s_addr)) + return false; + address.reset(); + address.sin4.sin_family = AF_INET; + if(octetsin > 0) + memcpy(&address.sin4.sin_addr.s_addr, options+sizeof(esow), octetsin); + } else if(esow.family == 2) { + if(len != sizeof(esow)+octetsin) + return false; + if(octetsin > sizeof(address.sin6.sin6_addr.s6_addr)) + return false; + + address.reset(); + address.sin4.sin_family = AF_INET6; + if(octetsin > 0) + memcpy(&address.sin6.sin6_addr.s6_addr, options+sizeof(esow), octetsin); + } + else + return false; + //cerr<<"Source address: "<source = Netmask(address, esow.sourceMask); + /* 'address' has more bits set (potentially) than scopeMask. This leads to odd looking netmasks that promise + more precision than they have. For this reason we truncate the address to scopeMask bits */ + + address.truncate(esow.scopeMask); // truncate will not throw for odd scopeMasks + eso->scope = Netmask(address, esow.scopeMask); + + return true; +} + +string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso) +{ + string ret; + EDNSSubnetOptsWire esow; + uint16_t family = htons(eso.source.getNetwork().sin4.sin_family == AF_INET ? 1 : 2); + esow.family = family; + esow.sourceMask = eso.source.getBits(); + esow.scopeMask = eso.scope.getBits(); + ret.assign((const char*)&esow, sizeof(esow)); + int octetsout = ((esow.sourceMask - 1)>> 3)+1; + + ComboAddress src=eso.source.getNetwork(); + src.truncate(esow.sourceMask); + + if(family == htons(1)) + ret.append((const char*) &src.sin4.sin_addr.s_addr, octetsout); + else + ret.append((const char*) &src.sin6.sin6_addr.s6_addr, octetsout); + return ret; +} + diff --git a/pdns/ednssubnet.hh b/pdns/ednssubnet.hh new file mode 100644 index 0000000..eb87b48 --- /dev/null +++ b/pdns/ednssubnet.hh @@ -0,0 +1,38 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_EDNSSUBNET_HH +#define PDNS_EDNSSUBNET_HH + +#include "namespaces.hh" +#include "iputils.hh" +#include "dnsname.hh" + +struct EDNSSubnetOpts +{ + Netmask source; + Netmask scope; +}; + +bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso); +bool getEDNSSubnetOptsFromString(const char* options, unsigned int len, EDNSSubnetOpts* eso); +string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso); +#endif diff --git a/pdns/effective_tld_names.dat b/pdns/effective_tld_names.dat new file mode 100644 index 0000000..1ded69b --- /dev/null +++ b/pdns/effective_tld_names.dat @@ -0,0 +1,12987 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, +// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. + +// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. + +// ===BEGIN ICANN DOMAINS=== + +// ac : https://en.wikipedia.org/wiki/.ac +ac +com.ac +edu.ac +gov.ac +net.ac +mil.ac +org.ac + +// ad : https://en.wikipedia.org/wiki/.ad +ad +nom.ad + +// ae : https://en.wikipedia.org/wiki/.ae +// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php +ae +co.ae +net.ae +org.ae +sch.ae +ac.ae +gov.ae +mil.ae + +// aero : see https://www.information.aero/index.php?id=66 +aero +accident-investigation.aero +accident-prevention.aero +aerobatic.aero +aeroclub.aero +aerodrome.aero +agents.aero +aircraft.aero +airline.aero +airport.aero +air-surveillance.aero +airtraffic.aero +air-traffic-control.aero +ambulance.aero +amusement.aero +association.aero +author.aero +ballooning.aero +broker.aero +caa.aero +cargo.aero +catering.aero +certification.aero +championship.aero +charter.aero +civilaviation.aero +club.aero +conference.aero +consultant.aero +consulting.aero +control.aero +council.aero +crew.aero +design.aero +dgca.aero +educator.aero +emergency.aero +engine.aero +engineer.aero +entertainment.aero +equipment.aero +exchange.aero +express.aero +federation.aero +flight.aero +freight.aero +fuel.aero +gliding.aero +government.aero +groundhandling.aero +group.aero +hanggliding.aero +homebuilt.aero +insurance.aero +journal.aero +journalist.aero +leasing.aero +logistics.aero +magazine.aero +maintenance.aero +media.aero +microlight.aero +modelling.aero +navigation.aero +parachuting.aero +paragliding.aero +passenger-association.aero +pilot.aero +press.aero +production.aero +recreation.aero +repbody.aero +res.aero +research.aero +rotorcraft.aero +safety.aero +scientist.aero +services.aero +show.aero +skydiving.aero +software.aero +student.aero +trader.aero +trading.aero +trainer.aero +union.aero +workinggroup.aero +works.aero + +// af : http://www.nic.af/help.jsp +af +gov.af +com.af +org.af +net.af +edu.af + +// ag : http://www.nic.ag/prices.htm +ag +com.ag +org.ag +net.ag +co.ag +nom.ag + +// ai : http://nic.com.ai/ +ai +off.ai +com.ai +net.ai +org.ai + +// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 +al +com.al +edu.al +gov.al +mil.al +net.al +org.al + +// am : https://www.amnic.net/policy/en/Policy_EN.pdf +am +co.am +com.am +commune.am +net.am +org.am + +// ao : https://en.wikipedia.org/wiki/.ao +// http://www.dns.ao/REGISTR.DOC +ao +ed.ao +gv.ao +og.ao +co.ao +pb.ao +it.ao + +// aq : https://en.wikipedia.org/wiki/.aq +aq + +// ar : https://nic.ar/nic-argentina/normativa-vigente +ar +com.ar +edu.ar +gob.ar +gov.ar +int.ar +mil.ar +musica.ar +net.ar +org.ar +tur.ar + +// arpa : https://en.wikipedia.org/wiki/.arpa +// Confirmed by registry 2008-06-18 +arpa +e164.arpa +in-addr.arpa +ip6.arpa +iris.arpa +uri.arpa +urn.arpa + +// as : https://en.wikipedia.org/wiki/.as +as +gov.as + +// asia : https://en.wikipedia.org/wiki/.asia +asia + +// at : https://en.wikipedia.org/wiki/.at +// Confirmed by registry 2008-06-17 +at +ac.at +co.at +gv.at +or.at + +// au : https://en.wikipedia.org/wiki/.au +// http://www.auda.org.au/ +au +// 2LDs +com.au +net.au +org.au +edu.au +gov.au +asn.au +id.au +// Historic 2LDs (closed to new registration, but sites still exist) +info.au +conf.au +oz.au +// CGDNs - http://www.cgdn.org.au/ +act.au +nsw.au +nt.au +qld.au +sa.au +tas.au +vic.au +wa.au +// 3LDs +act.edu.au +catholic.edu.au +eq.edu.au +nsw.edu.au +nt.edu.au +qld.edu.au +sa.edu.au +tas.edu.au +vic.edu.au +wa.edu.au +// act.gov.au Bug 984824 - Removed at request of Greg Tankard +// nsw.gov.au Bug 547985 - Removed at request of +// nt.gov.au Bug 940478 - Removed at request of Greg Connors +qld.gov.au +sa.gov.au +tas.gov.au +vic.gov.au +wa.gov.au +// 4LDs +education.tas.edu.au +schools.nsw.edu.au + +// aw : https://en.wikipedia.org/wiki/.aw +aw +com.aw + +// ax : https://en.wikipedia.org/wiki/.ax +ax + +// az : https://en.wikipedia.org/wiki/.az +az +com.az +net.az +int.az +gov.az +org.az +edu.az +info.az +pp.az +mil.az +name.az +pro.az +biz.az + +// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf +ba +com.ba +edu.ba +gov.ba +mil.ba +net.ba +org.ba + +// bb : https://en.wikipedia.org/wiki/.bb +bb +biz.bb +co.bb +com.bb +edu.bb +gov.bb +info.bb +net.bb +org.bb +store.bb +tv.bb + +// bd : https://en.wikipedia.org/wiki/.bd +*.bd + +// be : https://en.wikipedia.org/wiki/.be +// Confirmed by registry 2008-06-08 +be +ac.be + +// bf : https://en.wikipedia.org/wiki/.bf +bf +gov.bf + +// bg : https://en.wikipedia.org/wiki/.bg +// https://www.register.bg/user/static/rules/en/index.html +bg +a.bg +b.bg +c.bg +d.bg +e.bg +f.bg +g.bg +h.bg +i.bg +j.bg +k.bg +l.bg +m.bg +n.bg +o.bg +p.bg +q.bg +r.bg +s.bg +t.bg +u.bg +v.bg +w.bg +x.bg +y.bg +z.bg +0.bg +1.bg +2.bg +3.bg +4.bg +5.bg +6.bg +7.bg +8.bg +9.bg + +// bh : https://en.wikipedia.org/wiki/.bh +bh +com.bh +edu.bh +net.bh +org.bh +gov.bh + +// bi : https://en.wikipedia.org/wiki/.bi +// http://whois.nic.bi/ +bi +co.bi +com.bi +edu.bi +or.bi +org.bi + +// biz : https://en.wikipedia.org/wiki/.biz +biz + +// bj : https://en.wikipedia.org/wiki/.bj +bj +asso.bj +barreau.bj +gouv.bj + +// bm : http://www.bermudanic.bm/dnr-text.txt +bm +com.bm +edu.bm +gov.bm +net.bm +org.bm + +// bn : http://www.bnnic.bn/faqs +bn +com.bn +edu.bn +gov.bn +net.bn +org.bn + +// bo : https://nic.bo/delegacion2015.php#h-1.10 +bo +com.bo +edu.bo +gob.bo +int.bo +org.bo +net.bo +mil.bo +tv.bo +web.bo +// Social Domains +academia.bo +agro.bo +arte.bo +blog.bo +bolivia.bo +ciencia.bo +cooperativa.bo +democracia.bo +deporte.bo +ecologia.bo +economia.bo +empresa.bo +indigena.bo +industria.bo +info.bo +medicina.bo +movimiento.bo +musica.bo +natural.bo +nombre.bo +noticias.bo +patria.bo +politica.bo +profesional.bo +plurinacional.bo +pueblo.bo +revista.bo +salud.bo +tecnologia.bo +tksat.bo +transporte.bo +wiki.bo + +// br : http://registro.br/dominio/categoria.html +// Submitted by registry +br +9guacu.br +abc.br +adm.br +adv.br +agr.br +aju.br +am.br +anani.br +aparecida.br +arq.br +art.br +ato.br +b.br +barueri.br +belem.br +bhz.br +bio.br +blog.br +bmd.br +boavista.br +bsb.br +campinagrande.br +campinas.br +caxias.br +cim.br +cng.br +cnt.br +com.br +contagem.br +coop.br +cri.br +cuiaba.br +curitiba.br +def.br +ecn.br +eco.br +edu.br +emp.br +eng.br +esp.br +etc.br +eti.br +far.br +feira.br +flog.br +floripa.br +fm.br +fnd.br +fortal.br +fot.br +foz.br +fst.br +g12.br +ggf.br +goiania.br +gov.br +// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil +ac.gov.br +al.gov.br +am.gov.br +ap.gov.br +ba.gov.br +ce.gov.br +df.gov.br +es.gov.br +go.gov.br +ma.gov.br +mg.gov.br +ms.gov.br +mt.gov.br +pa.gov.br +pb.gov.br +pe.gov.br +pi.gov.br +pr.gov.br +rj.gov.br +rn.gov.br +ro.gov.br +rr.gov.br +rs.gov.br +sc.gov.br +se.gov.br +sp.gov.br +to.gov.br +gru.br +imb.br +ind.br +inf.br +jab.br +jampa.br +jdf.br +joinville.br +jor.br +jus.br +leg.br +lel.br +londrina.br +macapa.br +maceio.br +manaus.br +maringa.br +mat.br +med.br +mil.br +morena.br +mp.br +mus.br +natal.br +net.br +niteroi.br +*.nom.br +not.br +ntr.br +odo.br +ong.br +org.br +osasco.br +palmas.br +poa.br +ppg.br +pro.br +psc.br +psi.br +pvh.br +qsl.br +radio.br +rec.br +recife.br +ribeirao.br +rio.br +riobranco.br +riopreto.br +salvador.br +sampa.br +santamaria.br +santoandre.br +saobernardo.br +saogonca.br +sjc.br +slg.br +slz.br +sorocaba.br +srv.br +taxi.br +tc.br +teo.br +the.br +tmp.br +trd.br +tur.br +tv.br +udi.br +vet.br +vix.br +vlog.br +wiki.br +zlg.br + +// bs : http://www.nic.bs/rules.html +bs +com.bs +net.bs +org.bs +edu.bs +gov.bs + +// bt : https://en.wikipedia.org/wiki/.bt +bt +com.bt +edu.bt +gov.bt +net.bt +org.bt + +// bv : No registrations at this time. +// Submitted by registry +bv + +// bw : https://en.wikipedia.org/wiki/.bw +// http://www.gobin.info/domainname/bw.doc +// list of other 2nd level tlds ? +bw +co.bw +org.bw + +// by : https://en.wikipedia.org/wiki/.by +// http://tld.by/rules_2006_en.html +// list of other 2nd level tlds ? +by +gov.by +mil.by +// Official information does not indicate that com.by is a reserved +// second-level domain, but it's being used as one (see www.google.com.by and +// www.yahoo.com.by, for example), so we list it here for safety's sake. +com.by + +// http://hoster.by/ +of.by + +// bz : https://en.wikipedia.org/wiki/.bz +// http://www.belizenic.bz/ +bz +com.bz +net.bz +org.bz +edu.bz +gov.bz + +// ca : https://en.wikipedia.org/wiki/.ca +ca +// ca geographical names +ab.ca +bc.ca +mb.ca +nb.ca +nf.ca +nl.ca +ns.ca +nt.ca +nu.ca +on.ca +pe.ca +qc.ca +sk.ca +yk.ca +// gc.ca: https://en.wikipedia.org/wiki/.gc.ca +// see also: http://registry.gc.ca/en/SubdomainFAQ +gc.ca + +// cat : https://en.wikipedia.org/wiki/.cat +cat + +// cc : https://en.wikipedia.org/wiki/.cc +cc + +// cd : https://en.wikipedia.org/wiki/.cd +// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 +cd +gov.cd + +// cf : https://en.wikipedia.org/wiki/.cf +cf + +// cg : https://en.wikipedia.org/wiki/.cg +cg + +// ch : https://en.wikipedia.org/wiki/.ch +ch + +// ci : https://en.wikipedia.org/wiki/.ci +// http://www.nic.ci/index.php?page=charte +ci +org.ci +or.ci +com.ci +co.ci +edu.ci +ed.ci +ac.ci +net.ci +go.ci +asso.ci +aéroport.ci +int.ci +presse.ci +md.ci +gouv.ci + +// ck : https://en.wikipedia.org/wiki/.ck +*.ck +!www.ck + +// cl : https://en.wikipedia.org/wiki/.cl +cl +gov.cl +gob.cl +co.cl +mil.cl + +// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 +cm +co.cm +com.cm +gov.cm +net.cm + +// cn : https://en.wikipedia.org/wiki/.cn +// Submitted by registry +cn +ac.cn +com.cn +edu.cn +gov.cn +net.cn +org.cn +mil.cn +公司.cn +网络.cn +網絡.cn +// cn geographic names +ah.cn +bj.cn +cq.cn +fj.cn +gd.cn +gs.cn +gz.cn +gx.cn +ha.cn +hb.cn +he.cn +hi.cn +hl.cn +hn.cn +jl.cn +js.cn +jx.cn +ln.cn +nm.cn +nx.cn +qh.cn +sc.cn +sd.cn +sh.cn +sn.cn +sx.cn +tj.cn +xj.cn +xz.cn +yn.cn +zj.cn +hk.cn +mo.cn +tw.cn + +// co : https://en.wikipedia.org/wiki/.co +// Submitted by registry +co +arts.co +com.co +edu.co +firm.co +gov.co +info.co +int.co +mil.co +net.co +nom.co +org.co +rec.co +web.co + +// com : https://en.wikipedia.org/wiki/.com +com + +// coop : https://en.wikipedia.org/wiki/.coop +coop + +// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do +cr +ac.cr +co.cr +ed.cr +fi.cr +go.cr +or.cr +sa.cr + +// cu : https://en.wikipedia.org/wiki/.cu +cu +com.cu +edu.cu +org.cu +net.cu +gov.cu +inf.cu + +// cv : https://en.wikipedia.org/wiki/.cv +cv + +// cw : http://www.una.cw/cw_registry/ +// Confirmed by registry 2013-03-26 +cw +com.cw +edu.cw +net.cw +org.cw + +// cx : https://en.wikipedia.org/wiki/.cx +// list of other 2nd level tlds ? +cx +gov.cx + +// cy : http://www.nic.cy/ +// Submitted by registry Panayiotou Fotia +cy +ac.cy +biz.cy +com.cy +ekloges.cy +gov.cy +ltd.cy +name.cy +net.cy +org.cy +parliament.cy +press.cy +pro.cy +tm.cy + +// cz : https://en.wikipedia.org/wiki/.cz +cz + +// de : https://en.wikipedia.org/wiki/.de +// Confirmed by registry (with technical +// reservations) 2008-07-01 +de + +// dj : https://en.wikipedia.org/wiki/.dj +dj + +// dk : https://en.wikipedia.org/wiki/.dk +// Confirmed by registry 2008-06-17 +dk + +// dm : https://en.wikipedia.org/wiki/.dm +dm +com.dm +net.dm +org.dm +edu.dm +gov.dm + +// do : https://en.wikipedia.org/wiki/.do +do +art.do +com.do +edu.do +gob.do +gov.do +mil.do +net.do +org.do +sld.do +web.do + +// dz : https://en.wikipedia.org/wiki/.dz +dz +com.dz +org.dz +net.dz +gov.dz +edu.dz +asso.dz +pol.dz +art.dz + +// ec : http://www.nic.ec/reg/paso1.asp +// Submitted by registry +ec +com.ec +info.ec +net.ec +fin.ec +k12.ec +med.ec +pro.ec +org.ec +edu.ec +gov.ec +gob.ec +mil.ec + +// edu : https://en.wikipedia.org/wiki/.edu +edu + +// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B +ee +edu.ee +gov.ee +riik.ee +lib.ee +med.ee +com.ee +pri.ee +aip.ee +org.ee +fie.ee + +// eg : https://en.wikipedia.org/wiki/.eg +eg +com.eg +edu.eg +eun.eg +gov.eg +mil.eg +name.eg +net.eg +org.eg +sci.eg + +// er : https://en.wikipedia.org/wiki/.er +*.er + +// es : https://www.nic.es/site_ingles/ingles/dominios/index.html +es +com.es +nom.es +org.es +gob.es +edu.es + +// et : https://en.wikipedia.org/wiki/.et +et +com.et +gov.et +org.et +edu.et +biz.et +name.et +info.et +net.et + +// eu : https://en.wikipedia.org/wiki/.eu +eu + +// fi : https://en.wikipedia.org/wiki/.fi +fi +// aland.fi : https://en.wikipedia.org/wiki/.ax +// This domain is being phased out in favor of .ax. As there are still many +// domains under aland.fi, we still keep it on the list until aland.fi is +// completely removed. +// TODO: Check for updates (expected to be phased out around Q1/2009) +aland.fi + +// fj : https://en.wikipedia.org/wiki/.fj +*.fj + +// fk : https://en.wikipedia.org/wiki/.fk +*.fk + +// fm : https://en.wikipedia.org/wiki/.fm +fm + +// fo : https://en.wikipedia.org/wiki/.fo +fo + +// fr : http://www.afnic.fr/ +// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf +fr +asso.fr +com.fr +gouv.fr +nom.fr +prd.fr +tm.fr +// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html +aeroport.fr +avocat.fr +avoues.fr +cci.fr +chambagri.fr +chirurgiens-dentistes.fr +experts-comptables.fr +geometre-expert.fr +greta.fr +huissier-justice.fr +medecin.fr +notaires.fr +pharmacien.fr +port.fr +veterinaire.fr + +// ga : https://en.wikipedia.org/wiki/.ga +ga + +// gb : This registry is effectively dormant +// Submitted by registry +gb + +// gd : https://en.wikipedia.org/wiki/.gd +gd + +// ge : http://www.nic.net.ge/policy_en.pdf +ge +com.ge +edu.ge +gov.ge +org.ge +mil.ge +net.ge +pvt.ge + +// gf : https://en.wikipedia.org/wiki/.gf +gf + +// gg : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +gg +co.gg +net.gg +org.gg + +// gh : https://en.wikipedia.org/wiki/.gh +// see also: http://www.nic.gh/reg_now.php +// Although domains directly at second level are not possible at the moment, +// they have been possible for some time and may come back. +gh +com.gh +edu.gh +gov.gh +org.gh +mil.gh + +// gi : http://www.nic.gi/rules.html +gi +com.gi +ltd.gi +gov.gi +mod.gi +edu.gi +org.gi + +// gl : https://en.wikipedia.org/wiki/.gl +// http://nic.gl +gl +co.gl +com.gl +edu.gl +net.gl +org.gl + +// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm +gm + +// gn : http://psg.com/dns/gn/gn.txt +// Submitted by registry +gn +ac.gn +com.gn +edu.gn +gov.gn +org.gn +net.gn + +// gov : https://en.wikipedia.org/wiki/.gov +gov + +// gp : http://www.nic.gp/index.php?lang=en +gp +com.gp +net.gp +mobi.gp +edu.gp +org.gp +asso.gp + +// gq : https://en.wikipedia.org/wiki/.gq +gq + +// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// Submitted by registry +gr +com.gr +edu.gr +net.gr +org.gr +gov.gr + +// gs : https://en.wikipedia.org/wiki/.gs +gs + +// gt : http://www.gt/politicas_de_registro.html +gt +com.gt +edu.gt +gob.gt +ind.gt +mil.gt +net.gt +org.gt + +// gu : http://gadao.gov.gu/register.html +// University of Guam : https://www.uog.edu +// Submitted by uognoc@triton.uog.edu +gu +com.gu +edu.gu +gov.gu +guam.gu +info.gu +net.gu +org.gu +web.gu + +// gw : https://en.wikipedia.org/wiki/.gw +gw + +// gy : https://en.wikipedia.org/wiki/.gy +// http://registry.gy/ +gy +co.gy +com.gy +edu.gy +gov.gy +net.gy +org.gy + +// hk : https://www.hkirc.hk +// Submitted by registry +hk +com.hk +edu.hk +gov.hk +idv.hk +net.hk +org.hk +公司.hk +教育.hk +敎育.hk +政府.hk +個人.hk +个人.hk +箇人.hk +網络.hk +网络.hk +组織.hk +網絡.hk +网絡.hk +组织.hk +組織.hk +組织.hk + +// hm : https://en.wikipedia.org/wiki/.hm +hm + +// hn : http://www.nic.hn/politicas/ps02,,05.html +hn +com.hn +edu.hn +org.hn +net.hn +mil.hn +gob.hn + +// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf +hr +iz.hr +from.hr +name.hr +com.hr + +// ht : http://www.nic.ht/info/charte.cfm +ht +com.ht +shop.ht +firm.ht +info.ht +adult.ht +net.ht +pro.ht +org.ht +med.ht +art.ht +coop.ht +pol.ht +asso.ht +edu.ht +rel.ht +gouv.ht +perso.ht + +// hu : http://www.domain.hu/domain/English/sld.html +// Confirmed by registry 2008-06-12 +hu +co.hu +info.hu +org.hu +priv.hu +sport.hu +tm.hu +2000.hu +agrar.hu +bolt.hu +casino.hu +city.hu +erotica.hu +erotika.hu +film.hu +forum.hu +games.hu +hotel.hu +ingatlan.hu +jogasz.hu +konyvelo.hu +lakas.hu +media.hu +news.hu +reklam.hu +sex.hu +shop.hu +suli.hu +szex.hu +tozsde.hu +utazas.hu +video.hu + +// id : https://pandi.id/en/domain/registration-requirements/ +id +ac.id +biz.id +co.id +desa.id +go.id +mil.id +my.id +net.id +or.id +ponpes.id +sch.id +web.id + +// ie : https://en.wikipedia.org/wiki/.ie +ie +gov.ie + +// il : http://www.isoc.org.il/domains/ +il +ac.il +co.il +gov.il +idf.il +k12.il +muni.il +net.il +org.il + +// im : https://www.nic.im/ +// Submitted by registry +im +ac.im +co.im +com.im +ltd.co.im +net.im +org.im +plc.co.im +tt.im +tv.im + +// in : https://en.wikipedia.org/wiki/.in +// see also: https://registry.in/Policies +// Please note, that nic.in is not an official eTLD, but used by most +// government institutions. +in +co.in +firm.in +net.in +org.in +gen.in +ind.in +nic.in +ac.in +edu.in +res.in +gov.in +mil.in + +// info : https://en.wikipedia.org/wiki/.info +info + +// int : https://en.wikipedia.org/wiki/.int +// Confirmed by registry 2008-06-18 +int +eu.int + +// io : http://www.nic.io/rules.html +// list of other 2nd level tlds ? +io +com.io + +// iq : http://www.cmc.iq/english/iq/iqregister1.htm +iq +gov.iq +edu.iq +mil.iq +com.iq +org.iq +net.iq + +// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules +// Also see http://www.nic.ir/Internationalized_Domain_Names +// Two .ir entries added at request of , 2010-04-16 +ir +ac.ir +co.ir +gov.ir +id.ir +net.ir +org.ir +sch.ir +// xn--mgba3a4f16a.ir (.ir, Persian YEH) +ایران.ir +// xn--mgba3a4fra.ir (.ir, Arabic YEH) +ايران.ir + +// is : http://www.isnic.is/domain/rules.php +// Confirmed by registry 2008-12-06 +is +net.is +com.is +edu.is +gov.is +org.is +int.is + +// it : https://en.wikipedia.org/wiki/.it +it +gov.it +edu.it +// Reserved geo-names (regions and provinces): +// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf +// Regions +abr.it +abruzzo.it +aosta-valley.it +aostavalley.it +bas.it +basilicata.it +cal.it +calabria.it +cam.it +campania.it +emilia-romagna.it +emiliaromagna.it +emr.it +friuli-v-giulia.it +friuli-ve-giulia.it +friuli-vegiulia.it +friuli-venezia-giulia.it +friuli-veneziagiulia.it +friuli-vgiulia.it +friuliv-giulia.it +friulive-giulia.it +friulivegiulia.it +friulivenezia-giulia.it +friuliveneziagiulia.it +friulivgiulia.it +fvg.it +laz.it +lazio.it +lig.it +liguria.it +lom.it +lombardia.it +lombardy.it +lucania.it +mar.it +marche.it +mol.it +molise.it +piedmont.it +piemonte.it +pmn.it +pug.it +puglia.it +sar.it +sardegna.it +sardinia.it +sic.it +sicilia.it +sicily.it +taa.it +tos.it +toscana.it +trentin-sud-tirol.it +trentin-süd-tirol.it +trentin-sudtirol.it +trentin-südtirol.it +trentin-sued-tirol.it +trentin-suedtirol.it +trentino-a-adige.it +trentino-aadige.it +trentino-alto-adige.it +trentino-altoadige.it +trentino-s-tirol.it +trentino-stirol.it +trentino-sud-tirol.it +trentino-süd-tirol.it +trentino-sudtirol.it +trentino-südtirol.it +trentino-sued-tirol.it +trentino-suedtirol.it +trentino.it +trentinoa-adige.it +trentinoaadige.it +trentinoalto-adige.it +trentinoaltoadige.it +trentinos-tirol.it +trentinostirol.it +trentinosud-tirol.it +trentinosüd-tirol.it +trentinosudtirol.it +trentinosüdtirol.it +trentinosued-tirol.it +trentinosuedtirol.it +trentinsud-tirol.it +trentinsüd-tirol.it +trentinsudtirol.it +trentinsüdtirol.it +trentinsued-tirol.it +trentinsuedtirol.it +tuscany.it +umb.it +umbria.it +val-d-aosta.it +val-daosta.it +vald-aosta.it +valdaosta.it +valle-aosta.it +valle-d-aosta.it +valle-daosta.it +valleaosta.it +valled-aosta.it +valledaosta.it +vallee-aoste.it +vallée-aoste.it +vallee-d-aoste.it +vallée-d-aoste.it +valleeaoste.it +valléeaoste.it +valleedaoste.it +valléedaoste.it +vao.it +vda.it +ven.it +veneto.it +// Provinces +ag.it +agrigento.it +al.it +alessandria.it +alto-adige.it +altoadige.it +an.it +ancona.it +andria-barletta-trani.it +andria-trani-barletta.it +andriabarlettatrani.it +andriatranibarletta.it +ao.it +aosta.it +aoste.it +ap.it +aq.it +aquila.it +ar.it +arezzo.it +ascoli-piceno.it +ascolipiceno.it +asti.it +at.it +av.it +avellino.it +ba.it +balsan-sudtirol.it +balsan-südtirol.it +balsan-suedtirol.it +balsan.it +bari.it +barletta-trani-andria.it +barlettatraniandria.it +belluno.it +benevento.it +bergamo.it +bg.it +bi.it +biella.it +bl.it +bn.it +bo.it +bologna.it +bolzano-altoadige.it +bolzano.it +bozen-sudtirol.it +bozen-südtirol.it +bozen-suedtirol.it +bozen.it +br.it +brescia.it +brindisi.it +bs.it +bt.it +bulsan-sudtirol.it +bulsan-südtirol.it +bulsan-suedtirol.it +bulsan.it +bz.it +ca.it +cagliari.it +caltanissetta.it +campidano-medio.it +campidanomedio.it +campobasso.it +carbonia-iglesias.it +carboniaiglesias.it +carrara-massa.it +carraramassa.it +caserta.it +catania.it +catanzaro.it +cb.it +ce.it +cesena-forli.it +cesena-forlì.it +cesenaforli.it +cesenaforlì.it +ch.it +chieti.it +ci.it +cl.it +cn.it +co.it +como.it +cosenza.it +cr.it +cremona.it +crotone.it +cs.it +ct.it +cuneo.it +cz.it +dell-ogliastra.it +dellogliastra.it +en.it +enna.it +fc.it +fe.it +fermo.it +ferrara.it +fg.it +fi.it +firenze.it +florence.it +fm.it +foggia.it +forli-cesena.it +forlì-cesena.it +forlicesena.it +forlìcesena.it +fr.it +frosinone.it +ge.it +genoa.it +genova.it +go.it +gorizia.it +gr.it +grosseto.it +iglesias-carbonia.it +iglesiascarbonia.it +im.it +imperia.it +is.it +isernia.it +kr.it +la-spezia.it +laquila.it +laspezia.it +latina.it +lc.it +le.it +lecce.it +lecco.it +li.it +livorno.it +lo.it +lodi.it +lt.it +lu.it +lucca.it +macerata.it +mantova.it +massa-carrara.it +massacarrara.it +matera.it +mb.it +mc.it +me.it +medio-campidano.it +mediocampidano.it +messina.it +mi.it +milan.it +milano.it +mn.it +mo.it +modena.it +monza-brianza.it +monza-e-della-brianza.it +monza.it +monzabrianza.it +monzaebrianza.it +monzaedellabrianza.it +ms.it +mt.it +na.it +naples.it +napoli.it +no.it +novara.it +nu.it +nuoro.it +og.it +ogliastra.it +olbia-tempio.it +olbiatempio.it +or.it +oristano.it +ot.it +pa.it +padova.it +padua.it +palermo.it +parma.it +pavia.it +pc.it +pd.it +pe.it +perugia.it +pesaro-urbino.it +pesarourbino.it +pescara.it +pg.it +pi.it +piacenza.it +pisa.it +pistoia.it +pn.it +po.it +pordenone.it +potenza.it +pr.it +prato.it +pt.it +pu.it +pv.it +pz.it +ra.it +ragusa.it +ravenna.it +rc.it +re.it +reggio-calabria.it +reggio-emilia.it +reggiocalabria.it +reggioemilia.it +rg.it +ri.it +rieti.it +rimini.it +rm.it +rn.it +ro.it +roma.it +rome.it +rovigo.it +sa.it +salerno.it +sassari.it +savona.it +si.it +siena.it +siracusa.it +so.it +sondrio.it +sp.it +sr.it +ss.it +suedtirol.it +südtirol.it +sv.it +ta.it +taranto.it +te.it +tempio-olbia.it +tempioolbia.it +teramo.it +terni.it +tn.it +to.it +torino.it +tp.it +tr.it +trani-andria-barletta.it +trani-barletta-andria.it +traniandriabarletta.it +tranibarlettaandria.it +trapani.it +trento.it +treviso.it +trieste.it +ts.it +turin.it +tv.it +ud.it +udine.it +urbino-pesaro.it +urbinopesaro.it +va.it +varese.it +vb.it +vc.it +ve.it +venezia.it +venice.it +verbania.it +vercelli.it +verona.it +vi.it +vibo-valentia.it +vibovalentia.it +vicenza.it +viterbo.it +vr.it +vs.it +vt.it +vv.it + +// je : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +je +co.je +net.je +org.je + +// jm : http://www.com.jm/register.html +*.jm + +// jo : http://www.dns.jo/Registration_policy.aspx +jo +com.jo +org.jo +net.jo +edu.jo +sch.jo +gov.jo +mil.jo +name.jo + +// jobs : https://en.wikipedia.org/wiki/.jobs +jobs + +// jp : https://en.wikipedia.org/wiki/.jp +// http://jprs.co.jp/en/jpdomain.html +// Submitted by registry +jp +// jp organizational type names +ac.jp +ad.jp +co.jp +ed.jp +go.jp +gr.jp +lg.jp +ne.jp +or.jp +// jp prefecture type names +aichi.jp +akita.jp +aomori.jp +chiba.jp +ehime.jp +fukui.jp +fukuoka.jp +fukushima.jp +gifu.jp +gunma.jp +hiroshima.jp +hokkaido.jp +hyogo.jp +ibaraki.jp +ishikawa.jp +iwate.jp +kagawa.jp +kagoshima.jp +kanagawa.jp +kochi.jp +kumamoto.jp +kyoto.jp +mie.jp +miyagi.jp +miyazaki.jp +nagano.jp +nagasaki.jp +nara.jp +niigata.jp +oita.jp +okayama.jp +okinawa.jp +osaka.jp +saga.jp +saitama.jp +shiga.jp +shimane.jp +shizuoka.jp +tochigi.jp +tokushima.jp +tokyo.jp +tottori.jp +toyama.jp +wakayama.jp +yamagata.jp +yamaguchi.jp +yamanashi.jp +栃木.jp +愛知.jp +愛媛.jp +兵庫.jp +熊本.jp +茨城.jp +北海道.jp +千葉.jp +和歌山.jp +長崎.jp +長野.jp +新潟.jp +青森.jp +静岡.jp +東京.jp +石川.jp +埼玉.jp +三重.jp +京都.jp +佐賀.jp +大分.jp +大阪.jp +奈良.jp +宮城.jp +宮崎.jp +富山.jp +山口.jp +山形.jp +山梨.jp +岩手.jp +岐阜.jp +岡山.jp +島根.jp +広島.jp +徳島.jp +沖縄.jp +滋賀.jp +神奈川.jp +福井.jp +福岡.jp +福島.jp +秋田.jp +群馬.jp +香川.jp +高知.jp +鳥取.jp +鹿児島.jp +// jp geographic type names +// http://jprs.jp/doc/rule/saisoku-1.html +*.kawasaki.jp +*.kitakyushu.jp +*.kobe.jp +*.nagoya.jp +*.sapporo.jp +*.sendai.jp +*.yokohama.jp +!city.kawasaki.jp +!city.kitakyushu.jp +!city.kobe.jp +!city.nagoya.jp +!city.sapporo.jp +!city.sendai.jp +!city.yokohama.jp +// 4th level registration +aisai.aichi.jp +ama.aichi.jp +anjo.aichi.jp +asuke.aichi.jp +chiryu.aichi.jp +chita.aichi.jp +fuso.aichi.jp +gamagori.aichi.jp +handa.aichi.jp +hazu.aichi.jp +hekinan.aichi.jp +higashiura.aichi.jp +ichinomiya.aichi.jp +inazawa.aichi.jp +inuyama.aichi.jp +isshiki.aichi.jp +iwakura.aichi.jp +kanie.aichi.jp +kariya.aichi.jp +kasugai.aichi.jp +kira.aichi.jp +kiyosu.aichi.jp +komaki.aichi.jp +konan.aichi.jp +kota.aichi.jp +mihama.aichi.jp +miyoshi.aichi.jp +nishio.aichi.jp +nisshin.aichi.jp +obu.aichi.jp +oguchi.aichi.jp +oharu.aichi.jp +okazaki.aichi.jp +owariasahi.aichi.jp +seto.aichi.jp +shikatsu.aichi.jp +shinshiro.aichi.jp +shitara.aichi.jp +tahara.aichi.jp +takahama.aichi.jp +tobishima.aichi.jp +toei.aichi.jp +togo.aichi.jp +tokai.aichi.jp +tokoname.aichi.jp +toyoake.aichi.jp +toyohashi.aichi.jp +toyokawa.aichi.jp +toyone.aichi.jp +toyota.aichi.jp +tsushima.aichi.jp +yatomi.aichi.jp +akita.akita.jp +daisen.akita.jp +fujisato.akita.jp +gojome.akita.jp +hachirogata.akita.jp +happou.akita.jp +higashinaruse.akita.jp +honjo.akita.jp +honjyo.akita.jp +ikawa.akita.jp +kamikoani.akita.jp +kamioka.akita.jp +katagami.akita.jp +kazuno.akita.jp +kitaakita.akita.jp +kosaka.akita.jp +kyowa.akita.jp +misato.akita.jp +mitane.akita.jp +moriyoshi.akita.jp +nikaho.akita.jp +noshiro.akita.jp +odate.akita.jp +oga.akita.jp +ogata.akita.jp +semboku.akita.jp +yokote.akita.jp +yurihonjo.akita.jp +aomori.aomori.jp +gonohe.aomori.jp +hachinohe.aomori.jp +hashikami.aomori.jp +hiranai.aomori.jp +hirosaki.aomori.jp +itayanagi.aomori.jp +kuroishi.aomori.jp +misawa.aomori.jp +mutsu.aomori.jp +nakadomari.aomori.jp +noheji.aomori.jp +oirase.aomori.jp +owani.aomori.jp +rokunohe.aomori.jp +sannohe.aomori.jp +shichinohe.aomori.jp +shingo.aomori.jp +takko.aomori.jp +towada.aomori.jp +tsugaru.aomori.jp +tsuruta.aomori.jp +abiko.chiba.jp +asahi.chiba.jp +chonan.chiba.jp +chosei.chiba.jp +choshi.chiba.jp +chuo.chiba.jp +funabashi.chiba.jp +futtsu.chiba.jp +hanamigawa.chiba.jp +ichihara.chiba.jp +ichikawa.chiba.jp +ichinomiya.chiba.jp +inzai.chiba.jp +isumi.chiba.jp +kamagaya.chiba.jp +kamogawa.chiba.jp +kashiwa.chiba.jp +katori.chiba.jp +katsuura.chiba.jp +kimitsu.chiba.jp +kisarazu.chiba.jp +kozaki.chiba.jp +kujukuri.chiba.jp +kyonan.chiba.jp +matsudo.chiba.jp +midori.chiba.jp +mihama.chiba.jp +minamiboso.chiba.jp +mobara.chiba.jp +mutsuzawa.chiba.jp +nagara.chiba.jp +nagareyama.chiba.jp +narashino.chiba.jp +narita.chiba.jp +noda.chiba.jp +oamishirasato.chiba.jp +omigawa.chiba.jp +onjuku.chiba.jp +otaki.chiba.jp +sakae.chiba.jp +sakura.chiba.jp +shimofusa.chiba.jp +shirako.chiba.jp +shiroi.chiba.jp +shisui.chiba.jp +sodegaura.chiba.jp +sosa.chiba.jp +tako.chiba.jp +tateyama.chiba.jp +togane.chiba.jp +tohnosho.chiba.jp +tomisato.chiba.jp +urayasu.chiba.jp +yachimata.chiba.jp +yachiyo.chiba.jp +yokaichiba.chiba.jp +yokoshibahikari.chiba.jp +yotsukaido.chiba.jp +ainan.ehime.jp +honai.ehime.jp +ikata.ehime.jp +imabari.ehime.jp +iyo.ehime.jp +kamijima.ehime.jp +kihoku.ehime.jp +kumakogen.ehime.jp +masaki.ehime.jp +matsuno.ehime.jp +matsuyama.ehime.jp +namikata.ehime.jp +niihama.ehime.jp +ozu.ehime.jp +saijo.ehime.jp +seiyo.ehime.jp +shikokuchuo.ehime.jp +tobe.ehime.jp +toon.ehime.jp +uchiko.ehime.jp +uwajima.ehime.jp +yawatahama.ehime.jp +echizen.fukui.jp +eiheiji.fukui.jp +fukui.fukui.jp +ikeda.fukui.jp +katsuyama.fukui.jp +mihama.fukui.jp +minamiechizen.fukui.jp +obama.fukui.jp +ohi.fukui.jp +ono.fukui.jp +sabae.fukui.jp +sakai.fukui.jp +takahama.fukui.jp +tsuruga.fukui.jp +wakasa.fukui.jp +ashiya.fukuoka.jp +buzen.fukuoka.jp +chikugo.fukuoka.jp +chikuho.fukuoka.jp +chikujo.fukuoka.jp +chikushino.fukuoka.jp +chikuzen.fukuoka.jp +chuo.fukuoka.jp +dazaifu.fukuoka.jp +fukuchi.fukuoka.jp +hakata.fukuoka.jp +higashi.fukuoka.jp +hirokawa.fukuoka.jp +hisayama.fukuoka.jp +iizuka.fukuoka.jp +inatsuki.fukuoka.jp +kaho.fukuoka.jp +kasuga.fukuoka.jp +kasuya.fukuoka.jp +kawara.fukuoka.jp +keisen.fukuoka.jp +koga.fukuoka.jp +kurate.fukuoka.jp +kurogi.fukuoka.jp +kurume.fukuoka.jp +minami.fukuoka.jp +miyako.fukuoka.jp +miyama.fukuoka.jp +miyawaka.fukuoka.jp +mizumaki.fukuoka.jp +munakata.fukuoka.jp +nakagawa.fukuoka.jp +nakama.fukuoka.jp +nishi.fukuoka.jp +nogata.fukuoka.jp +ogori.fukuoka.jp +okagaki.fukuoka.jp +okawa.fukuoka.jp +oki.fukuoka.jp +omuta.fukuoka.jp +onga.fukuoka.jp +onojo.fukuoka.jp +oto.fukuoka.jp +saigawa.fukuoka.jp +sasaguri.fukuoka.jp +shingu.fukuoka.jp +shinyoshitomi.fukuoka.jp +shonai.fukuoka.jp +soeda.fukuoka.jp +sue.fukuoka.jp +tachiarai.fukuoka.jp +tagawa.fukuoka.jp +takata.fukuoka.jp +toho.fukuoka.jp +toyotsu.fukuoka.jp +tsuiki.fukuoka.jp +ukiha.fukuoka.jp +umi.fukuoka.jp +usui.fukuoka.jp +yamada.fukuoka.jp +yame.fukuoka.jp +yanagawa.fukuoka.jp +yukuhashi.fukuoka.jp +aizubange.fukushima.jp +aizumisato.fukushima.jp +aizuwakamatsu.fukushima.jp +asakawa.fukushima.jp +bandai.fukushima.jp +date.fukushima.jp +fukushima.fukushima.jp +furudono.fukushima.jp +futaba.fukushima.jp +hanawa.fukushima.jp +higashi.fukushima.jp +hirata.fukushima.jp +hirono.fukushima.jp +iitate.fukushima.jp +inawashiro.fukushima.jp +ishikawa.fukushima.jp +iwaki.fukushima.jp +izumizaki.fukushima.jp +kagamiishi.fukushima.jp +kaneyama.fukushima.jp +kawamata.fukushima.jp +kitakata.fukushima.jp +kitashiobara.fukushima.jp +koori.fukushima.jp +koriyama.fukushima.jp +kunimi.fukushima.jp +miharu.fukushima.jp +mishima.fukushima.jp +namie.fukushima.jp +nango.fukushima.jp +nishiaizu.fukushima.jp +nishigo.fukushima.jp +okuma.fukushima.jp +omotego.fukushima.jp +ono.fukushima.jp +otama.fukushima.jp +samegawa.fukushima.jp +shimogo.fukushima.jp +shirakawa.fukushima.jp +showa.fukushima.jp +soma.fukushima.jp +sukagawa.fukushima.jp +taishin.fukushima.jp +tamakawa.fukushima.jp +tanagura.fukushima.jp +tenei.fukushima.jp +yabuki.fukushima.jp +yamato.fukushima.jp +yamatsuri.fukushima.jp +yanaizu.fukushima.jp +yugawa.fukushima.jp +anpachi.gifu.jp +ena.gifu.jp +gifu.gifu.jp +ginan.gifu.jp +godo.gifu.jp +gujo.gifu.jp +hashima.gifu.jp +hichiso.gifu.jp +hida.gifu.jp +higashishirakawa.gifu.jp +ibigawa.gifu.jp +ikeda.gifu.jp +kakamigahara.gifu.jp +kani.gifu.jp +kasahara.gifu.jp +kasamatsu.gifu.jp +kawaue.gifu.jp +kitagata.gifu.jp +mino.gifu.jp +minokamo.gifu.jp +mitake.gifu.jp +mizunami.gifu.jp +motosu.gifu.jp +nakatsugawa.gifu.jp +ogaki.gifu.jp +sakahogi.gifu.jp +seki.gifu.jp +sekigahara.gifu.jp +shirakawa.gifu.jp +tajimi.gifu.jp +takayama.gifu.jp +tarui.gifu.jp +toki.gifu.jp +tomika.gifu.jp +wanouchi.gifu.jp +yamagata.gifu.jp +yaotsu.gifu.jp +yoro.gifu.jp +annaka.gunma.jp +chiyoda.gunma.jp +fujioka.gunma.jp +higashiagatsuma.gunma.jp +isesaki.gunma.jp +itakura.gunma.jp +kanna.gunma.jp +kanra.gunma.jp +katashina.gunma.jp +kawaba.gunma.jp +kiryu.gunma.jp +kusatsu.gunma.jp +maebashi.gunma.jp +meiwa.gunma.jp +midori.gunma.jp +minakami.gunma.jp +naganohara.gunma.jp +nakanojo.gunma.jp +nanmoku.gunma.jp +numata.gunma.jp +oizumi.gunma.jp +ora.gunma.jp +ota.gunma.jp +shibukawa.gunma.jp +shimonita.gunma.jp +shinto.gunma.jp +showa.gunma.jp +takasaki.gunma.jp +takayama.gunma.jp +tamamura.gunma.jp +tatebayashi.gunma.jp +tomioka.gunma.jp +tsukiyono.gunma.jp +tsumagoi.gunma.jp +ueno.gunma.jp +yoshioka.gunma.jp +asaminami.hiroshima.jp +daiwa.hiroshima.jp +etajima.hiroshima.jp +fuchu.hiroshima.jp +fukuyama.hiroshima.jp +hatsukaichi.hiroshima.jp +higashihiroshima.hiroshima.jp +hongo.hiroshima.jp +jinsekikogen.hiroshima.jp +kaita.hiroshima.jp +kui.hiroshima.jp +kumano.hiroshima.jp +kure.hiroshima.jp +mihara.hiroshima.jp +miyoshi.hiroshima.jp +naka.hiroshima.jp +onomichi.hiroshima.jp +osakikamijima.hiroshima.jp +otake.hiroshima.jp +saka.hiroshima.jp +sera.hiroshima.jp +seranishi.hiroshima.jp +shinichi.hiroshima.jp +shobara.hiroshima.jp +takehara.hiroshima.jp +abashiri.hokkaido.jp +abira.hokkaido.jp +aibetsu.hokkaido.jp +akabira.hokkaido.jp +akkeshi.hokkaido.jp +asahikawa.hokkaido.jp +ashibetsu.hokkaido.jp +ashoro.hokkaido.jp +assabu.hokkaido.jp +atsuma.hokkaido.jp +bibai.hokkaido.jp +biei.hokkaido.jp +bifuka.hokkaido.jp +bihoro.hokkaido.jp +biratori.hokkaido.jp +chippubetsu.hokkaido.jp +chitose.hokkaido.jp +date.hokkaido.jp +ebetsu.hokkaido.jp +embetsu.hokkaido.jp +eniwa.hokkaido.jp +erimo.hokkaido.jp +esan.hokkaido.jp +esashi.hokkaido.jp +fukagawa.hokkaido.jp +fukushima.hokkaido.jp +furano.hokkaido.jp +furubira.hokkaido.jp +haboro.hokkaido.jp +hakodate.hokkaido.jp +hamatonbetsu.hokkaido.jp +hidaka.hokkaido.jp +higashikagura.hokkaido.jp +higashikawa.hokkaido.jp +hiroo.hokkaido.jp +hokuryu.hokkaido.jp +hokuto.hokkaido.jp +honbetsu.hokkaido.jp +horokanai.hokkaido.jp +horonobe.hokkaido.jp +ikeda.hokkaido.jp +imakane.hokkaido.jp +ishikari.hokkaido.jp +iwamizawa.hokkaido.jp +iwanai.hokkaido.jp +kamifurano.hokkaido.jp +kamikawa.hokkaido.jp +kamishihoro.hokkaido.jp +kamisunagawa.hokkaido.jp +kamoenai.hokkaido.jp +kayabe.hokkaido.jp +kembuchi.hokkaido.jp +kikonai.hokkaido.jp +kimobetsu.hokkaido.jp +kitahiroshima.hokkaido.jp +kitami.hokkaido.jp +kiyosato.hokkaido.jp +koshimizu.hokkaido.jp +kunneppu.hokkaido.jp +kuriyama.hokkaido.jp +kuromatsunai.hokkaido.jp +kushiro.hokkaido.jp +kutchan.hokkaido.jp +kyowa.hokkaido.jp +mashike.hokkaido.jp +matsumae.hokkaido.jp +mikasa.hokkaido.jp +minamifurano.hokkaido.jp +mombetsu.hokkaido.jp +moseushi.hokkaido.jp +mukawa.hokkaido.jp +muroran.hokkaido.jp +naie.hokkaido.jp +nakagawa.hokkaido.jp +nakasatsunai.hokkaido.jp +nakatombetsu.hokkaido.jp +nanae.hokkaido.jp +nanporo.hokkaido.jp +nayoro.hokkaido.jp +nemuro.hokkaido.jp +niikappu.hokkaido.jp +niki.hokkaido.jp +nishiokoppe.hokkaido.jp +noboribetsu.hokkaido.jp +numata.hokkaido.jp +obihiro.hokkaido.jp +obira.hokkaido.jp +oketo.hokkaido.jp +okoppe.hokkaido.jp +otaru.hokkaido.jp +otobe.hokkaido.jp +otofuke.hokkaido.jp +otoineppu.hokkaido.jp +oumu.hokkaido.jp +ozora.hokkaido.jp +pippu.hokkaido.jp +rankoshi.hokkaido.jp +rebun.hokkaido.jp +rikubetsu.hokkaido.jp +rishiri.hokkaido.jp +rishirifuji.hokkaido.jp +saroma.hokkaido.jp +sarufutsu.hokkaido.jp +shakotan.hokkaido.jp +shari.hokkaido.jp +shibecha.hokkaido.jp +shibetsu.hokkaido.jp +shikabe.hokkaido.jp +shikaoi.hokkaido.jp +shimamaki.hokkaido.jp +shimizu.hokkaido.jp +shimokawa.hokkaido.jp +shinshinotsu.hokkaido.jp +shintoku.hokkaido.jp +shiranuka.hokkaido.jp +shiraoi.hokkaido.jp +shiriuchi.hokkaido.jp +sobetsu.hokkaido.jp +sunagawa.hokkaido.jp +taiki.hokkaido.jp +takasu.hokkaido.jp +takikawa.hokkaido.jp +takinoue.hokkaido.jp +teshikaga.hokkaido.jp +tobetsu.hokkaido.jp +tohma.hokkaido.jp +tomakomai.hokkaido.jp +tomari.hokkaido.jp +toya.hokkaido.jp +toyako.hokkaido.jp +toyotomi.hokkaido.jp +toyoura.hokkaido.jp +tsubetsu.hokkaido.jp +tsukigata.hokkaido.jp +urakawa.hokkaido.jp +urausu.hokkaido.jp +uryu.hokkaido.jp +utashinai.hokkaido.jp +wakkanai.hokkaido.jp +wassamu.hokkaido.jp +yakumo.hokkaido.jp +yoichi.hokkaido.jp +aioi.hyogo.jp +akashi.hyogo.jp +ako.hyogo.jp +amagasaki.hyogo.jp +aogaki.hyogo.jp +asago.hyogo.jp +ashiya.hyogo.jp +awaji.hyogo.jp +fukusaki.hyogo.jp +goshiki.hyogo.jp +harima.hyogo.jp +himeji.hyogo.jp +ichikawa.hyogo.jp +inagawa.hyogo.jp +itami.hyogo.jp +kakogawa.hyogo.jp +kamigori.hyogo.jp +kamikawa.hyogo.jp +kasai.hyogo.jp +kasuga.hyogo.jp +kawanishi.hyogo.jp +miki.hyogo.jp +minamiawaji.hyogo.jp +nishinomiya.hyogo.jp +nishiwaki.hyogo.jp +ono.hyogo.jp +sanda.hyogo.jp +sannan.hyogo.jp +sasayama.hyogo.jp +sayo.hyogo.jp +shingu.hyogo.jp +shinonsen.hyogo.jp +shiso.hyogo.jp +sumoto.hyogo.jp +taishi.hyogo.jp +taka.hyogo.jp +takarazuka.hyogo.jp +takasago.hyogo.jp +takino.hyogo.jp +tamba.hyogo.jp +tatsuno.hyogo.jp +toyooka.hyogo.jp +yabu.hyogo.jp +yashiro.hyogo.jp +yoka.hyogo.jp +yokawa.hyogo.jp +ami.ibaraki.jp +asahi.ibaraki.jp +bando.ibaraki.jp +chikusei.ibaraki.jp +daigo.ibaraki.jp +fujishiro.ibaraki.jp +hitachi.ibaraki.jp +hitachinaka.ibaraki.jp +hitachiomiya.ibaraki.jp +hitachiota.ibaraki.jp +ibaraki.ibaraki.jp +ina.ibaraki.jp +inashiki.ibaraki.jp +itako.ibaraki.jp +iwama.ibaraki.jp +joso.ibaraki.jp +kamisu.ibaraki.jp +kasama.ibaraki.jp +kashima.ibaraki.jp +kasumigaura.ibaraki.jp +koga.ibaraki.jp +miho.ibaraki.jp +mito.ibaraki.jp +moriya.ibaraki.jp +naka.ibaraki.jp +namegata.ibaraki.jp +oarai.ibaraki.jp +ogawa.ibaraki.jp +omitama.ibaraki.jp +ryugasaki.ibaraki.jp +sakai.ibaraki.jp +sakuragawa.ibaraki.jp +shimodate.ibaraki.jp +shimotsuma.ibaraki.jp +shirosato.ibaraki.jp +sowa.ibaraki.jp +suifu.ibaraki.jp +takahagi.ibaraki.jp +tamatsukuri.ibaraki.jp +tokai.ibaraki.jp +tomobe.ibaraki.jp +tone.ibaraki.jp +toride.ibaraki.jp +tsuchiura.ibaraki.jp +tsukuba.ibaraki.jp +uchihara.ibaraki.jp +ushiku.ibaraki.jp +yachiyo.ibaraki.jp +yamagata.ibaraki.jp +yawara.ibaraki.jp +yuki.ibaraki.jp +anamizu.ishikawa.jp +hakui.ishikawa.jp +hakusan.ishikawa.jp +kaga.ishikawa.jp +kahoku.ishikawa.jp +kanazawa.ishikawa.jp +kawakita.ishikawa.jp +komatsu.ishikawa.jp +nakanoto.ishikawa.jp +nanao.ishikawa.jp +nomi.ishikawa.jp +nonoichi.ishikawa.jp +noto.ishikawa.jp +shika.ishikawa.jp +suzu.ishikawa.jp +tsubata.ishikawa.jp +tsurugi.ishikawa.jp +uchinada.ishikawa.jp +wajima.ishikawa.jp +fudai.iwate.jp +fujisawa.iwate.jp +hanamaki.iwate.jp +hiraizumi.iwate.jp +hirono.iwate.jp +ichinohe.iwate.jp +ichinoseki.iwate.jp +iwaizumi.iwate.jp +iwate.iwate.jp +joboji.iwate.jp +kamaishi.iwate.jp +kanegasaki.iwate.jp +karumai.iwate.jp +kawai.iwate.jp +kitakami.iwate.jp +kuji.iwate.jp +kunohe.iwate.jp +kuzumaki.iwate.jp +miyako.iwate.jp +mizusawa.iwate.jp +morioka.iwate.jp +ninohe.iwate.jp +noda.iwate.jp +ofunato.iwate.jp +oshu.iwate.jp +otsuchi.iwate.jp +rikuzentakata.iwate.jp +shiwa.iwate.jp +shizukuishi.iwate.jp +sumita.iwate.jp +tanohata.iwate.jp +tono.iwate.jp +yahaba.iwate.jp +yamada.iwate.jp +ayagawa.kagawa.jp +higashikagawa.kagawa.jp +kanonji.kagawa.jp +kotohira.kagawa.jp +manno.kagawa.jp +marugame.kagawa.jp +mitoyo.kagawa.jp +naoshima.kagawa.jp +sanuki.kagawa.jp +tadotsu.kagawa.jp +takamatsu.kagawa.jp +tonosho.kagawa.jp +uchinomi.kagawa.jp +utazu.kagawa.jp +zentsuji.kagawa.jp +akune.kagoshima.jp +amami.kagoshima.jp +hioki.kagoshima.jp +isa.kagoshima.jp +isen.kagoshima.jp +izumi.kagoshima.jp +kagoshima.kagoshima.jp +kanoya.kagoshima.jp +kawanabe.kagoshima.jp +kinko.kagoshima.jp +kouyama.kagoshima.jp +makurazaki.kagoshima.jp +matsumoto.kagoshima.jp +minamitane.kagoshima.jp +nakatane.kagoshima.jp +nishinoomote.kagoshima.jp +satsumasendai.kagoshima.jp +soo.kagoshima.jp +tarumizu.kagoshima.jp +yusui.kagoshima.jp +aikawa.kanagawa.jp +atsugi.kanagawa.jp +ayase.kanagawa.jp +chigasaki.kanagawa.jp +ebina.kanagawa.jp +fujisawa.kanagawa.jp +hadano.kanagawa.jp +hakone.kanagawa.jp +hiratsuka.kanagawa.jp +isehara.kanagawa.jp +kaisei.kanagawa.jp +kamakura.kanagawa.jp +kiyokawa.kanagawa.jp +matsuda.kanagawa.jp +minamiashigara.kanagawa.jp +miura.kanagawa.jp +nakai.kanagawa.jp +ninomiya.kanagawa.jp +odawara.kanagawa.jp +oi.kanagawa.jp +oiso.kanagawa.jp +sagamihara.kanagawa.jp +samukawa.kanagawa.jp +tsukui.kanagawa.jp +yamakita.kanagawa.jp +yamato.kanagawa.jp +yokosuka.kanagawa.jp +yugawara.kanagawa.jp +zama.kanagawa.jp +zushi.kanagawa.jp +aki.kochi.jp +geisei.kochi.jp +hidaka.kochi.jp +higashitsuno.kochi.jp +ino.kochi.jp +kagami.kochi.jp +kami.kochi.jp +kitagawa.kochi.jp +kochi.kochi.jp +mihara.kochi.jp +motoyama.kochi.jp +muroto.kochi.jp +nahari.kochi.jp +nakamura.kochi.jp +nankoku.kochi.jp +nishitosa.kochi.jp +niyodogawa.kochi.jp +ochi.kochi.jp +okawa.kochi.jp +otoyo.kochi.jp +otsuki.kochi.jp +sakawa.kochi.jp +sukumo.kochi.jp +susaki.kochi.jp +tosa.kochi.jp +tosashimizu.kochi.jp +toyo.kochi.jp +tsuno.kochi.jp +umaji.kochi.jp +yasuda.kochi.jp +yusuhara.kochi.jp +amakusa.kumamoto.jp +arao.kumamoto.jp +aso.kumamoto.jp +choyo.kumamoto.jp +gyokuto.kumamoto.jp +kamiamakusa.kumamoto.jp +kikuchi.kumamoto.jp +kumamoto.kumamoto.jp +mashiki.kumamoto.jp +mifune.kumamoto.jp +minamata.kumamoto.jp +minamioguni.kumamoto.jp +nagasu.kumamoto.jp +nishihara.kumamoto.jp +oguni.kumamoto.jp +ozu.kumamoto.jp +sumoto.kumamoto.jp +takamori.kumamoto.jp +uki.kumamoto.jp +uto.kumamoto.jp +yamaga.kumamoto.jp +yamato.kumamoto.jp +yatsushiro.kumamoto.jp +ayabe.kyoto.jp +fukuchiyama.kyoto.jp +higashiyama.kyoto.jp +ide.kyoto.jp +ine.kyoto.jp +joyo.kyoto.jp +kameoka.kyoto.jp +kamo.kyoto.jp +kita.kyoto.jp +kizu.kyoto.jp +kumiyama.kyoto.jp +kyotamba.kyoto.jp +kyotanabe.kyoto.jp +kyotango.kyoto.jp +maizuru.kyoto.jp +minami.kyoto.jp +minamiyamashiro.kyoto.jp +miyazu.kyoto.jp +muko.kyoto.jp +nagaokakyo.kyoto.jp +nakagyo.kyoto.jp +nantan.kyoto.jp +oyamazaki.kyoto.jp +sakyo.kyoto.jp +seika.kyoto.jp +tanabe.kyoto.jp +uji.kyoto.jp +ujitawara.kyoto.jp +wazuka.kyoto.jp +yamashina.kyoto.jp +yawata.kyoto.jp +asahi.mie.jp +inabe.mie.jp +ise.mie.jp +kameyama.mie.jp +kawagoe.mie.jp +kiho.mie.jp +kisosaki.mie.jp +kiwa.mie.jp +komono.mie.jp +kumano.mie.jp +kuwana.mie.jp +matsusaka.mie.jp +meiwa.mie.jp +mihama.mie.jp +minamiise.mie.jp +misugi.mie.jp +miyama.mie.jp +nabari.mie.jp +shima.mie.jp +suzuka.mie.jp +tado.mie.jp +taiki.mie.jp +taki.mie.jp +tamaki.mie.jp +toba.mie.jp +tsu.mie.jp +udono.mie.jp +ureshino.mie.jp +watarai.mie.jp +yokkaichi.mie.jp +furukawa.miyagi.jp +higashimatsushima.miyagi.jp +ishinomaki.miyagi.jp +iwanuma.miyagi.jp +kakuda.miyagi.jp +kami.miyagi.jp +kawasaki.miyagi.jp +marumori.miyagi.jp +matsushima.miyagi.jp +minamisanriku.miyagi.jp +misato.miyagi.jp +murata.miyagi.jp +natori.miyagi.jp +ogawara.miyagi.jp +ohira.miyagi.jp +onagawa.miyagi.jp +osaki.miyagi.jp +rifu.miyagi.jp +semine.miyagi.jp +shibata.miyagi.jp +shichikashuku.miyagi.jp +shikama.miyagi.jp +shiogama.miyagi.jp +shiroishi.miyagi.jp +tagajo.miyagi.jp +taiwa.miyagi.jp +tome.miyagi.jp +tomiya.miyagi.jp +wakuya.miyagi.jp +watari.miyagi.jp +yamamoto.miyagi.jp +zao.miyagi.jp +aya.miyazaki.jp +ebino.miyazaki.jp +gokase.miyazaki.jp +hyuga.miyazaki.jp +kadogawa.miyazaki.jp +kawaminami.miyazaki.jp +kijo.miyazaki.jp +kitagawa.miyazaki.jp +kitakata.miyazaki.jp +kitaura.miyazaki.jp +kobayashi.miyazaki.jp +kunitomi.miyazaki.jp +kushima.miyazaki.jp +mimata.miyazaki.jp +miyakonojo.miyazaki.jp +miyazaki.miyazaki.jp +morotsuka.miyazaki.jp +nichinan.miyazaki.jp +nishimera.miyazaki.jp +nobeoka.miyazaki.jp +saito.miyazaki.jp +shiiba.miyazaki.jp +shintomi.miyazaki.jp +takaharu.miyazaki.jp +takanabe.miyazaki.jp +takazaki.miyazaki.jp +tsuno.miyazaki.jp +achi.nagano.jp +agematsu.nagano.jp +anan.nagano.jp +aoki.nagano.jp +asahi.nagano.jp +azumino.nagano.jp +chikuhoku.nagano.jp +chikuma.nagano.jp +chino.nagano.jp +fujimi.nagano.jp +hakuba.nagano.jp +hara.nagano.jp +hiraya.nagano.jp +iida.nagano.jp +iijima.nagano.jp +iiyama.nagano.jp +iizuna.nagano.jp +ikeda.nagano.jp +ikusaka.nagano.jp +ina.nagano.jp +karuizawa.nagano.jp +kawakami.nagano.jp +kiso.nagano.jp +kisofukushima.nagano.jp +kitaaiki.nagano.jp +komagane.nagano.jp +komoro.nagano.jp +matsukawa.nagano.jp +matsumoto.nagano.jp +miasa.nagano.jp +minamiaiki.nagano.jp +minamimaki.nagano.jp +minamiminowa.nagano.jp +minowa.nagano.jp +miyada.nagano.jp +miyota.nagano.jp +mochizuki.nagano.jp +nagano.nagano.jp +nagawa.nagano.jp +nagiso.nagano.jp +nakagawa.nagano.jp +nakano.nagano.jp +nozawaonsen.nagano.jp +obuse.nagano.jp +ogawa.nagano.jp +okaya.nagano.jp +omachi.nagano.jp +omi.nagano.jp +ookuwa.nagano.jp +ooshika.nagano.jp +otaki.nagano.jp +otari.nagano.jp +sakae.nagano.jp +sakaki.nagano.jp +saku.nagano.jp +sakuho.nagano.jp +shimosuwa.nagano.jp +shinanomachi.nagano.jp +shiojiri.nagano.jp +suwa.nagano.jp +suzaka.nagano.jp +takagi.nagano.jp +takamori.nagano.jp +takayama.nagano.jp +tateshina.nagano.jp +tatsuno.nagano.jp +togakushi.nagano.jp +togura.nagano.jp +tomi.nagano.jp +ueda.nagano.jp +wada.nagano.jp +yamagata.nagano.jp +yamanouchi.nagano.jp +yasaka.nagano.jp +yasuoka.nagano.jp +chijiwa.nagasaki.jp +futsu.nagasaki.jp +goto.nagasaki.jp +hasami.nagasaki.jp +hirado.nagasaki.jp +iki.nagasaki.jp +isahaya.nagasaki.jp +kawatana.nagasaki.jp +kuchinotsu.nagasaki.jp +matsuura.nagasaki.jp +nagasaki.nagasaki.jp +obama.nagasaki.jp +omura.nagasaki.jp +oseto.nagasaki.jp +saikai.nagasaki.jp +sasebo.nagasaki.jp +seihi.nagasaki.jp +shimabara.nagasaki.jp +shinkamigoto.nagasaki.jp +togitsu.nagasaki.jp +tsushima.nagasaki.jp +unzen.nagasaki.jp +ando.nara.jp +gose.nara.jp +heguri.nara.jp +higashiyoshino.nara.jp +ikaruga.nara.jp +ikoma.nara.jp +kamikitayama.nara.jp +kanmaki.nara.jp +kashiba.nara.jp +kashihara.nara.jp +katsuragi.nara.jp +kawai.nara.jp +kawakami.nara.jp +kawanishi.nara.jp +koryo.nara.jp +kurotaki.nara.jp +mitsue.nara.jp +miyake.nara.jp +nara.nara.jp +nosegawa.nara.jp +oji.nara.jp +ouda.nara.jp +oyodo.nara.jp +sakurai.nara.jp +sango.nara.jp +shimoichi.nara.jp +shimokitayama.nara.jp +shinjo.nara.jp +soni.nara.jp +takatori.nara.jp +tawaramoto.nara.jp +tenkawa.nara.jp +tenri.nara.jp +uda.nara.jp +yamatokoriyama.nara.jp +yamatotakada.nara.jp +yamazoe.nara.jp +yoshino.nara.jp +aga.niigata.jp +agano.niigata.jp +gosen.niigata.jp +itoigawa.niigata.jp +izumozaki.niigata.jp +joetsu.niigata.jp +kamo.niigata.jp +kariwa.niigata.jp +kashiwazaki.niigata.jp +minamiuonuma.niigata.jp +mitsuke.niigata.jp +muika.niigata.jp +murakami.niigata.jp +myoko.niigata.jp +nagaoka.niigata.jp +niigata.niigata.jp +ojiya.niigata.jp +omi.niigata.jp +sado.niigata.jp +sanjo.niigata.jp +seiro.niigata.jp +seirou.niigata.jp +sekikawa.niigata.jp +shibata.niigata.jp +tagami.niigata.jp +tainai.niigata.jp +tochio.niigata.jp +tokamachi.niigata.jp +tsubame.niigata.jp +tsunan.niigata.jp +uonuma.niigata.jp +yahiko.niigata.jp +yoita.niigata.jp +yuzawa.niigata.jp +beppu.oita.jp +bungoono.oita.jp +bungotakada.oita.jp +hasama.oita.jp +hiji.oita.jp +himeshima.oita.jp +hita.oita.jp +kamitsue.oita.jp +kokonoe.oita.jp +kuju.oita.jp +kunisaki.oita.jp +kusu.oita.jp +oita.oita.jp +saiki.oita.jp +taketa.oita.jp +tsukumi.oita.jp +usa.oita.jp +usuki.oita.jp +yufu.oita.jp +akaiwa.okayama.jp +asakuchi.okayama.jp +bizen.okayama.jp +hayashima.okayama.jp +ibara.okayama.jp +kagamino.okayama.jp +kasaoka.okayama.jp +kibichuo.okayama.jp +kumenan.okayama.jp +kurashiki.okayama.jp +maniwa.okayama.jp +misaki.okayama.jp +nagi.okayama.jp +niimi.okayama.jp +nishiawakura.okayama.jp +okayama.okayama.jp +satosho.okayama.jp +setouchi.okayama.jp +shinjo.okayama.jp +shoo.okayama.jp +soja.okayama.jp +takahashi.okayama.jp +tamano.okayama.jp +tsuyama.okayama.jp +wake.okayama.jp +yakage.okayama.jp +aguni.okinawa.jp +ginowan.okinawa.jp +ginoza.okinawa.jp +gushikami.okinawa.jp +haebaru.okinawa.jp +higashi.okinawa.jp +hirara.okinawa.jp +iheya.okinawa.jp +ishigaki.okinawa.jp +ishikawa.okinawa.jp +itoman.okinawa.jp +izena.okinawa.jp +kadena.okinawa.jp +kin.okinawa.jp +kitadaito.okinawa.jp +kitanakagusuku.okinawa.jp +kumejima.okinawa.jp +kunigami.okinawa.jp +minamidaito.okinawa.jp +motobu.okinawa.jp +nago.okinawa.jp +naha.okinawa.jp +nakagusuku.okinawa.jp +nakijin.okinawa.jp +nanjo.okinawa.jp +nishihara.okinawa.jp +ogimi.okinawa.jp +okinawa.okinawa.jp +onna.okinawa.jp +shimoji.okinawa.jp +taketomi.okinawa.jp +tarama.okinawa.jp +tokashiki.okinawa.jp +tomigusuku.okinawa.jp +tonaki.okinawa.jp +urasoe.okinawa.jp +uruma.okinawa.jp +yaese.okinawa.jp +yomitan.okinawa.jp +yonabaru.okinawa.jp +yonaguni.okinawa.jp +zamami.okinawa.jp +abeno.osaka.jp +chihayaakasaka.osaka.jp +chuo.osaka.jp +daito.osaka.jp +fujiidera.osaka.jp +habikino.osaka.jp +hannan.osaka.jp +higashiosaka.osaka.jp +higashisumiyoshi.osaka.jp +higashiyodogawa.osaka.jp +hirakata.osaka.jp +ibaraki.osaka.jp +ikeda.osaka.jp +izumi.osaka.jp +izumiotsu.osaka.jp +izumisano.osaka.jp +kadoma.osaka.jp +kaizuka.osaka.jp +kanan.osaka.jp +kashiwara.osaka.jp +katano.osaka.jp +kawachinagano.osaka.jp +kishiwada.osaka.jp +kita.osaka.jp +kumatori.osaka.jp +matsubara.osaka.jp +minato.osaka.jp +minoh.osaka.jp +misaki.osaka.jp +moriguchi.osaka.jp +neyagawa.osaka.jp +nishi.osaka.jp +nose.osaka.jp +osakasayama.osaka.jp +sakai.osaka.jp +sayama.osaka.jp +sennan.osaka.jp +settsu.osaka.jp +shijonawate.osaka.jp +shimamoto.osaka.jp +suita.osaka.jp +tadaoka.osaka.jp +taishi.osaka.jp +tajiri.osaka.jp +takaishi.osaka.jp +takatsuki.osaka.jp +tondabayashi.osaka.jp +toyonaka.osaka.jp +toyono.osaka.jp +yao.osaka.jp +ariake.saga.jp +arita.saga.jp +fukudomi.saga.jp +genkai.saga.jp +hamatama.saga.jp +hizen.saga.jp +imari.saga.jp +kamimine.saga.jp +kanzaki.saga.jp +karatsu.saga.jp +kashima.saga.jp +kitagata.saga.jp +kitahata.saga.jp +kiyama.saga.jp +kouhoku.saga.jp +kyuragi.saga.jp +nishiarita.saga.jp +ogi.saga.jp +omachi.saga.jp +ouchi.saga.jp +saga.saga.jp +shiroishi.saga.jp +taku.saga.jp +tara.saga.jp +tosu.saga.jp +yoshinogari.saga.jp +arakawa.saitama.jp +asaka.saitama.jp +chichibu.saitama.jp +fujimi.saitama.jp +fujimino.saitama.jp +fukaya.saitama.jp +hanno.saitama.jp +hanyu.saitama.jp +hasuda.saitama.jp +hatogaya.saitama.jp +hatoyama.saitama.jp +hidaka.saitama.jp +higashichichibu.saitama.jp +higashimatsuyama.saitama.jp +honjo.saitama.jp +ina.saitama.jp +iruma.saitama.jp +iwatsuki.saitama.jp +kamiizumi.saitama.jp +kamikawa.saitama.jp +kamisato.saitama.jp +kasukabe.saitama.jp +kawagoe.saitama.jp +kawaguchi.saitama.jp +kawajima.saitama.jp +kazo.saitama.jp +kitamoto.saitama.jp +koshigaya.saitama.jp +kounosu.saitama.jp +kuki.saitama.jp +kumagaya.saitama.jp +matsubushi.saitama.jp +minano.saitama.jp +misato.saitama.jp +miyashiro.saitama.jp +miyoshi.saitama.jp +moroyama.saitama.jp +nagatoro.saitama.jp +namegawa.saitama.jp +niiza.saitama.jp +ogano.saitama.jp +ogawa.saitama.jp +ogose.saitama.jp +okegawa.saitama.jp +omiya.saitama.jp +otaki.saitama.jp +ranzan.saitama.jp +ryokami.saitama.jp +saitama.saitama.jp +sakado.saitama.jp +satte.saitama.jp +sayama.saitama.jp +shiki.saitama.jp +shiraoka.saitama.jp +soka.saitama.jp +sugito.saitama.jp +toda.saitama.jp +tokigawa.saitama.jp +tokorozawa.saitama.jp +tsurugashima.saitama.jp +urawa.saitama.jp +warabi.saitama.jp +yashio.saitama.jp +yokoze.saitama.jp +yono.saitama.jp +yorii.saitama.jp +yoshida.saitama.jp +yoshikawa.saitama.jp +yoshimi.saitama.jp +aisho.shiga.jp +gamo.shiga.jp +higashiomi.shiga.jp +hikone.shiga.jp +koka.shiga.jp +konan.shiga.jp +kosei.shiga.jp +koto.shiga.jp +kusatsu.shiga.jp +maibara.shiga.jp +moriyama.shiga.jp +nagahama.shiga.jp +nishiazai.shiga.jp +notogawa.shiga.jp +omihachiman.shiga.jp +otsu.shiga.jp +ritto.shiga.jp +ryuoh.shiga.jp +takashima.shiga.jp +takatsuki.shiga.jp +torahime.shiga.jp +toyosato.shiga.jp +yasu.shiga.jp +akagi.shimane.jp +ama.shimane.jp +gotsu.shimane.jp +hamada.shimane.jp +higashiizumo.shimane.jp +hikawa.shimane.jp +hikimi.shimane.jp +izumo.shimane.jp +kakinoki.shimane.jp +masuda.shimane.jp +matsue.shimane.jp +misato.shimane.jp +nishinoshima.shimane.jp +ohda.shimane.jp +okinoshima.shimane.jp +okuizumo.shimane.jp +shimane.shimane.jp +tamayu.shimane.jp +tsuwano.shimane.jp +unnan.shimane.jp +yakumo.shimane.jp +yasugi.shimane.jp +yatsuka.shimane.jp +arai.shizuoka.jp +atami.shizuoka.jp +fuji.shizuoka.jp +fujieda.shizuoka.jp +fujikawa.shizuoka.jp +fujinomiya.shizuoka.jp +fukuroi.shizuoka.jp +gotemba.shizuoka.jp +haibara.shizuoka.jp +hamamatsu.shizuoka.jp +higashiizu.shizuoka.jp +ito.shizuoka.jp +iwata.shizuoka.jp +izu.shizuoka.jp +izunokuni.shizuoka.jp +kakegawa.shizuoka.jp +kannami.shizuoka.jp +kawanehon.shizuoka.jp +kawazu.shizuoka.jp +kikugawa.shizuoka.jp +kosai.shizuoka.jp +makinohara.shizuoka.jp +matsuzaki.shizuoka.jp +minamiizu.shizuoka.jp +mishima.shizuoka.jp +morimachi.shizuoka.jp +nishiizu.shizuoka.jp +numazu.shizuoka.jp +omaezaki.shizuoka.jp +shimada.shizuoka.jp +shimizu.shizuoka.jp +shimoda.shizuoka.jp +shizuoka.shizuoka.jp +susono.shizuoka.jp +yaizu.shizuoka.jp +yoshida.shizuoka.jp +ashikaga.tochigi.jp +bato.tochigi.jp +haga.tochigi.jp +ichikai.tochigi.jp +iwafune.tochigi.jp +kaminokawa.tochigi.jp +kanuma.tochigi.jp +karasuyama.tochigi.jp +kuroiso.tochigi.jp +mashiko.tochigi.jp +mibu.tochigi.jp +moka.tochigi.jp +motegi.tochigi.jp +nasu.tochigi.jp +nasushiobara.tochigi.jp +nikko.tochigi.jp +nishikata.tochigi.jp +nogi.tochigi.jp +ohira.tochigi.jp +ohtawara.tochigi.jp +oyama.tochigi.jp +sakura.tochigi.jp +sano.tochigi.jp +shimotsuke.tochigi.jp +shioya.tochigi.jp +takanezawa.tochigi.jp +tochigi.tochigi.jp +tsuga.tochigi.jp +ujiie.tochigi.jp +utsunomiya.tochigi.jp +yaita.tochigi.jp +aizumi.tokushima.jp +anan.tokushima.jp +ichiba.tokushima.jp +itano.tokushima.jp +kainan.tokushima.jp +komatsushima.tokushima.jp +matsushige.tokushima.jp +mima.tokushima.jp +minami.tokushima.jp +miyoshi.tokushima.jp +mugi.tokushima.jp +nakagawa.tokushima.jp +naruto.tokushima.jp +sanagochi.tokushima.jp +shishikui.tokushima.jp +tokushima.tokushima.jp +wajiki.tokushima.jp +adachi.tokyo.jp +akiruno.tokyo.jp +akishima.tokyo.jp +aogashima.tokyo.jp +arakawa.tokyo.jp +bunkyo.tokyo.jp +chiyoda.tokyo.jp +chofu.tokyo.jp +chuo.tokyo.jp +edogawa.tokyo.jp +fuchu.tokyo.jp +fussa.tokyo.jp +hachijo.tokyo.jp +hachioji.tokyo.jp +hamura.tokyo.jp +higashikurume.tokyo.jp +higashimurayama.tokyo.jp +higashiyamato.tokyo.jp +hino.tokyo.jp +hinode.tokyo.jp +hinohara.tokyo.jp +inagi.tokyo.jp +itabashi.tokyo.jp +katsushika.tokyo.jp +kita.tokyo.jp +kiyose.tokyo.jp +kodaira.tokyo.jp +koganei.tokyo.jp +kokubunji.tokyo.jp +komae.tokyo.jp +koto.tokyo.jp +kouzushima.tokyo.jp +kunitachi.tokyo.jp +machida.tokyo.jp +meguro.tokyo.jp +minato.tokyo.jp +mitaka.tokyo.jp +mizuho.tokyo.jp +musashimurayama.tokyo.jp +musashino.tokyo.jp +nakano.tokyo.jp +nerima.tokyo.jp +ogasawara.tokyo.jp +okutama.tokyo.jp +ome.tokyo.jp +oshima.tokyo.jp +ota.tokyo.jp +setagaya.tokyo.jp +shibuya.tokyo.jp +shinagawa.tokyo.jp +shinjuku.tokyo.jp +suginami.tokyo.jp +sumida.tokyo.jp +tachikawa.tokyo.jp +taito.tokyo.jp +tama.tokyo.jp +toshima.tokyo.jp +chizu.tottori.jp +hino.tottori.jp +kawahara.tottori.jp +koge.tottori.jp +kotoura.tottori.jp +misasa.tottori.jp +nanbu.tottori.jp +nichinan.tottori.jp +sakaiminato.tottori.jp +tottori.tottori.jp +wakasa.tottori.jp +yazu.tottori.jp +yonago.tottori.jp +asahi.toyama.jp +fuchu.toyama.jp +fukumitsu.toyama.jp +funahashi.toyama.jp +himi.toyama.jp +imizu.toyama.jp +inami.toyama.jp +johana.toyama.jp +kamiichi.toyama.jp +kurobe.toyama.jp +nakaniikawa.toyama.jp +namerikawa.toyama.jp +nanto.toyama.jp +nyuzen.toyama.jp +oyabe.toyama.jp +taira.toyama.jp +takaoka.toyama.jp +tateyama.toyama.jp +toga.toyama.jp +tonami.toyama.jp +toyama.toyama.jp +unazuki.toyama.jp +uozu.toyama.jp +yamada.toyama.jp +arida.wakayama.jp +aridagawa.wakayama.jp +gobo.wakayama.jp +hashimoto.wakayama.jp +hidaka.wakayama.jp +hirogawa.wakayama.jp +inami.wakayama.jp +iwade.wakayama.jp +kainan.wakayama.jp +kamitonda.wakayama.jp +katsuragi.wakayama.jp +kimino.wakayama.jp +kinokawa.wakayama.jp +kitayama.wakayama.jp +koya.wakayama.jp +koza.wakayama.jp +kozagawa.wakayama.jp +kudoyama.wakayama.jp +kushimoto.wakayama.jp +mihama.wakayama.jp +misato.wakayama.jp +nachikatsuura.wakayama.jp +shingu.wakayama.jp +shirahama.wakayama.jp +taiji.wakayama.jp +tanabe.wakayama.jp +wakayama.wakayama.jp +yuasa.wakayama.jp +yura.wakayama.jp +asahi.yamagata.jp +funagata.yamagata.jp +higashine.yamagata.jp +iide.yamagata.jp +kahoku.yamagata.jp +kaminoyama.yamagata.jp +kaneyama.yamagata.jp +kawanishi.yamagata.jp +mamurogawa.yamagata.jp +mikawa.yamagata.jp +murayama.yamagata.jp +nagai.yamagata.jp +nakayama.yamagata.jp +nanyo.yamagata.jp +nishikawa.yamagata.jp +obanazawa.yamagata.jp +oe.yamagata.jp +oguni.yamagata.jp +ohkura.yamagata.jp +oishida.yamagata.jp +sagae.yamagata.jp +sakata.yamagata.jp +sakegawa.yamagata.jp +shinjo.yamagata.jp +shirataka.yamagata.jp +shonai.yamagata.jp +takahata.yamagata.jp +tendo.yamagata.jp +tozawa.yamagata.jp +tsuruoka.yamagata.jp +yamagata.yamagata.jp +yamanobe.yamagata.jp +yonezawa.yamagata.jp +yuza.yamagata.jp +abu.yamaguchi.jp +hagi.yamaguchi.jp +hikari.yamaguchi.jp +hofu.yamaguchi.jp +iwakuni.yamaguchi.jp +kudamatsu.yamaguchi.jp +mitou.yamaguchi.jp +nagato.yamaguchi.jp +oshima.yamaguchi.jp +shimonoseki.yamaguchi.jp +shunan.yamaguchi.jp +tabuse.yamaguchi.jp +tokuyama.yamaguchi.jp +toyota.yamaguchi.jp +ube.yamaguchi.jp +yuu.yamaguchi.jp +chuo.yamanashi.jp +doshi.yamanashi.jp +fuefuki.yamanashi.jp +fujikawa.yamanashi.jp +fujikawaguchiko.yamanashi.jp +fujiyoshida.yamanashi.jp +hayakawa.yamanashi.jp +hokuto.yamanashi.jp +ichikawamisato.yamanashi.jp +kai.yamanashi.jp +kofu.yamanashi.jp +koshu.yamanashi.jp +kosuge.yamanashi.jp +minami-alps.yamanashi.jp +minobu.yamanashi.jp +nakamichi.yamanashi.jp +nanbu.yamanashi.jp +narusawa.yamanashi.jp +nirasaki.yamanashi.jp +nishikatsura.yamanashi.jp +oshino.yamanashi.jp +otsuki.yamanashi.jp +showa.yamanashi.jp +tabayama.yamanashi.jp +tsuru.yamanashi.jp +uenohara.yamanashi.jp +yamanakako.yamanashi.jp +yamanashi.yamanashi.jp + +// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains +ke +ac.ke +co.ke +go.ke +info.ke +me.ke +mobi.ke +ne.ke +or.ke +sc.ke + +// kg : http://www.domain.kg/dmn_n.html +kg +org.kg +net.kg +com.kg +edu.kg +gov.kg +mil.kg + +// kh : http://www.mptc.gov.kh/dns_registration.htm +*.kh + +// ki : http://www.ki/dns/index.html +ki +edu.ki +biz.ki +net.ki +org.ki +gov.ki +info.ki +com.ki + +// km : https://en.wikipedia.org/wiki/.km +// http://www.domaine.km/documents/charte.doc +km +org.km +nom.km +gov.km +prd.km +tm.km +edu.km +mil.km +ass.km +com.km +// These are only mentioned as proposed suggestions at domaine.km, but +// https://en.wikipedia.org/wiki/.km says they're available for registration: +coop.km +asso.km +presse.km +medecin.km +notaires.km +pharmaciens.km +veterinaire.km +gouv.km + +// kn : https://en.wikipedia.org/wiki/.kn +// http://www.dot.kn/domainRules.html +kn +net.kn +org.kn +edu.kn +gov.kn + +// kp : http://www.kcce.kp/en_index.php +kp +com.kp +edu.kp +gov.kp +org.kp +rep.kp +tra.kp + +// kr : https://en.wikipedia.org/wiki/.kr +// see also: http://domain.nida.or.kr/eng/registration.jsp +kr +ac.kr +co.kr +es.kr +go.kr +hs.kr +kg.kr +mil.kr +ms.kr +ne.kr +or.kr +pe.kr +re.kr +sc.kr +// kr geographical names +busan.kr +chungbuk.kr +chungnam.kr +daegu.kr +daejeon.kr +gangwon.kr +gwangju.kr +gyeongbuk.kr +gyeonggi.kr +gyeongnam.kr +incheon.kr +jeju.kr +jeonbuk.kr +jeonnam.kr +seoul.kr +ulsan.kr + +// kw : https://www.nic.kw/policies/ +// Confirmed by registry +kw +com.kw +edu.kw +emb.kw +gov.kw +ind.kw +net.kw +org.kw + +// ky : http://www.icta.ky/da_ky_reg_dom.php +// Confirmed by registry 2008-06-17 +ky +edu.ky +gov.ky +com.ky +org.ky +net.ky + +// kz : https://en.wikipedia.org/wiki/.kz +// see also: http://www.nic.kz/rules/index.jsp +kz +org.kz +edu.kz +net.kz +gov.kz +mil.kz +com.kz + +// la : https://en.wikipedia.org/wiki/.la +// Submitted by registry +la +int.la +net.la +info.la +edu.la +gov.la +per.la +com.la +org.la + +// lb : https://en.wikipedia.org/wiki/.lb +// Submitted by registry +lb +com.lb +edu.lb +gov.lb +net.lb +org.lb + +// lc : https://en.wikipedia.org/wiki/.lc +// see also: http://www.nic.lc/rules.htm +lc +com.lc +net.lc +co.lc +org.lc +edu.lc +gov.lc + +// li : https://en.wikipedia.org/wiki/.li +li + +// lk : http://www.nic.lk/seclevpr.html +lk +gov.lk +sch.lk +net.lk +int.lk +com.lk +org.lk +edu.lk +ngo.lk +soc.lk +web.lk +ltd.lk +assn.lk +grp.lk +hotel.lk +ac.lk + +// lr : http://psg.com/dns/lr/lr.txt +// Submitted by registry +lr +com.lr +edu.lr +gov.lr +org.lr +net.lr + +// ls : http://www.nic.ls/ +// Confirmed by registry +ls +ac.ls +biz.ls +co.ls +edu.ls +gov.ls +info.ls +net.ls +org.ls +sc.ls + +// lt : https://en.wikipedia.org/wiki/.lt +lt +// gov.lt : http://www.gov.lt/index_en.php +gov.lt + +// lu : http://www.dns.lu/en/ +lu + +// lv : http://www.nic.lv/DNS/En/generic.php +lv +com.lv +edu.lv +gov.lv +org.lv +mil.lv +id.lv +net.lv +asn.lv +conf.lv + +// ly : http://www.nic.ly/regulations.php +ly +com.ly +net.ly +gov.ly +plc.ly +edu.ly +sch.ly +med.ly +org.ly +id.ly + +// ma : https://en.wikipedia.org/wiki/.ma +// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf +ma +co.ma +net.ma +gov.ma +org.ma +ac.ma +press.ma + +// mc : http://www.nic.mc/ +mc +tm.mc +asso.mc + +// md : https://en.wikipedia.org/wiki/.md +md + +// me : https://en.wikipedia.org/wiki/.me +me +co.me +net.me +org.me +edu.me +ac.me +gov.me +its.me +priv.me + +// mg : http://nic.mg/nicmg/?page_id=39 +mg +org.mg +nom.mg +gov.mg +prd.mg +tm.mg +edu.mg +mil.mg +com.mg +co.mg + +// mh : https://en.wikipedia.org/wiki/.mh +mh + +// mil : https://en.wikipedia.org/wiki/.mil +mil + +// mk : https://en.wikipedia.org/wiki/.mk +// see also: http://dns.marnet.net.mk/postapka.php +mk +com.mk +org.mk +net.mk +edu.mk +gov.mk +inf.mk +name.mk + +// ml : http://www.gobin.info/domainname/ml-template.doc +// see also: https://en.wikipedia.org/wiki/.ml +ml +com.ml +edu.ml +gouv.ml +gov.ml +net.ml +org.ml +presse.ml + +// mm : https://en.wikipedia.org/wiki/.mm +*.mm + +// mn : https://en.wikipedia.org/wiki/.mn +mn +gov.mn +edu.mn +org.mn + +// mo : http://www.monic.net.mo/ +mo +com.mo +net.mo +org.mo +edu.mo +gov.mo + +// mobi : https://en.wikipedia.org/wiki/.mobi +mobi + +// mp : http://www.dot.mp/ +// Confirmed by registry 2008-06-17 +mp + +// mq : https://en.wikipedia.org/wiki/.mq +mq + +// mr : https://en.wikipedia.org/wiki/.mr +mr +gov.mr + +// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf +ms +com.ms +edu.ms +gov.ms +net.ms +org.ms + +// mt : https://www.nic.org.mt/go/policy +// Submitted by registry +mt +com.mt +edu.mt +net.mt +org.mt + +// mu : https://en.wikipedia.org/wiki/.mu +mu +com.mu +net.mu +org.mu +gov.mu +ac.mu +co.mu +or.mu + +// museum : http://about.museum/naming/ +// http://index.museum/ +museum +academy.museum +agriculture.museum +air.museum +airguard.museum +alabama.museum +alaska.museum +amber.museum +ambulance.museum +american.museum +americana.museum +americanantiques.museum +americanart.museum +amsterdam.museum +and.museum +annefrank.museum +anthro.museum +anthropology.museum +antiques.museum +aquarium.museum +arboretum.museum +archaeological.museum +archaeology.museum +architecture.museum +art.museum +artanddesign.museum +artcenter.museum +artdeco.museum +arteducation.museum +artgallery.museum +arts.museum +artsandcrafts.museum +asmatart.museum +assassination.museum +assisi.museum +association.museum +astronomy.museum +atlanta.museum +austin.museum +australia.museum +automotive.museum +aviation.museum +axis.museum +badajoz.museum +baghdad.museum +bahn.museum +bale.museum +baltimore.museum +barcelona.museum +baseball.museum +basel.museum +baths.museum +bauern.museum +beauxarts.museum +beeldengeluid.museum +bellevue.museum +bergbau.museum +berkeley.museum +berlin.museum +bern.museum +bible.museum +bilbao.museum +bill.museum +birdart.museum +birthplace.museum +bonn.museum +boston.museum +botanical.museum +botanicalgarden.museum +botanicgarden.museum +botany.museum +brandywinevalley.museum +brasil.museum +bristol.museum +british.museum +britishcolumbia.museum +broadcast.museum +brunel.museum +brussel.museum +brussels.museum +bruxelles.museum +building.museum +burghof.museum +bus.museum +bushey.museum +cadaques.museum +california.museum +cambridge.museum +can.museum +canada.museum +capebreton.museum +carrier.museum +cartoonart.museum +casadelamoneda.museum +castle.museum +castres.museum +celtic.museum +center.museum +chattanooga.museum +cheltenham.museum +chesapeakebay.museum +chicago.museum +children.museum +childrens.museum +childrensgarden.museum +chiropractic.museum +chocolate.museum +christiansburg.museum +cincinnati.museum +cinema.museum +circus.museum +civilisation.museum +civilization.museum +civilwar.museum +clinton.museum +clock.museum +coal.museum +coastaldefence.museum +cody.museum +coldwar.museum +collection.museum +colonialwilliamsburg.museum +coloradoplateau.museum +columbia.museum +columbus.museum +communication.museum +communications.museum +community.museum +computer.museum +computerhistory.museum +comunicações.museum +contemporary.museum +contemporaryart.museum +convent.museum +copenhagen.museum +corporation.museum +correios-e-telecomunicações.museum +corvette.museum +costume.museum +countryestate.museum +county.museum +crafts.museum +cranbrook.museum +creation.museum +cultural.museum +culturalcenter.museum +culture.museum +cyber.museum +cymru.museum +dali.museum +dallas.museum +database.museum +ddr.museum +decorativearts.museum +delaware.museum +delmenhorst.museum +denmark.museum +depot.museum +design.museum +detroit.museum +dinosaur.museum +discovery.museum +dolls.museum +donostia.museum +durham.museum +eastafrica.museum +eastcoast.museum +education.museum +educational.museum +egyptian.museum +eisenbahn.museum +elburg.museum +elvendrell.museum +embroidery.museum +encyclopedic.museum +england.museum +entomology.museum +environment.museum +environmentalconservation.museum +epilepsy.museum +essex.museum +estate.museum +ethnology.museum +exeter.museum +exhibition.museum +family.museum +farm.museum +farmequipment.museum +farmers.museum +farmstead.museum +field.museum +figueres.museum +filatelia.museum +film.museum +fineart.museum +finearts.museum +finland.museum +flanders.museum +florida.museum +force.museum +fortmissoula.museum +fortworth.museum +foundation.museum +francaise.museum +frankfurt.museum +franziskaner.museum +freemasonry.museum +freiburg.museum +fribourg.museum +frog.museum +fundacio.museum +furniture.museum +gallery.museum +garden.museum +gateway.museum +geelvinck.museum +gemological.museum +geology.museum +georgia.museum +giessen.museum +glas.museum +glass.museum +gorge.museum +grandrapids.museum +graz.museum +guernsey.museum +halloffame.museum +hamburg.museum +handson.museum +harvestcelebration.museum +hawaii.museum +health.museum +heimatunduhren.museum +hellas.museum +helsinki.museum +hembygdsforbund.museum +heritage.museum +histoire.museum +historical.museum +historicalsociety.museum +historichouses.museum +historisch.museum +historisches.museum +history.museum +historyofscience.museum +horology.museum +house.museum +humanities.museum +illustration.museum +imageandsound.museum +indian.museum +indiana.museum +indianapolis.museum +indianmarket.museum +intelligence.museum +interactive.museum +iraq.museum +iron.museum +isleofman.museum +jamison.museum +jefferson.museum +jerusalem.museum +jewelry.museum +jewish.museum +jewishart.museum +jfk.museum +journalism.museum +judaica.museum +judygarland.museum +juedisches.museum +juif.museum +karate.museum +karikatur.museum +kids.museum +koebenhavn.museum +koeln.museum +kunst.museum +kunstsammlung.museum +kunstunddesign.museum +labor.museum +labour.museum +lajolla.museum +lancashire.museum +landes.museum +lans.museum +läns.museum +larsson.museum +lewismiller.museum +lincoln.museum +linz.museum +living.museum +livinghistory.museum +localhistory.museum +london.museum +losangeles.museum +louvre.museum +loyalist.museum +lucerne.museum +luxembourg.museum +luzern.museum +mad.museum +madrid.museum +mallorca.museum +manchester.museum +mansion.museum +mansions.museum +manx.museum +marburg.museum +maritime.museum +maritimo.museum +maryland.museum +marylhurst.museum +media.museum +medical.museum +medizinhistorisches.museum +meeres.museum +memorial.museum +mesaverde.museum +michigan.museum +midatlantic.museum +military.museum +mill.museum +miners.museum +mining.museum +minnesota.museum +missile.museum +missoula.museum +modern.museum +moma.museum +money.museum +monmouth.museum +monticello.museum +montreal.museum +moscow.museum +motorcycle.museum +muenchen.museum +muenster.museum +mulhouse.museum +muncie.museum +museet.museum +museumcenter.museum +museumvereniging.museum +music.museum +national.museum +nationalfirearms.museum +nationalheritage.museum +nativeamerican.museum +naturalhistory.museum +naturalhistorymuseum.museum +naturalsciences.museum +nature.museum +naturhistorisches.museum +natuurwetenschappen.museum +naumburg.museum +naval.museum +nebraska.museum +neues.museum +newhampshire.museum +newjersey.museum +newmexico.museum +newport.museum +newspaper.museum +newyork.museum +niepce.museum +norfolk.museum +north.museum +nrw.museum +nyc.museum +nyny.museum +oceanographic.museum +oceanographique.museum +omaha.museum +online.museum +ontario.museum +openair.museum +oregon.museum +oregontrail.museum +otago.museum +oxford.museum +pacific.museum +paderborn.museum +palace.museum +paleo.museum +palmsprings.museum +panama.museum +paris.museum +pasadena.museum +pharmacy.museum +philadelphia.museum +philadelphiaarea.museum +philately.museum +phoenix.museum +photography.museum +pilots.museum +pittsburgh.museum +planetarium.museum +plantation.museum +plants.museum +plaza.museum +portal.museum +portland.museum +portlligat.museum +posts-and-telecommunications.museum +preservation.museum +presidio.museum +press.museum +project.museum +public.museum +pubol.museum +quebec.museum +railroad.museum +railway.museum +research.museum +resistance.museum +riodejaneiro.museum +rochester.museum +rockart.museum +roma.museum +russia.museum +saintlouis.museum +salem.museum +salvadordali.museum +salzburg.museum +sandiego.museum +sanfrancisco.museum +santabarbara.museum +santacruz.museum +santafe.museum +saskatchewan.museum +satx.museum +savannahga.museum +schlesisches.museum +schoenbrunn.museum +schokoladen.museum +school.museum +schweiz.museum +science.museum +scienceandhistory.museum +scienceandindustry.museum +sciencecenter.museum +sciencecenters.museum +science-fiction.museum +sciencehistory.museum +sciences.museum +sciencesnaturelles.museum +scotland.museum +seaport.museum +settlement.museum +settlers.museum +shell.museum +sherbrooke.museum +sibenik.museum +silk.museum +ski.museum +skole.museum +society.museum +sologne.museum +soundandvision.museum +southcarolina.museum +southwest.museum +space.museum +spy.museum +square.museum +stadt.museum +stalbans.museum +starnberg.museum +state.museum +stateofdelaware.museum +station.museum +steam.museum +steiermark.museum +stjohn.museum +stockholm.museum +stpetersburg.museum +stuttgart.museum +suisse.museum +surgeonshall.museum +surrey.museum +svizzera.museum +sweden.museum +sydney.museum +tank.museum +tcm.museum +technology.museum +telekommunikation.museum +television.museum +texas.museum +textile.museum +theater.museum +time.museum +timekeeping.museum +topology.museum +torino.museum +touch.museum +town.museum +transport.museum +tree.museum +trolley.museum +trust.museum +trustee.museum +uhren.museum +ulm.museum +undersea.museum +university.museum +usa.museum +usantiques.museum +usarts.museum +uscountryestate.museum +usculture.museum +usdecorativearts.museum +usgarden.museum +ushistory.museum +ushuaia.museum +uslivinghistory.museum +utah.museum +uvic.museum +valley.museum +vantaa.museum +versailles.museum +viking.museum +village.museum +virginia.museum +virtual.museum +virtuel.museum +vlaanderen.museum +volkenkunde.museum +wales.museum +wallonie.museum +war.museum +washingtondc.museum +watchandclock.museum +watch-and-clock.museum +western.museum +westfalen.museum +whaling.museum +wildlife.museum +williamsburg.museum +windmill.museum +workshop.museum +york.museum +yorkshire.museum +yosemite.museum +youth.museum +zoological.museum +zoology.museum +ירושלים.museum +иком.museum + +// mv : https://en.wikipedia.org/wiki/.mv +// "mv" included because, contra Wikipedia, google.mv exists. +mv +aero.mv +biz.mv +com.mv +coop.mv +edu.mv +gov.mv +info.mv +int.mv +mil.mv +museum.mv +name.mv +net.mv +org.mv +pro.mv + +// mw : http://www.registrar.mw/ +mw +ac.mw +biz.mw +co.mw +com.mw +coop.mw +edu.mw +gov.mw +int.mw +museum.mw +net.mw +org.mw + +// mx : http://www.nic.mx/ +// Submitted by registry +mx +com.mx +org.mx +gob.mx +edu.mx +net.mx + +// my : http://www.mynic.net.my/ +my +com.my +net.my +org.my +gov.my +edu.my +mil.my +name.my + +// mz : http://www.uem.mz/ +// Submitted by registry +mz +ac.mz +adv.mz +co.mz +edu.mz +gov.mz +mil.mz +net.mz +org.mz + +// na : http://www.na-nic.com.na/ +// http://www.info.na/domain/ +na +info.na +pro.na +name.na +school.na +or.na +dr.na +us.na +mx.na +ca.na +in.na +cc.na +tv.na +ws.na +mobi.na +co.na +com.na +org.na + +// name : has 2nd-level tlds, but there's no list of them +name + +// nc : http://www.cctld.nc/ +nc +asso.nc +nom.nc + +// ne : https://en.wikipedia.org/wiki/.ne +ne + +// net : https://en.wikipedia.org/wiki/.net +net + +// nf : https://en.wikipedia.org/wiki/.nf +nf +com.nf +net.nf +per.nf +rec.nf +web.nf +arts.nf +firm.nf +info.nf +other.nf +store.nf + +// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds +ng +com.ng +edu.ng +gov.ng +i.ng +mil.ng +mobi.ng +name.ng +net.ng +org.ng +sch.ng + +// ni : http://www.nic.ni/ +ni +ac.ni +biz.ni +co.ni +com.ni +edu.ni +gob.ni +in.ni +info.ni +int.ni +mil.ni +net.ni +nom.ni +org.ni +web.ni + +// nl : https://en.wikipedia.org/wiki/.nl +// https://www.sidn.nl/ +// ccTLD for the Netherlands +nl + +// no : http://www.norid.no/regelverk/index.en.html +// The Norwegian registry has declined to notify us of updates. The web pages +// referenced below are the official source of the data. There is also an +// announce mailing list: +// https://postlister.uninett.no/sympa/info/norid-diskusjon +no +// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +fhs.no +vgs.no +fylkesbibl.no +folkebibl.no +museum.no +idrett.no +priv.no +// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +mil.no +stat.no +dep.no +kommune.no +herad.no +// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// counties +aa.no +ah.no +bu.no +fm.no +hl.no +hm.no +jan-mayen.no +mr.no +nl.no +nt.no +of.no +ol.no +oslo.no +rl.no +sf.no +st.no +svalbard.no +tm.no +tr.no +va.no +vf.no +// primary and lower secondary schools per county +gs.aa.no +gs.ah.no +gs.bu.no +gs.fm.no +gs.hl.no +gs.hm.no +gs.jan-mayen.no +gs.mr.no +gs.nl.no +gs.nt.no +gs.of.no +gs.ol.no +gs.oslo.no +gs.rl.no +gs.sf.no +gs.st.no +gs.svalbard.no +gs.tm.no +gs.tr.no +gs.va.no +gs.vf.no +// cities +akrehamn.no +åkrehamn.no +algard.no +ålgård.no +arna.no +brumunddal.no +bryne.no +bronnoysund.no +brønnøysund.no +drobak.no +drøbak.no +egersund.no +fetsund.no +floro.no +florø.no +fredrikstad.no +hokksund.no +honefoss.no +hønefoss.no +jessheim.no +jorpeland.no +jørpeland.no +kirkenes.no +kopervik.no +krokstadelva.no +langevag.no +langevåg.no +leirvik.no +mjondalen.no +mjøndalen.no +mo-i-rana.no +mosjoen.no +mosjøen.no +nesoddtangen.no +orkanger.no +osoyro.no +osøyro.no +raholt.no +råholt.no +sandnessjoen.no +sandnessjøen.no +skedsmokorset.no +slattum.no +spjelkavik.no +stathelle.no +stavern.no +stjordalshalsen.no +stjørdalshalsen.no +tananger.no +tranby.no +vossevangen.no +// communities +afjord.no +åfjord.no +agdenes.no +al.no +ål.no +alesund.no +ålesund.no +alstahaug.no +alta.no +áltá.no +alaheadju.no +álaheadju.no +alvdal.no +amli.no +åmli.no +amot.no +åmot.no +andebu.no +andoy.no +andøy.no +andasuolo.no +ardal.no +årdal.no +aremark.no +arendal.no +ås.no +aseral.no +åseral.no +asker.no +askim.no +askvoll.no +askoy.no +askøy.no +asnes.no +åsnes.no +audnedaln.no +aukra.no +aure.no +aurland.no +aurskog-holand.no +aurskog-høland.no +austevoll.no +austrheim.no +averoy.no +averøy.no +balestrand.no +ballangen.no +balat.no +bálát.no +balsfjord.no +bahccavuotna.no +báhccavuotna.no +bamble.no +bardu.no +beardu.no +beiarn.no +bajddar.no +bájddar.no +baidar.no +báidár.no +berg.no +bergen.no +berlevag.no +berlevåg.no +bearalvahki.no +bearalváhki.no +bindal.no +birkenes.no +bjarkoy.no +bjarkøy.no +bjerkreim.no +bjugn.no +bodo.no +bodø.no +badaddja.no +bådåddjå.no +budejju.no +bokn.no +bremanger.no +bronnoy.no +brønnøy.no +bygland.no +bykle.no +barum.no +bærum.no +bo.telemark.no +bø.telemark.no +bo.nordland.no +bø.nordland.no +bievat.no +bievát.no +bomlo.no +bømlo.no +batsfjord.no +båtsfjord.no +bahcavuotna.no +báhcavuotna.no +dovre.no +drammen.no +drangedal.no +dyroy.no +dyrøy.no +donna.no +dønna.no +eid.no +eidfjord.no +eidsberg.no +eidskog.no +eidsvoll.no +eigersund.no +elverum.no +enebakk.no +engerdal.no +etne.no +etnedal.no +evenes.no +evenassi.no +evenášši.no +evje-og-hornnes.no +farsund.no +fauske.no +fuossko.no +fuoisku.no +fedje.no +fet.no +finnoy.no +finnøy.no +fitjar.no +fjaler.no +fjell.no +flakstad.no +flatanger.no +flekkefjord.no +flesberg.no +flora.no +fla.no +flå.no +folldal.no +forsand.no +fosnes.no +frei.no +frogn.no +froland.no +frosta.no +frana.no +fræna.no +froya.no +frøya.no +fusa.no +fyresdal.no +forde.no +førde.no +gamvik.no +gangaviika.no +gáŋgaviika.no +gaular.no +gausdal.no +gildeskal.no +gildeskål.no +giske.no +gjemnes.no +gjerdrum.no +gjerstad.no +gjesdal.no +gjovik.no +gjøvik.no +gloppen.no +gol.no +gran.no +grane.no +granvin.no +gratangen.no +grimstad.no +grong.no +kraanghke.no +kråanghke.no +grue.no +gulen.no +hadsel.no +halden.no +halsa.no +hamar.no +hamaroy.no +habmer.no +hábmer.no +hapmir.no +hápmir.no +hammerfest.no +hammarfeasta.no +hámmárfeasta.no +haram.no +hareid.no +harstad.no +hasvik.no +aknoluokta.no +ákŋoluokta.no +hattfjelldal.no +aarborte.no +haugesund.no +hemne.no +hemnes.no +hemsedal.no +heroy.more-og-romsdal.no +herøy.møre-og-romsdal.no +heroy.nordland.no +herøy.nordland.no +hitra.no +hjartdal.no +hjelmeland.no +hobol.no +hobøl.no +hof.no +hol.no +hole.no +holmestrand.no +holtalen.no +holtålen.no +hornindal.no +horten.no +hurdal.no +hurum.no +hvaler.no +hyllestad.no +hagebostad.no +hægebostad.no +hoyanger.no +høyanger.no +hoylandet.no +høylandet.no +ha.no +hå.no +ibestad.no +inderoy.no +inderøy.no +iveland.no +jevnaker.no +jondal.no +jolster.no +jølster.no +karasjok.no +karasjohka.no +kárášjohka.no +karlsoy.no +galsa.no +gálsá.no +karmoy.no +karmøy.no +kautokeino.no +guovdageaidnu.no +klepp.no +klabu.no +klæbu.no +kongsberg.no +kongsvinger.no +kragero.no +kragerø.no +kristiansand.no +kristiansund.no +krodsherad.no +krødsherad.no +kvalsund.no +rahkkeravju.no +ráhkkerávju.no +kvam.no +kvinesdal.no +kvinnherad.no +kviteseid.no +kvitsoy.no +kvitsøy.no +kvafjord.no +kvæfjord.no +giehtavuoatna.no +kvanangen.no +kvænangen.no +navuotna.no +návuotna.no +kafjord.no +kåfjord.no +gaivuotna.no +gáivuotna.no +larvik.no +lavangen.no +lavagis.no +loabat.no +loabát.no +lebesby.no +davvesiida.no +leikanger.no +leirfjord.no +leka.no +leksvik.no +lenvik.no +leangaviika.no +leaŋgaviika.no +lesja.no +levanger.no +lier.no +lierne.no +lillehammer.no +lillesand.no +lindesnes.no +lindas.no +lindås.no +lom.no +loppa.no +lahppi.no +láhppi.no +lund.no +lunner.no +luroy.no +lurøy.no +luster.no +lyngdal.no +lyngen.no +ivgu.no +lardal.no +lerdal.no +lærdal.no +lodingen.no +lødingen.no +lorenskog.no +lørenskog.no +loten.no +løten.no +malvik.no +masoy.no +måsøy.no +muosat.no +muosát.no +mandal.no +marker.no +marnardal.no +masfjorden.no +meland.no +meldal.no +melhus.no +meloy.no +meløy.no +meraker.no +meråker.no +moareke.no +moåreke.no +midsund.no +midtre-gauldal.no +modalen.no +modum.no +molde.no +moskenes.no +moss.no +mosvik.no +malselv.no +målselv.no +malatvuopmi.no +málatvuopmi.no +namdalseid.no +aejrie.no +namsos.no +namsskogan.no +naamesjevuemie.no +nååmesjevuemie.no +laakesvuemie.no +nannestad.no +narvik.no +narviika.no +naustdal.no +nedre-eiker.no +nes.akershus.no +nes.buskerud.no +nesna.no +nesodden.no +nesseby.no +unjarga.no +unjárga.no +nesset.no +nissedal.no +nittedal.no +nord-aurdal.no +nord-fron.no +nord-odal.no +norddal.no +nordkapp.no +davvenjarga.no +davvenjárga.no +nordre-land.no +nordreisa.no +raisa.no +ráisa.no +nore-og-uvdal.no +notodden.no +naroy.no +nærøy.no +notteroy.no +nøtterøy.no +odda.no +oksnes.no +øksnes.no +oppdal.no +oppegard.no +oppegård.no +orkdal.no +orland.no +ørland.no +orskog.no +ørskog.no +orsta.no +ørsta.no +os.hedmark.no +os.hordaland.no +osen.no +osteroy.no +osterøy.no +ostre-toten.no +østre-toten.no +overhalla.no +ovre-eiker.no +øvre-eiker.no +oyer.no +øyer.no +oygarden.no +øygarden.no +oystre-slidre.no +øystre-slidre.no +porsanger.no +porsangu.no +porsáŋgu.no +porsgrunn.no +radoy.no +radøy.no +rakkestad.no +rana.no +ruovat.no +randaberg.no +rauma.no +rendalen.no +rennebu.no +rennesoy.no +rennesøy.no +rindal.no +ringebu.no +ringerike.no +ringsaker.no +rissa.no +risor.no +risør.no +roan.no +rollag.no +rygge.no +ralingen.no +rælingen.no +rodoy.no +rødøy.no +romskog.no +rømskog.no +roros.no +røros.no +rost.no +røst.no +royken.no +røyken.no +royrvik.no +røyrvik.no +rade.no +råde.no +salangen.no +siellak.no +saltdal.no +salat.no +sálát.no +sálat.no +samnanger.no +sande.more-og-romsdal.no +sande.møre-og-romsdal.no +sande.vestfold.no +sandefjord.no +sandnes.no +sandoy.no +sandøy.no +sarpsborg.no +sauda.no +sauherad.no +sel.no +selbu.no +selje.no +seljord.no +sigdal.no +siljan.no +sirdal.no +skaun.no +skedsmo.no +ski.no +skien.no +skiptvet.no +skjervoy.no +skjervøy.no +skierva.no +skiervá.no +skjak.no +skjåk.no +skodje.no +skanland.no +skånland.no +skanit.no +skánit.no +smola.no +smøla.no +snillfjord.no +snasa.no +snåsa.no +snoasa.no +snaase.no +snåase.no +sogndal.no +sokndal.no +sola.no +solund.no +songdalen.no +sortland.no +spydeberg.no +stange.no +stavanger.no +steigen.no +steinkjer.no +stjordal.no +stjørdal.no +stokke.no +stor-elvdal.no +stord.no +stordal.no +storfjord.no +omasvuotna.no +strand.no +stranda.no +stryn.no +sula.no +suldal.no +sund.no +sunndal.no +surnadal.no +sveio.no +svelvik.no +sykkylven.no +sogne.no +søgne.no +somna.no +sømna.no +sondre-land.no +søndre-land.no +sor-aurdal.no +sør-aurdal.no +sor-fron.no +sør-fron.no +sor-odal.no +sør-odal.no +sor-varanger.no +sør-varanger.no +matta-varjjat.no +mátta-várjjat.no +sorfold.no +sørfold.no +sorreisa.no +sørreisa.no +sorum.no +sørum.no +tana.no +deatnu.no +time.no +tingvoll.no +tinn.no +tjeldsund.no +dielddanuorri.no +tjome.no +tjøme.no +tokke.no +tolga.no +torsken.no +tranoy.no +tranøy.no +tromso.no +tromsø.no +tromsa.no +romsa.no +trondheim.no +troandin.no +trysil.no +trana.no +træna.no +trogstad.no +trøgstad.no +tvedestrand.no +tydal.no +tynset.no +tysfjord.no +divtasvuodna.no +divttasvuotna.no +tysnes.no +tysvar.no +tysvær.no +tonsberg.no +tønsberg.no +ullensaker.no +ullensvang.no +ulvik.no +utsira.no +vadso.no +vadsø.no +cahcesuolo.no +čáhcesuolo.no +vaksdal.no +valle.no +vang.no +vanylven.no +vardo.no +vardø.no +varggat.no +várggát.no +vefsn.no +vaapste.no +vega.no +vegarshei.no +vegårshei.no +vennesla.no +verdal.no +verran.no +vestby.no +vestnes.no +vestre-slidre.no +vestre-toten.no +vestvagoy.no +vestvågøy.no +vevelstad.no +vik.no +vikna.no +vindafjord.no +volda.no +voss.no +varoy.no +værøy.no +vagan.no +vågan.no +voagat.no +vagsoy.no +vågsøy.no +vaga.no +vågå.no +valer.ostfold.no +våler.østfold.no +valer.hedmark.no +våler.hedmark.no + +// np : http://www.mos.com.np/register.html +*.np + +// nr : http://cenpac.net.nr/dns/index.html +// Submitted by registry +nr +biz.nr +info.nr +gov.nr +edu.nr +org.nr +net.nr +com.nr + +// nu : https://en.wikipedia.org/wiki/.nu +nu + +// nz : https://en.wikipedia.org/wiki/.nz +// Submitted by registry +nz +ac.nz +co.nz +cri.nz +geek.nz +gen.nz +govt.nz +health.nz +iwi.nz +kiwi.nz +maori.nz +mil.nz +māori.nz +net.nz +org.nz +parliament.nz +school.nz + +// om : https://en.wikipedia.org/wiki/.om +om +co.om +com.om +edu.om +gov.om +med.om +museum.om +net.om +org.om +pro.om + +// onion : https://tools.ietf.org/html/rfc7686 +onion + +// org : https://en.wikipedia.org/wiki/.org +org + +// pa : http://www.nic.pa/ +// Some additional second level "domains" resolve directly as hostnames, such as +// pannet.pa, so we add a rule for "pa". +pa +ac.pa +gob.pa +com.pa +org.pa +sld.pa +edu.pa +net.pa +ing.pa +abo.pa +med.pa +nom.pa + +// pe : https://www.nic.pe/InformeFinalComision.pdf +pe +edu.pe +gob.pe +nom.pe +mil.pe +org.pe +com.pe +net.pe + +// pf : http://www.gobin.info/domainname/formulaire-pf.pdf +pf +com.pf +org.pf +edu.pf + +// pg : https://en.wikipedia.org/wiki/.pg +*.pg + +// ph : http://www.domains.ph/FAQ2.asp +// Submitted by registry +ph +com.ph +net.ph +org.ph +gov.ph +edu.ph +ngo.ph +mil.ph +i.ph + +// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK +pk +com.pk +net.pk +edu.pk +org.pk +fam.pk +biz.pk +web.pk +gov.pk +gob.pk +gok.pk +gon.pk +gop.pk +gos.pk +info.pk + +// pl http://www.dns.pl/english/index.html +// Submitted by registry +pl +com.pl +net.pl +org.pl +// pl functional domains (http://www.dns.pl/english/index.html) +aid.pl +agro.pl +atm.pl +auto.pl +biz.pl +edu.pl +gmina.pl +gsm.pl +info.pl +mail.pl +miasta.pl +media.pl +mil.pl +nieruchomosci.pl +nom.pl +pc.pl +powiat.pl +priv.pl +realestate.pl +rel.pl +sex.pl +shop.pl +sklep.pl +sos.pl +szkola.pl +targi.pl +tm.pl +tourism.pl +travel.pl +turystyka.pl +// Government domains +gov.pl +ap.gov.pl +ic.gov.pl +is.gov.pl +us.gov.pl +kmpsp.gov.pl +kppsp.gov.pl +kwpsp.gov.pl +psp.gov.pl +wskr.gov.pl +kwp.gov.pl +mw.gov.pl +ug.gov.pl +um.gov.pl +umig.gov.pl +ugim.gov.pl +upow.gov.pl +uw.gov.pl +starostwo.gov.pl +pa.gov.pl +po.gov.pl +psse.gov.pl +pup.gov.pl +rzgw.gov.pl +sa.gov.pl +so.gov.pl +sr.gov.pl +wsa.gov.pl +sko.gov.pl +uzs.gov.pl +wiih.gov.pl +winb.gov.pl +pinb.gov.pl +wios.gov.pl +witd.gov.pl +wzmiuw.gov.pl +piw.gov.pl +wiw.gov.pl +griw.gov.pl +wif.gov.pl +oum.gov.pl +sdn.gov.pl +zp.gov.pl +uppo.gov.pl +mup.gov.pl +wuoz.gov.pl +konsulat.gov.pl +oirm.gov.pl +// pl regional domains (http://www.dns.pl/english/index.html) +augustow.pl +babia-gora.pl +bedzin.pl +beskidy.pl +bialowieza.pl +bialystok.pl +bielawa.pl +bieszczady.pl +boleslawiec.pl +bydgoszcz.pl +bytom.pl +cieszyn.pl +czeladz.pl +czest.pl +dlugoleka.pl +elblag.pl +elk.pl +glogow.pl +gniezno.pl +gorlice.pl +grajewo.pl +ilawa.pl +jaworzno.pl +jelenia-gora.pl +jgora.pl +kalisz.pl +kazimierz-dolny.pl +karpacz.pl +kartuzy.pl +kaszuby.pl +katowice.pl +kepno.pl +ketrzyn.pl +klodzko.pl +kobierzyce.pl +kolobrzeg.pl +konin.pl +konskowola.pl +kutno.pl +lapy.pl +lebork.pl +legnica.pl +lezajsk.pl +limanowa.pl +lomza.pl +lowicz.pl +lubin.pl +lukow.pl +malbork.pl +malopolska.pl +mazowsze.pl +mazury.pl +mielec.pl +mielno.pl +mragowo.pl +naklo.pl +nowaruda.pl +nysa.pl +olawa.pl +olecko.pl +olkusz.pl +olsztyn.pl +opoczno.pl +opole.pl +ostroda.pl +ostroleka.pl +ostrowiec.pl +ostrowwlkp.pl +pila.pl +pisz.pl +podhale.pl +podlasie.pl +polkowice.pl +pomorze.pl +pomorskie.pl +prochowice.pl +pruszkow.pl +przeworsk.pl +pulawy.pl +radom.pl +rawa-maz.pl +rybnik.pl +rzeszow.pl +sanok.pl +sejny.pl +slask.pl +slupsk.pl +sosnowiec.pl +stalowa-wola.pl +skoczow.pl +starachowice.pl +stargard.pl +suwalki.pl +swidnica.pl +swiebodzin.pl +swinoujscie.pl +szczecin.pl +szczytno.pl +tarnobrzeg.pl +tgory.pl +turek.pl +tychy.pl +ustka.pl +walbrzych.pl +warmia.pl +warszawa.pl +waw.pl +wegrow.pl +wielun.pl +wlocl.pl +wloclawek.pl +wodzislaw.pl +wolomin.pl +wroclaw.pl +zachpomor.pl +zagan.pl +zarow.pl +zgora.pl +zgorzelec.pl + +// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +pm + +// pn : http://www.government.pn/PnRegistry/policies.htm +pn +gov.pn +co.pn +org.pn +edu.pn +net.pn + +// post : https://en.wikipedia.org/wiki/.post +post + +// pr : http://www.nic.pr/index.asp?f=1 +pr +com.pr +net.pr +org.pr +gov.pr +edu.pr +isla.pr +pro.pr +biz.pr +info.pr +name.pr +// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr +est.pr +prof.pr +ac.pr + +// pro : http://registry.pro/get-pro +pro +aaa.pro +aca.pro +acct.pro +avocat.pro +bar.pro +cpa.pro +eng.pro +jur.pro +law.pro +med.pro +recht.pro + +// ps : https://en.wikipedia.org/wiki/.ps +// http://www.nic.ps/registration/policy.html#reg +ps +edu.ps +gov.ps +sec.ps +plo.ps +com.ps +org.ps +net.ps + +// pt : http://online.dns.pt/dns/start_dns +pt +net.pt +gov.pt +org.pt +edu.pt +int.pt +publ.pt +com.pt +nome.pt + +// pw : https://en.wikipedia.org/wiki/.pw +pw +co.pw +ne.pw +or.pw +ed.pw +go.pw +belau.pw + +// py : http://www.nic.py/pautas.html#seccion_9 +// Submitted by registry +py +com.py +coop.py +edu.py +gov.py +mil.py +net.py +org.py + +// qa : http://domains.qa/en/ +qa +com.qa +edu.qa +gov.qa +mil.qa +name.qa +net.qa +org.qa +sch.qa + +// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs +re +asso.re +com.re +nom.re + +// ro : http://www.rotld.ro/ +ro +arts.ro +com.ro +firm.ro +info.ro +nom.ro +nt.ro +org.ro +rec.ro +store.ro +tm.ro +www.ro + +// rs : https://www.rnids.rs/en/domains/national-domains +rs +ac.rs +co.rs +edu.rs +gov.rs +in.rs +org.rs + +// ru : https://cctld.ru/en/domains/domens_ru/reserved/ +ru +ac.ru +edu.ru +gov.ru +int.ru +mil.ru +test.ru + +// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf +rw +ac.rw +co.rw +coop.rw +gov.rw +mil.rw +net.rw +org.rw + +// sa : http://www.nic.net.sa/ +sa +com.sa +net.sa +org.sa +gov.sa +med.sa +pub.sa +edu.sa +sch.sa + +// sb : http://www.sbnic.net.sb/ +// Submitted by registry +sb +com.sb +edu.sb +gov.sb +net.sb +org.sb + +// sc : http://www.nic.sc/ +sc +com.sc +gov.sc +net.sc +org.sc +edu.sc + +// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// Submitted by registry +sd +com.sd +net.sd +org.sd +edu.sd +med.sd +tv.sd +gov.sd +info.sd + +// se : https://en.wikipedia.org/wiki/.se +// Submitted by registry +se +a.se +ac.se +b.se +bd.se +brand.se +c.se +d.se +e.se +f.se +fh.se +fhsk.se +fhv.se +g.se +h.se +i.se +k.se +komforb.se +kommunalforbund.se +komvux.se +l.se +lanbib.se +m.se +n.se +naturbruksgymn.se +o.se +org.se +p.se +parti.se +pp.se +press.se +r.se +s.se +t.se +tm.se +u.se +w.se +x.se +y.se +z.se + +// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines +sg +com.sg +net.sg +org.sg +gov.sg +edu.sg +per.sg + +// sh : http://www.nic.sh/registrar.html +sh +com.sh +net.sh +gov.sh +org.sh +mil.sh + +// si : https://en.wikipedia.org/wiki/.si +si + +// sj : No registrations at this time. +// Submitted by registry +sj + +// sk : https://en.wikipedia.org/wiki/.sk +// list of 2nd level domains ? +sk + +// sl : http://www.nic.sl +// Submitted by registry +sl +com.sl +net.sl +edu.sl +gov.sl +org.sl + +// sm : https://en.wikipedia.org/wiki/.sm +sm + +// sn : https://en.wikipedia.org/wiki/.sn +sn +art.sn +com.sn +edu.sn +gouv.sn +org.sn +perso.sn +univ.sn + +// so : http://sonic.so/policies/ +so +com.so +edu.so +gov.so +me.so +net.so +org.so + +// sr : https://en.wikipedia.org/wiki/.sr +sr + +// ss : https://registry.nic.ss/ +// Submitted by registry +ss +biz.ss +com.ss +edu.ss +gov.ss +net.ss +org.ss + +// st : http://www.nic.st/html/policyrules/ +st +co.st +com.st +consulado.st +edu.st +embaixada.st +gov.st +mil.st +net.st +org.st +principe.st +saotome.st +store.st + +// su : https://en.wikipedia.org/wiki/.su +su + +// sv : http://www.svnet.org.sv/niveldos.pdf +sv +com.sv +edu.sv +gob.sv +org.sv +red.sv + +// sx : https://en.wikipedia.org/wiki/.sx +// Submitted by registry +sx +gov.sx + +// sy : https://en.wikipedia.org/wiki/.sy +// see also: http://www.gobin.info/domainname/sy.doc +sy +edu.sy +gov.sy +net.sy +mil.sy +com.sy +org.sy + +// sz : https://en.wikipedia.org/wiki/.sz +// http://www.sispa.org.sz/ +sz +co.sz +ac.sz +org.sz + +// tc : https://en.wikipedia.org/wiki/.tc +tc + +// td : https://en.wikipedia.org/wiki/.td +td + +// tel: https://en.wikipedia.org/wiki/.tel +// http://www.telnic.org/ +tel + +// tf : https://en.wikipedia.org/wiki/.tf +tf + +// tg : https://en.wikipedia.org/wiki/.tg +// http://www.nic.tg/ +tg + +// th : https://en.wikipedia.org/wiki/.th +// Submitted by registry +th +ac.th +co.th +go.th +in.th +mi.th +net.th +or.th + +// tj : http://www.nic.tj/policy.html +tj +ac.tj +biz.tj +co.tj +com.tj +edu.tj +go.tj +gov.tj +int.tj +mil.tj +name.tj +net.tj +nic.tj +org.tj +test.tj +web.tj + +// tk : https://en.wikipedia.org/wiki/.tk +tk + +// tl : https://en.wikipedia.org/wiki/.tl +tl +gov.tl + +// tm : http://www.nic.tm/local.html +tm +com.tm +co.tm +org.tm +net.tm +nom.tm +gov.tm +mil.tm +edu.tm + +// tn : https://en.wikipedia.org/wiki/.tn +// http://whois.ati.tn/ +tn +com.tn +ens.tn +fin.tn +gov.tn +ind.tn +intl.tn +nat.tn +net.tn +org.tn +info.tn +perso.tn +tourism.tn +edunet.tn +rnrt.tn +rns.tn +rnu.tn +mincom.tn +agrinet.tn +defense.tn +turen.tn + +// to : https://en.wikipedia.org/wiki/.to +// Submitted by registry +to +com.to +gov.to +net.to +org.to +edu.to +mil.to + +// tr : https://nic.tr/ +// https://nic.tr/forms/eng/policies.pdf +// https://nic.tr/index.php?USRACTN=PRICELST +tr +av.tr +bbs.tr +bel.tr +biz.tr +com.tr +dr.tr +edu.tr +gen.tr +gov.tr +info.tr +mil.tr +k12.tr +kep.tr +name.tr +net.tr +org.tr +pol.tr +tel.tr +tsk.tr +tv.tr +web.tr +// Used by Northern Cyprus +nc.tr +// Used by government agencies of Northern Cyprus +gov.nc.tr + +// tt : http://www.nic.tt/ +tt +co.tt +com.tt +org.tt +net.tt +biz.tt +info.tt +pro.tt +int.tt +coop.tt +jobs.tt +mobi.tt +travel.tt +museum.tt +aero.tt +name.tt +gov.tt +edu.tt + +// tv : https://en.wikipedia.org/wiki/.tv +// Not listing any 2LDs as reserved since none seem to exist in practice, +// Wikipedia notwithstanding. +tv + +// tw : https://en.wikipedia.org/wiki/.tw +tw +edu.tw +gov.tw +mil.tw +com.tw +net.tw +org.tw +idv.tw +game.tw +ebiz.tw +club.tw +網路.tw +組織.tw +商業.tw + +// tz : http://www.tznic.or.tz/index.php/domains +// Submitted by registry +tz +ac.tz +co.tz +go.tz +hotel.tz +info.tz +me.tz +mil.tz +mobi.tz +ne.tz +or.tz +sc.tz +tv.tz + +// ua : https://hostmaster.ua/policy/?ua +// Submitted by registry +ua +// ua 2LD +com.ua +edu.ua +gov.ua +in.ua +net.ua +org.ua +// ua geographic names +// https://hostmaster.ua/2ld/ +cherkassy.ua +cherkasy.ua +chernigov.ua +chernihiv.ua +chernivtsi.ua +chernovtsy.ua +ck.ua +cn.ua +cr.ua +crimea.ua +cv.ua +dn.ua +dnepropetrovsk.ua +dnipropetrovsk.ua +dominic.ua +donetsk.ua +dp.ua +if.ua +ivano-frankivsk.ua +kh.ua +kharkiv.ua +kharkov.ua +kherson.ua +khmelnitskiy.ua +khmelnytskyi.ua +kiev.ua +kirovograd.ua +km.ua +kr.ua +krym.ua +ks.ua +kv.ua +kyiv.ua +lg.ua +lt.ua +lugansk.ua +lutsk.ua +lv.ua +lviv.ua +mk.ua +mykolaiv.ua +nikolaev.ua +od.ua +odesa.ua +odessa.ua +pl.ua +poltava.ua +rivne.ua +rovno.ua +rv.ua +sb.ua +sebastopol.ua +sevastopol.ua +sm.ua +sumy.ua +te.ua +ternopil.ua +uz.ua +uzhgorod.ua +vinnica.ua +vinnytsia.ua +vn.ua +volyn.ua +yalta.ua +zaporizhzhe.ua +zaporizhzhia.ua +zhitomir.ua +zhytomyr.ua +zp.ua +zt.ua + +// ug : https://www.registry.co.ug/ +ug +co.ug +or.ug +ac.ug +sc.ug +go.ug +ne.ug +com.ug +org.ug + +// uk : https://en.wikipedia.org/wiki/.uk +// Submitted by registry +uk +ac.uk +co.uk +gov.uk +ltd.uk +me.uk +net.uk +nhs.uk +org.uk +plc.uk +police.uk +*.sch.uk + +// us : https://en.wikipedia.org/wiki/.us +us +dni.us +fed.us +isa.us +kids.us +nsn.us +// us geographic names +ak.us +al.us +ar.us +as.us +az.us +ca.us +co.us +ct.us +dc.us +de.us +fl.us +ga.us +gu.us +hi.us +ia.us +id.us +il.us +in.us +ks.us +ky.us +la.us +ma.us +md.us +me.us +mi.us +mn.us +mo.us +ms.us +mt.us +nc.us +nd.us +ne.us +nh.us +nj.us +nm.us +nv.us +ny.us +oh.us +ok.us +or.us +pa.us +pr.us +ri.us +sc.us +sd.us +tn.us +tx.us +ut.us +vi.us +vt.us +va.us +wa.us +wi.us +wv.us +wy.us +// The registrar notes several more specific domains available in each state, +// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat +// haphazard; in some states these domains resolve as addresses, while in others +// only subdomains are available, or even nothing at all. We include the +// most common ones where it's clear that different sites are different +// entities. +k12.ak.us +k12.al.us +k12.ar.us +k12.as.us +k12.az.us +k12.ca.us +k12.co.us +k12.ct.us +k12.dc.us +k12.de.us +k12.fl.us +k12.ga.us +k12.gu.us +// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login +k12.ia.us +k12.id.us +k12.il.us +k12.in.us +k12.ks.us +k12.ky.us +k12.la.us +k12.ma.us +k12.md.us +k12.me.us +k12.mi.us +k12.mn.us +k12.mo.us +k12.ms.us +k12.mt.us +k12.nc.us +// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso +k12.ne.us +k12.nh.us +k12.nj.us +k12.nm.us +k12.nv.us +k12.ny.us +k12.oh.us +k12.ok.us +k12.or.us +k12.pa.us +k12.pr.us +k12.ri.us +k12.sc.us +// k12.sd.us Bug 934131 - Removed at request of James Booze +k12.tn.us +k12.tx.us +k12.ut.us +k12.vi.us +k12.vt.us +k12.va.us +k12.wa.us +k12.wi.us +// k12.wv.us Bug 947705 - Removed at request of Verne Britton +k12.wy.us +cc.ak.us +cc.al.us +cc.ar.us +cc.as.us +cc.az.us +cc.ca.us +cc.co.us +cc.ct.us +cc.dc.us +cc.de.us +cc.fl.us +cc.ga.us +cc.gu.us +cc.hi.us +cc.ia.us +cc.id.us +cc.il.us +cc.in.us +cc.ks.us +cc.ky.us +cc.la.us +cc.ma.us +cc.md.us +cc.me.us +cc.mi.us +cc.mn.us +cc.mo.us +cc.ms.us +cc.mt.us +cc.nc.us +cc.nd.us +cc.ne.us +cc.nh.us +cc.nj.us +cc.nm.us +cc.nv.us +cc.ny.us +cc.oh.us +cc.ok.us +cc.or.us +cc.pa.us +cc.pr.us +cc.ri.us +cc.sc.us +cc.sd.us +cc.tn.us +cc.tx.us +cc.ut.us +cc.vi.us +cc.vt.us +cc.va.us +cc.wa.us +cc.wi.us +cc.wv.us +cc.wy.us +lib.ak.us +lib.al.us +lib.ar.us +lib.as.us +lib.az.us +lib.ca.us +lib.co.us +lib.ct.us +lib.dc.us +// lib.de.us Issue #243 - Moved to Private section at request of Ed Moore +lib.fl.us +lib.ga.us +lib.gu.us +lib.hi.us +lib.ia.us +lib.id.us +lib.il.us +lib.in.us +lib.ks.us +lib.ky.us +lib.la.us +lib.ma.us +lib.md.us +lib.me.us +lib.mi.us +lib.mn.us +lib.mo.us +lib.ms.us +lib.mt.us +lib.nc.us +lib.nd.us +lib.ne.us +lib.nh.us +lib.nj.us +lib.nm.us +lib.nv.us +lib.ny.us +lib.oh.us +lib.ok.us +lib.or.us +lib.pa.us +lib.pr.us +lib.ri.us +lib.sc.us +lib.sd.us +lib.tn.us +lib.tx.us +lib.ut.us +lib.vi.us +lib.vt.us +lib.va.us +lib.wa.us +lib.wi.us +// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold +lib.wy.us +// k12.ma.us contains school districts in Massachusetts. The 4LDs are +// managed independently except for private (PVT), charter (CHTR) and +// parochial (PAROCH) schools. Those are delegated directly to the +// 5LD operators. +pvt.k12.ma.us +chtr.k12.ma.us +paroch.k12.ma.us +// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following +// see also: http://domreg.merit.edu +// see also: whois -h whois.domreg.merit.edu help +ann-arbor.mi.us +cog.mi.us +dst.mi.us +eaton.mi.us +gen.mi.us +mus.mi.us +tec.mi.us +washtenaw.mi.us + +// uy : http://www.nic.org.uy/ +uy +com.uy +edu.uy +gub.uy +mil.uy +net.uy +org.uy + +// uz : http://www.reg.uz/ +uz +co.uz +com.uz +net.uz +org.uz + +// va : https://en.wikipedia.org/wiki/.va +va + +// vc : https://en.wikipedia.org/wiki/.vc +// Submitted by registry +vc +com.vc +net.vc +org.vc +gov.vc +mil.vc +edu.vc + +// ve : https://registro.nic.ve/ +// Submitted by registry +ve +arts.ve +co.ve +com.ve +e12.ve +edu.ve +firm.ve +gob.ve +gov.ve +info.ve +int.ve +mil.ve +net.ve +org.ve +rec.ve +store.ve +tec.ve +web.ve + +// vg : https://en.wikipedia.org/wiki/.vg +vg + +// vi : http://www.nic.vi/newdomainform.htm +// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other +// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they +// are available for registration (which they do not seem to be). +vi +co.vi +com.vi +k12.vi +net.vi +org.vi + +// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp +vn +com.vn +net.vn +org.vn +edu.vn +gov.vn +int.vn +ac.vn +biz.vn +info.vn +name.vn +pro.vn +health.vn + +// vu : https://en.wikipedia.org/wiki/.vu +// http://www.vunic.vu/ +vu +com.vu +edu.vu +net.vu +org.vu + +// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +wf + +// ws : https://en.wikipedia.org/wiki/.ws +// http://samoanic.ws/index.dhtml +ws +com.ws +net.ws +org.ws +gov.ws +edu.ws + +// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +yt + +// IDN ccTLDs +// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then +// U-label, and follow this format: +// // A-Label ("", [, variant info]) : +// // [sponsoring org] +// U-Label + +// xn--mgbaam7a8h ("Emerat", Arabic) : AE +// http://nic.ae/english/arabicdomain/rules.jsp +امارات + +// xn--y9a3aq ("hye", Armenian) : AM +// ISOC AM (operated by .am Registry) +հայ + +// xn--54b7fta0cc ("Bangla", Bangla) : BD +বাংলা + +// xn--90ae ("bg", Bulgarian) : BG +бг + +// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY +// Operated by .by registry +бел + +// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中国 + +// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中國 + +// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ +الجزائر + +// xn--wgbh1c ("Egypt/Masr", Arabic) : EG +// http://www.dotmasr.eg/ +مصر + +// xn--e1a4c ("eu", Cyrillic) : EU +ею + +// xn--mgbah1a3hjkrd ("Mauritania", Arabic) : MR +موريتانيا + +// xn--node ("ge", Georgian Mkhedruli) : GE +გე + +// xn--qxam ("el", Greek) : GR +// Hellenic Ministry of Infrastructure, Transport, and Networks +ελ + +// xn--j6w193g ("Hong Kong", Chinese) : HK +// https://www.hkirc.hk +// Submitted by registry +// https://www.hkirc.hk/content.jsp?id=30#!/34 +香港 +公司.香港 +教育.香港 +政府.香港 +個人.香港 +網絡.香港 +組織.香港 + +// xn--2scrj9c ("Bharat", Kannada) : IN +// India +ಭಾರತ + +// xn--3hcrj9c ("Bharat", Oriya) : IN +// India +ଭାରତ + +// xn--45br5cyl ("Bharatam", Assamese) : IN +// India +ভাৰত + +// xn--h2breg3eve ("Bharatam", Sanskrit) : IN +// India +भारतम् + +// xn--h2brj9c8c ("Bharot", Santali) : IN +// India +भारोत + +// xn--mgbgu82a ("Bharat", Sindhi) : IN +// India +ڀارت + +// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN +// India +ഭാരതം + +// xn--h2brj9c ("Bharat", Devanagari) : IN +// India +भारत + +// xn--mgbbh1a ("Bharat", Kashmiri) : IN +// India +بارت + +// xn--mgbbh1a71e ("Bharat", Arabic) : IN +// India +بھارت + +// xn--fpcrj9c3d ("Bharat", Telugu) : IN +// India +భారత్ + +// xn--gecrj9c ("Bharat", Gujarati) : IN +// India +ભારત + +// xn--s9brj9c ("Bharat", Gurmukhi) : IN +// India +ਭਾਰਤ + +// xn--45brj9c ("Bharat", Bengali) : IN +// India +ভারত + +// xn--xkc2dl3a5ee0h ("India", Tamil) : IN +// India +இந்தியா + +// xn--mgba3a4f16a ("Iran", Persian) : IR +ایران + +// xn--mgba3a4fra ("Iran", Arabic) : IR +ايران + +// xn--mgbtx2b ("Iraq", Arabic) : IQ +// Communications and Media Commission +عراق + +// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO +// National Information Technology Center (NITC) +// Royal Scientific Society, Al-Jubeiha +الاردن + +// xn--3e0b707e ("Republic of Korea", Hangul) : KR +한국 + +// xn--80ao21a ("Kaz", Kazakh) : KZ +қаз + +// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK +// http://nic.lk +ලංකා + +// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK +// http://nic.lk +இலங்கை + +// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA +المغرب + +// xn--d1alf ("mkd", Macedonian) : MK +// MARnet +мкд + +// xn--l1acc ("mon", Mongolian) : MN +мон + +// xn--mix891f ("Macao", Chinese, Traditional) : MO +// MONIC / HNET Asia (Registry Operator for .mo) +澳門 + +// xn--mix082f ("Macao", Chinese, Simplified) : MO +澳门 + +// xn--mgbx4cd0ab ("Malaysia", Malay) : MY +مليسيا + +// xn--mgb9awbf ("Oman", Arabic) : OM +عمان + +// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK +پاکستان + +// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK +پاكستان + +// xn--ygbi2ammx ("Falasteen", Arabic) : PS +// The Palestinian National Internet Naming Authority (PNINA) +// http://www.pnina.ps +فلسطين + +// xn--90a3ac ("srb", Cyrillic) : RS +// https://www.rnids.rs/en/domains/national-domains +срб +пр.срб +орг.срб +обр.срб +од.срб +упр.срб +ак.срб + +// xn--p1ai ("rf", Russian-Cyrillic) : RU +// http://www.cctld.ru/en/docs/rulesrf.php +рф + +// xn--wgbl6a ("Qatar", Arabic) : QA +// http://www.ict.gov.qa/ +قطر + +// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA +// http://www.nic.net.sa/ +السعودية + +// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA +السعودیة + +// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA +السعودیۃ + +// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA +السعوديه + +// xn--mgbpl2fh ("sudan", Arabic) : SD +// Operated by .sd registry +سودان + +// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG +新加坡 + +// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG +சிங்கப்பூர் + +// xn--ogbpf8fl ("Syria", Arabic) : SY +سورية + +// xn--mgbtf8fl ("Syria", Arabic, variant) : SY +سوريا + +// xn--o3cw4h ("Thai", Thai) : TH +// http://www.thnic.co.th +ไทย +ศึกษา.ไทย +ธุรกิจ.ไทย +รัฐบาล.ไทย +ทหาร.ไทย +เน็ต.ไทย +องค์กร.ไทย + +// xn--pgbs0dh ("Tunisia", Arabic) : TN +// http://nic.tn +تونس + +// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台灣 + +// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台湾 + +// xn--nnx388a ("Taiwan", Chinese, variant) : TW +臺灣 + +// xn--j1amh ("ukr", Cyrillic) : UA +укр + +// xn--mgb2ddes ("AlYemen", Arabic) : YE +اليمن + +// xxx : http://icmregistry.com +xxx + +// ye : http://www.y.net.ye/services/domain_name.htm +*.ye + +// za : https://www.zadna.org.za/content/page/domain-information/ +ac.za +agric.za +alt.za +co.za +edu.za +gov.za +grondar.za +law.za +mil.za +net.za +ngo.za +nic.za +nis.za +nom.za +org.za +school.za +tm.za +web.za + +// zm : https://zicta.zm/ +// Submitted by registry +zm +ac.zm +biz.zm +co.zm +com.zm +edu.zm +gov.zm +info.zm +mil.zm +net.zm +org.zm +sch.zm + +// zw : https://www.potraz.gov.zw/ +// Confirmed by registry 2017-01-25 +zw +ac.zw +co.zw +gov.zw +mil.zw +org.zw + + +// newGTLDs + +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2019-11-20T17:10:44Z +// This list is auto-generated, don't edit it manually. +// aaa : 2015-02-26 American Automobile Association, Inc. +aaa + +// aarp : 2015-05-21 AARP +aarp + +// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V. +abarth + +// abb : 2014-10-24 ABB Ltd +abb + +// abbott : 2014-07-24 Abbott Laboratories, Inc. +abbott + +// abbvie : 2015-07-30 AbbVie Inc. +abbvie + +// abc : 2015-07-30 Disney Enterprises, Inc. +abc + +// able : 2015-06-25 Able Inc. +able + +// abogado : 2014-04-24 Minds + Machines Group Limited +abogado + +// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre +abudhabi + +// academy : 2013-11-07 Binky Moon, LLC +academy + +// accenture : 2014-08-15 Accenture plc +accenture + +// accountant : 2014-11-20 dot Accountant Limited +accountant + +// accountants : 2014-03-20 Binky Moon, LLC +accountants + +// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG +aco + +// actor : 2013-12-12 Dog Beach, LLC +actor + +// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) +adac + +// ads : 2014-12-04 Charleston Road Registry Inc. +ads + +// adult : 2014-10-16 ICM Registry AD LLC +adult + +// aeg : 2015-03-19 Aktiebolaget Electrolux +aeg + +// aetna : 2015-05-21 Aetna Life Insurance Company +aetna + +// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. +afamilycompany + +// afl : 2014-10-02 Australian Football League +afl + +// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa +africa + +// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +agakhan + +// agency : 2013-11-14 Binky Moon, LLC +agency + +// aig : 2014-12-18 American International Group, Inc. +aig + +// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. +aigo + +// airbus : 2015-07-30 Airbus S.A.S. +airbus + +// airforce : 2014-03-06 Dog Beach, LLC +airforce + +// airtel : 2014-10-24 Bharti Airtel Limited +airtel + +// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +akdn + +// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V. +alfaromeo + +// alibaba : 2015-01-15 Alibaba Group Holding Limited +alibaba + +// alipay : 2015-01-15 Alibaba Group Holding Limited +alipay + +// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft +allfinanz + +// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company +allstate + +// ally : 2015-06-18 Ally Financial Inc. +ally + +// alsace : 2014-07-02 Region Grand Est +alsace + +// alstom : 2015-07-30 ALSTOM +alstom + +// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc. +americanexpress + +// americanfamily : 2015-07-23 AmFam, Inc. +americanfamily + +// amex : 2015-07-31 American Express Travel Related Services Company, Inc. +amex + +// amfam : 2015-07-23 AmFam, Inc. +amfam + +// amica : 2015-05-28 Amica Mutual Insurance Company +amica + +// amsterdam : 2014-07-24 Gemeente Amsterdam +amsterdam + +// analytics : 2014-12-18 Campus IP LLC +analytics + +// android : 2014-08-07 Charleston Road Registry Inc. +android + +// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +anquan + +// anz : 2015-07-31 Australia and New Zealand Banking Group Limited +anz + +// aol : 2015-09-17 Oath Inc. +aol + +// apartments : 2014-12-11 Binky Moon, LLC +apartments + +// app : 2015-05-14 Charleston Road Registry Inc. +app + +// apple : 2015-05-14 Apple Inc. +apple + +// aquarelle : 2014-07-24 Aquarelle.com +aquarelle + +// arab : 2015-11-12 League of Arab States +arab + +// aramco : 2014-11-20 Aramco Services Company +aramco + +// archi : 2014-02-06 Afilias Limited +archi + +// army : 2014-03-06 Dog Beach, LLC +army + +// art : 2016-03-24 UK Creative Ideas Limited +art + +// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E. +arte + +// asda : 2015-07-31 Wal-Mart Stores, Inc. +asda + +// associates : 2014-03-06 Binky Moon, LLC +associates + +// athleta : 2015-07-30 The Gap, Inc. +athleta + +// attorney : 2014-03-20 Dog Beach, LLC +attorney + +// auction : 2014-03-20 Dog Beach, LLC +auction + +// audi : 2015-05-21 AUDI Aktiengesellschaft +audi + +// audible : 2015-06-25 Amazon Registry Services, Inc. +audible + +// audio : 2014-03-20 Uniregistry, Corp. +audio + +// auspost : 2015-08-13 Australian Postal Corporation +auspost + +// author : 2014-12-18 Amazon Registry Services, Inc. +author + +// auto : 2014-11-13 Cars Registry Limited +auto + +// autos : 2014-01-09 DERAutos, LLC +autos + +// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca +avianca + +// aws : 2015-06-25 Amazon Registry Services, Inc. +aws + +// axa : 2013-12-19 AXA SA +axa + +// azure : 2014-12-18 Microsoft Corporation +azure + +// baby : 2015-04-09 XYZ.COM LLC +baby + +// baidu : 2015-01-08 Baidu, Inc. +baidu + +// banamex : 2015-07-30 Citigroup Inc. +banamex + +// bananarepublic : 2015-07-31 The Gap, Inc. +bananarepublic + +// band : 2014-06-12 Dog Beach, LLC +band + +// bank : 2014-09-25 fTLD Registry Services LLC +bank + +// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +bar + +// barcelona : 2014-07-24 Municipi de Barcelona +barcelona + +// barclaycard : 2014-11-20 Barclays Bank PLC +barclaycard + +// barclays : 2014-11-20 Barclays Bank PLC +barclays + +// barefoot : 2015-06-11 Gallo Vineyards, Inc. +barefoot + +// bargains : 2013-11-14 Binky Moon, LLC +bargains + +// baseball : 2015-10-29 MLB Advanced Media DH, LLC +baseball + +// basketball : 2015-08-20 Fédération Internationale de Basketball (FIBA) +basketball + +// bauhaus : 2014-04-17 Werkhaus GmbH +bauhaus + +// bayern : 2014-01-23 Bayern Connect GmbH +bayern + +// bbc : 2014-12-18 British Broadcasting Corporation +bbc + +// bbt : 2015-07-23 BB&T Corporation +bbt + +// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A. +bbva + +// bcg : 2015-04-02 The Boston Consulting Group, Inc. +bcg + +// bcn : 2014-07-24 Municipi de Barcelona +bcn + +// beats : 2015-05-14 Beats Electronics, LLC +beats + +// beauty : 2015-12-03 L'Oréal +beauty + +// beer : 2014-01-09 Minds + Machines Group Limited +beer + +// bentley : 2014-12-18 Bentley Motors Limited +bentley + +// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG +berlin + +// best : 2013-12-19 BestTLD Pty Ltd +best + +// bestbuy : 2015-07-31 BBY Solutions, Inc. +bestbuy + +// bet : 2015-05-07 Afilias Limited +bet + +// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited +bharti + +// bible : 2014-06-19 American Bible Society +bible + +// bid : 2013-12-19 dot Bid Limited +bid + +// bike : 2013-08-27 Binky Moon, LLC +bike + +// bing : 2014-12-18 Microsoft Corporation +bing + +// bingo : 2014-12-04 Binky Moon, LLC +bingo + +// bio : 2014-03-06 Afilias Limited +bio + +// black : 2014-01-16 Afilias Limited +black + +// blackfriday : 2014-01-16 Uniregistry, Corp. +blackfriday + +// blockbuster : 2015-07-30 Dish DBS Corporation +blockbuster + +// blog : 2015-05-14 Knock Knock WHOIS There, LLC +blog + +// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC +bloomberg + +// blue : 2013-11-07 Afilias Limited +blue + +// bms : 2014-10-30 Bristol-Myers Squibb Company +bms + +// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +bmw + +// bnpparibas : 2014-05-29 BNP Paribas +bnpparibas + +// boats : 2014-12-04 DERBoats, LLC +boats + +// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH +boehringer + +// bofa : 2015-07-31 Bank of America Corporation +bofa + +// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +bom + +// bond : 2014-06-05 ShortDot SA +bond + +// boo : 2014-01-30 Charleston Road Registry Inc. +boo + +// book : 2015-08-27 Amazon Registry Services, Inc. +book + +// booking : 2015-07-16 Booking.com B.V. +booking + +// bosch : 2015-06-18 Robert Bosch GMBH +bosch + +// bostik : 2015-05-28 Bostik SA +bostik + +// boston : 2015-12-10 Boston TLD Management, LLC +boston + +// bot : 2014-12-18 Amazon Registry Services, Inc. +bot + +// boutique : 2013-11-14 Binky Moon, LLC +boutique + +// box : 2015-11-12 .BOX INC. +box + +// bradesco : 2014-12-18 Banco Bradesco S.A. +bradesco + +// bridgestone : 2014-12-18 Bridgestone Corporation +bridgestone + +// broadway : 2014-12-22 Celebrate Broadway, Inc. +broadway + +// broker : 2014-12-11 Dotbroker Registry Limited +broker + +// brother : 2015-01-29 Brother Industries, Ltd. +brother + +// brussels : 2014-02-06 DNS.be vzw +brussels + +// budapest : 2013-11-21 Minds + Machines Group Limited +budapest + +// bugatti : 2015-07-23 Bugatti International SA +bugatti + +// build : 2013-11-07 Plan Bee LLC +build + +// builders : 2013-11-07 Binky Moon, LLC +builders + +// business : 2013-11-07 Binky Moon, LLC +business + +// buy : 2014-12-18 Amazon Registry Services, Inc. +buy + +// buzz : 2013-10-02 DOTSTRATEGY CO. +buzz + +// bzh : 2014-02-27 Association www.bzh +bzh + +// cab : 2013-10-24 Binky Moon, LLC +cab + +// cafe : 2015-02-11 Binky Moon, LLC +cafe + +// cal : 2014-07-24 Charleston Road Registry Inc. +cal + +// call : 2014-12-18 Amazon Registry Services, Inc. +call + +// calvinklein : 2015-07-30 PVH gTLD Holdings LLC +calvinklein + +// cam : 2016-04-21 AC Webconnecting Holding B.V. +cam + +// camera : 2013-08-27 Binky Moon, LLC +camera + +// camp : 2013-11-07 Binky Moon, LLC +camp + +// cancerresearch : 2014-05-15 Australian Cancer Research Foundation +cancerresearch + +// canon : 2014-09-12 Canon Inc. +canon + +// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +capetown + +// capital : 2014-03-06 Binky Moon, LLC +capital + +// capitalone : 2015-08-06 Capital One Financial Corporation +capitalone + +// car : 2015-01-22 Cars Registry Limited +car + +// caravan : 2013-12-12 Caravan International, Inc. +caravan + +// cards : 2013-12-05 Binky Moon, LLC +cards + +// care : 2014-03-06 Binky Moon, LLC +care + +// career : 2013-10-09 dotCareer LLC +career + +// careers : 2013-10-02 Binky Moon, LLC +careers + +// cars : 2014-11-13 Cars Registry Limited +cars + +// casa : 2013-11-21 Minds + Machines Group Limited +casa + +// case : 2015-09-03 CNH Industrial N.V. +case + +// caseih : 2015-09-03 CNH Industrial N.V. +caseih + +// cash : 2014-03-06 Binky Moon, LLC +cash + +// casino : 2014-12-18 Binky Moon, LLC +casino + +// catering : 2013-12-05 Binky Moon, LLC +catering + +// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +catholic + +// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +cba + +// cbn : 2014-08-22 The Christian Broadcasting Network, Inc. +cbn + +// cbre : 2015-07-02 CBRE, Inc. +cbre + +// cbs : 2015-08-06 CBS Domains Inc. +cbs + +// ceb : 2015-04-09 The Corporate Executive Board Company +ceb + +// center : 2013-11-07 Binky Moon, LLC +center + +// ceo : 2013-11-07 CEOTLD Pty Ltd +ceo + +// cern : 2014-06-05 European Organization for Nuclear Research ("CERN") +cern + +// cfa : 2014-08-28 CFA Institute +cfa + +// cfd : 2014-12-11 DotCFD Registry Limited +cfd + +// chanel : 2015-04-09 Chanel International B.V. +chanel + +// channel : 2014-05-08 Charleston Road Registry Inc. +channel + +// charity : 2018-04-11 Binky Moon, LLC +charity + +// chase : 2015-04-30 JPMorgan Chase Bank, National Association +chase + +// chat : 2014-12-04 Binky Moon, LLC +chat + +// cheap : 2013-11-14 Binky Moon, LLC +cheap + +// chintai : 2015-06-11 CHINTAI Corporation +chintai + +// christmas : 2013-11-21 Uniregistry, Corp. +christmas + +// chrome : 2014-07-24 Charleston Road Registry Inc. +chrome + +// church : 2014-02-06 Binky Moon, LLC +church + +// cipriani : 2015-02-19 Hotel Cipriani Srl +cipriani + +// circle : 2014-12-18 Amazon Registry Services, Inc. +circle + +// cisco : 2014-12-22 Cisco Technology, Inc. +cisco + +// citadel : 2015-07-23 Citadel Domain LLC +citadel + +// citi : 2015-07-30 Citigroup Inc. +citi + +// citic : 2014-01-09 CITIC Group Corporation +citic + +// city : 2014-05-29 Binky Moon, LLC +city + +// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc. +cityeats + +// claims : 2014-03-20 Binky Moon, LLC +claims + +// cleaning : 2013-12-05 Binky Moon, LLC +cleaning + +// click : 2014-06-05 Uniregistry, Corp. +click + +// clinic : 2014-03-20 Binky Moon, LLC +clinic + +// clinique : 2015-10-01 The Estée Lauder Companies Inc. +clinique + +// clothing : 2013-08-27 Binky Moon, LLC +clothing + +// cloud : 2015-04-16 Aruba PEC S.p.A. +cloud + +// club : 2013-11-08 .CLUB DOMAINS, LLC +club + +// clubmed : 2015-06-25 Club Méditerranée S.A. +clubmed + +// coach : 2014-10-09 Binky Moon, LLC +coach + +// codes : 2013-10-31 Binky Moon, LLC +codes + +// coffee : 2013-10-17 Binky Moon, LLC +coffee + +// college : 2014-01-16 XYZ.COM LLC +college + +// cologne : 2014-02-05 dotKoeln GmbH +cologne + +// comcast : 2015-07-23 Comcast IP Holdings I, LLC +comcast + +// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +commbank + +// community : 2013-12-05 Binky Moon, LLC +community + +// company : 2013-11-07 Binky Moon, LLC +company + +// compare : 2015-10-08 Registry Services, LLC +compare + +// computer : 2013-10-24 Binky Moon, LLC +computer + +// comsec : 2015-01-08 VeriSign, Inc. +comsec + +// condos : 2013-12-05 Binky Moon, LLC +condos + +// construction : 2013-09-16 Binky Moon, LLC +construction + +// consulting : 2013-12-05 Dog Beach, LLC +consulting + +// contact : 2015-01-08 Dog Beach, LLC +contact + +// contractors : 2013-09-10 Binky Moon, LLC +contractors + +// cooking : 2013-11-21 Minds + Machines Group Limited +cooking + +// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +cookingchannel + +// cool : 2013-11-14 Binky Moon, LLC +cool + +// corsica : 2014-09-25 Collectivité de Corse +corsica + +// country : 2013-12-19 DotCountry LLC +country + +// coupon : 2015-02-26 Amazon Registry Services, Inc. +coupon + +// coupons : 2015-03-26 Binky Moon, LLC +coupons + +// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD +courses + +// cpa : 2019-06-10 American Institute of Certified Public Accountants +cpa + +// credit : 2014-03-20 Binky Moon, LLC +credit + +// creditcard : 2014-03-20 Binky Moon, LLC +creditcard + +// creditunion : 2015-01-22 CUNA Performance Resources, LLC +creditunion + +// cricket : 2014-10-09 dot Cricket Limited +cricket + +// crown : 2014-10-24 Crown Equipment Corporation +crown + +// crs : 2014-04-03 Federated Co-operatives Limited +crs + +// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd. +cruise + +// cruises : 2013-12-05 Binky Moon, LLC +cruises + +// csc : 2014-09-25 Alliance-One Services, Inc. +csc + +// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S. +cuisinella + +// cymru : 2014-05-08 Nominet UK +cymru + +// cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd. +cyou + +// dabur : 2014-02-06 Dabur India Limited +dabur + +// dad : 2014-01-23 Charleston Road Registry Inc. +dad + +// dance : 2013-10-24 Dog Beach, LLC +dance + +// data : 2016-06-02 Dish DBS Corporation +data + +// date : 2014-11-20 dot Date Limited +date + +// dating : 2013-12-05 Binky Moon, LLC +dating + +// datsun : 2014-03-27 NISSAN MOTOR CO., LTD. +datsun + +// day : 2014-01-30 Charleston Road Registry Inc. +day + +// dclk : 2014-11-20 Charleston Road Registry Inc. +dclk + +// dds : 2015-05-07 Minds + Machines Group Limited +dds + +// deal : 2015-06-25 Amazon Registry Services, Inc. +deal + +// dealer : 2014-12-22 Intercap Registry Inc. +dealer + +// deals : 2014-05-22 Binky Moon, LLC +deals + +// degree : 2014-03-06 Dog Beach, LLC +degree + +// delivery : 2014-09-11 Binky Moon, LLC +delivery + +// dell : 2014-10-24 Dell Inc. +dell + +// deloitte : 2015-07-31 Deloitte Touche Tohmatsu +deloitte + +// delta : 2015-02-19 Delta Air Lines, Inc. +delta + +// democrat : 2013-10-24 Dog Beach, LLC +democrat + +// dental : 2014-03-20 Binky Moon, LLC +dental + +// dentist : 2014-03-20 Dog Beach, LLC +dentist + +// desi : 2013-11-14 Desi Networks LLC +desi + +// design : 2014-11-07 Top Level Design, LLC +design + +// dev : 2014-10-16 Charleston Road Registry Inc. +dev + +// dhl : 2015-07-23 Deutsche Post AG +dhl + +// diamonds : 2013-09-22 Binky Moon, LLC +diamonds + +// diet : 2014-06-26 Uniregistry, Corp. +diet + +// digital : 2014-03-06 Binky Moon, LLC +digital + +// direct : 2014-04-10 Binky Moon, LLC +direct + +// directory : 2013-09-20 Binky Moon, LLC +directory + +// discount : 2014-03-06 Binky Moon, LLC +discount + +// discover : 2015-07-23 Discover Financial Services +discover + +// dish : 2015-07-30 Dish DBS Corporation +dish + +// diy : 2015-11-05 Lifestyle Domain Holdings, Inc. +diy + +// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd. +dnp + +// docs : 2014-10-16 Charleston Road Registry Inc. +docs + +// doctor : 2016-06-02 Binky Moon, LLC +doctor + +// dog : 2014-12-04 Binky Moon, LLC +dog + +// domains : 2013-10-17 Binky Moon, LLC +domains + +// dot : 2015-05-21 Dish DBS Corporation +dot + +// download : 2014-11-20 dot Support Limited +download + +// drive : 2015-03-05 Charleston Road Registry Inc. +drive + +// dtv : 2015-06-04 Dish DBS Corporation +dtv + +// dubai : 2015-01-01 Dubai Smart Government Department +dubai + +// duck : 2015-07-23 Johnson Shareholdings, Inc. +duck + +// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company +dunlop + +// dupont : 2015-06-25 E. I. du Pont de Nemours and Company +dupont + +// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +durban + +// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +dvag + +// dvr : 2016-05-26 DISH Technologies L.L.C. +dvr + +// earth : 2014-12-04 Interlink Co., Ltd. +earth + +// eat : 2014-01-23 Charleston Road Registry Inc. +eat + +// eco : 2016-07-08 Big Room Inc. +eco + +// edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V. +edeka + +// education : 2013-11-07 Binky Moon, LLC +education + +// email : 2013-10-31 Binky Moon, LLC +email + +// emerck : 2014-04-03 Merck KGaA +emerck + +// energy : 2014-09-11 Binky Moon, LLC +energy + +// engineer : 2014-03-06 Dog Beach, LLC +engineer + +// engineering : 2014-03-06 Binky Moon, LLC +engineering + +// enterprises : 2013-09-20 Binky Moon, LLC +enterprises + +// epson : 2014-12-04 Seiko Epson Corporation +epson + +// equipment : 2013-08-27 Binky Moon, LLC +equipment + +// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson +ericsson + +// erni : 2014-04-03 ERNI Group Holding AG +erni + +// esq : 2014-05-08 Charleston Road Registry Inc. +esq + +// estate : 2013-08-27 Binky Moon, LLC +estate + +// esurance : 2015-07-23 Esurance Insurance Company +esurance + +// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +etisalat + +// eurovision : 2014-04-24 European Broadcasting Union (EBU) +eurovision + +// eus : 2013-12-12 Puntueus Fundazioa +eus + +// events : 2013-12-05 Binky Moon, LLC +events + +// exchange : 2014-03-06 Binky Moon, LLC +exchange + +// expert : 2013-11-21 Binky Moon, LLC +expert + +// exposed : 2013-12-05 Binky Moon, LLC +exposed + +// express : 2015-02-11 Binky Moon, LLC +express + +// extraspace : 2015-05-14 Extra Space Storage LLC +extraspace + +// fage : 2014-12-18 Fage International S.A. +fage + +// fail : 2014-03-06 Binky Moon, LLC +fail + +// fairwinds : 2014-11-13 FairWinds Partners, LLC +fairwinds + +// faith : 2014-11-20 dot Faith Limited +faith + +// family : 2015-04-02 Dog Beach, LLC +family + +// fan : 2014-03-06 Dog Beach, LLC +fan + +// fans : 2014-11-07 ZDNS International Limited +fans + +// farm : 2013-11-07 Binky Moon, LLC +farm + +// farmers : 2015-07-09 Farmers Insurance Exchange +farmers + +// fashion : 2014-07-03 Minds + Machines Group Limited +fashion + +// fast : 2014-12-18 Amazon Registry Services, Inc. +fast + +// fedex : 2015-08-06 Federal Express Corporation +fedex + +// feedback : 2013-12-19 Top Level Spectrum, Inc. +feedback + +// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V. +ferrari + +// ferrero : 2014-12-18 Ferrero Trading Lux S.A. +ferrero + +// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V. +fiat + +// fidelity : 2015-07-30 Fidelity Brokerage Services LLC +fidelity + +// fido : 2015-08-06 Rogers Communications Canada Inc. +fido + +// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd +film + +// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +final + +// finance : 2014-03-20 Binky Moon, LLC +finance + +// financial : 2014-03-06 Binky Moon, LLC +financial + +// fire : 2015-06-25 Amazon Registry Services, Inc. +fire + +// firestone : 2014-12-18 Bridgestone Licensing Services, Inc +firestone + +// firmdale : 2014-03-27 Firmdale Holdings Limited +firmdale + +// fish : 2013-12-12 Binky Moon, LLC +fish + +// fishing : 2013-11-21 Minds + Machines Group Limited +fishing + +// fit : 2014-11-07 Minds + Machines Group Limited +fit + +// fitness : 2014-03-06 Binky Moon, LLC +fitness + +// flickr : 2015-04-02 Yahoo! Domain Services Inc. +flickr + +// flights : 2013-12-05 Binky Moon, LLC +flights + +// flir : 2015-07-23 FLIR Systems, Inc. +flir + +// florist : 2013-11-07 Binky Moon, LLC +florist + +// flowers : 2014-10-09 Uniregistry, Corp. +flowers + +// fly : 2014-05-08 Charleston Road Registry Inc. +fly + +// foo : 2014-01-23 Charleston Road Registry Inc. +foo + +// food : 2016-04-21 Lifestyle Domain Holdings, Inc. +food + +// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc. +foodnetwork + +// football : 2014-12-18 Binky Moon, LLC +football + +// ford : 2014-11-13 Ford Motor Company +ford + +// forex : 2014-12-11 Dotforex Registry Limited +forex + +// forsale : 2014-05-22 Dog Beach, LLC +forsale + +// forum : 2015-04-02 Fegistry, LLC +forum + +// foundation : 2013-12-05 Binky Moon, LLC +foundation + +// fox : 2015-09-11 FOX Registry, LLC +fox + +// free : 2015-12-10 Amazon Registry Services, Inc. +free + +// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH +fresenius + +// frl : 2014-05-15 FRLregistry B.V. +frl + +// frogans : 2013-12-19 OP3FT +frogans + +// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc. +frontdoor + +// frontier : 2015-02-05 Frontier Communications Corporation +frontier + +// ftr : 2015-07-16 Frontier Communications Corporation +ftr + +// fujitsu : 2015-07-30 Fujitsu Limited +fujitsu + +// fujixerox : 2015-07-23 Xerox DNHC LLC +fujixerox + +// fun : 2016-01-14 DotSpace Inc. +fun + +// fund : 2014-03-20 Binky Moon, LLC +fund + +// furniture : 2014-03-20 Binky Moon, LLC +furniture + +// futbol : 2013-09-20 Dog Beach, LLC +futbol + +// fyi : 2015-04-02 Binky Moon, LLC +fyi + +// gal : 2013-11-07 Asociación puntoGAL +gal + +// gallery : 2013-09-13 Binky Moon, LLC +gallery + +// gallo : 2015-06-11 Gallo Vineyards, Inc. +gallo + +// gallup : 2015-02-19 Gallup, Inc. +gallup + +// game : 2015-05-28 Uniregistry, Corp. +game + +// games : 2015-05-28 Dog Beach, LLC +games + +// gap : 2015-07-31 The Gap, Inc. +gap + +// garden : 2014-06-26 Minds + Machines Group Limited +garden + +// gay : 2019-05-23 Top Level Design, LLC +gay + +// gbiz : 2014-07-17 Charleston Road Registry Inc. +gbiz + +// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems" +gdn + +// gea : 2014-12-04 GEA Group Aktiengesellschaft +gea + +// gent : 2014-01-23 COMBELL NV +gent + +// genting : 2015-03-12 Resorts World Inc Pte. Ltd. +genting + +// george : 2015-07-31 Wal-Mart Stores, Inc. +george + +// ggee : 2014-01-09 GMO Internet, Inc. +ggee + +// gift : 2013-10-17 DotGift, LLC +gift + +// gifts : 2014-07-03 Binky Moon, LLC +gifts + +// gives : 2014-03-06 Dog Beach, LLC +gives + +// giving : 2014-11-13 Giving Limited +giving + +// glade : 2015-07-23 Johnson Shareholdings, Inc. +glade + +// glass : 2013-11-07 Binky Moon, LLC +glass + +// gle : 2014-07-24 Charleston Road Registry Inc. +gle + +// global : 2014-04-17 Dot Global Domain Registry Limited +global + +// globo : 2013-12-19 Globo Comunicação e Participações S.A +globo + +// gmail : 2014-05-01 Charleston Road Registry Inc. +gmail + +// gmbh : 2016-01-29 Binky Moon, LLC +gmbh + +// gmo : 2014-01-09 GMO Internet, Inc. +gmo + +// gmx : 2014-04-24 1&1 Mail & Media GmbH +gmx + +// godaddy : 2015-07-23 Go Daddy East, LLC +godaddy + +// gold : 2015-01-22 Binky Moon, LLC +gold + +// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +goldpoint + +// golf : 2014-12-18 Binky Moon, LLC +golf + +// goo : 2014-12-18 NTT Resonant Inc. +goo + +// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company +goodyear + +// goog : 2014-11-20 Charleston Road Registry Inc. +goog + +// google : 2014-07-24 Charleston Road Registry Inc. +google + +// gop : 2014-01-16 Republican State Leadership Committee, Inc. +gop + +// got : 2014-12-18 Amazon Registry Services, Inc. +got + +// grainger : 2015-05-07 Grainger Registry Services, LLC +grainger + +// graphics : 2013-09-13 Binky Moon, LLC +graphics + +// gratis : 2014-03-20 Binky Moon, LLC +gratis + +// green : 2014-05-08 Afilias Limited +green + +// gripe : 2014-03-06 Binky Moon, LLC +gripe + +// grocery : 2016-06-16 Wal-Mart Stores, Inc. +grocery + +// group : 2014-08-15 Binky Moon, LLC +group + +// guardian : 2015-07-30 The Guardian Life Insurance Company of America +guardian + +// gucci : 2014-11-13 Guccio Gucci S.p.a. +gucci + +// guge : 2014-08-28 Charleston Road Registry Inc. +guge + +// guide : 2013-09-13 Binky Moon, LLC +guide + +// guitars : 2013-11-14 Uniregistry, Corp. +guitars + +// guru : 2013-08-27 Binky Moon, LLC +guru + +// hair : 2015-12-03 L'Oréal +hair + +// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH +hamburg + +// hangout : 2014-11-13 Charleston Road Registry Inc. +hangout + +// haus : 2013-12-05 Dog Beach, LLC +haus + +// hbo : 2015-07-30 HBO Registry Services, Inc. +hbo + +// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED +hdfc + +// hdfcbank : 2015-02-12 HDFC Bank Limited +hdfcbank + +// health : 2015-02-11 DotHealth, LLC +health + +// healthcare : 2014-06-12 Binky Moon, LLC +healthcare + +// help : 2014-06-26 Uniregistry, Corp. +help + +// helsinki : 2015-02-05 City of Helsinki +helsinki + +// here : 2014-02-06 Charleston Road Registry Inc. +here + +// hermes : 2014-07-10 HERMES INTERNATIONAL +hermes + +// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. +hgtv + +// hiphop : 2014-03-06 Uniregistry, Corp. +hiphop + +// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. +hisamitsu + +// hitachi : 2014-10-31 Hitachi, Ltd. +hitachi + +// hiv : 2014-03-13 Uniregistry, Corp. +hiv + +// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited +hkt + +// hockey : 2015-03-19 Binky Moon, LLC +hockey + +// holdings : 2013-08-27 Binky Moon, LLC +holdings + +// holiday : 2013-11-07 Binky Moon, LLC +holiday + +// homedepot : 2015-04-02 Home Depot Product Authority, LLC +homedepot + +// homegoods : 2015-07-16 The TJX Companies, Inc. +homegoods + +// homes : 2014-01-09 DERHomes, LLC +homes + +// homesense : 2015-07-16 The TJX Companies, Inc. +homesense + +// honda : 2014-12-18 Honda Motor Co., Ltd. +honda + +// horse : 2013-11-21 Minds + Machines Group Limited +horse + +// hospital : 2016-10-20 Binky Moon, LLC +hospital + +// host : 2014-04-17 DotHost Inc. +host + +// hosting : 2014-05-29 Uniregistry, Corp. +hosting + +// hot : 2015-08-27 Amazon Registry Services, Inc. +hot + +// hoteles : 2015-03-05 Travel Reservations SRL +hoteles + +// hotels : 2016-04-07 Booking.com B.V. +hotels + +// hotmail : 2014-12-18 Microsoft Corporation +hotmail + +// house : 2013-11-07 Binky Moon, LLC +house + +// how : 2014-01-23 Charleston Road Registry Inc. +how + +// hsbc : 2014-10-24 HSBC Global Services (UK) Limited +hsbc + +// hughes : 2015-07-30 Hughes Satellite Systems Corporation +hughes + +// hyatt : 2015-07-30 Hyatt GTLD, L.L.C. +hyatt + +// hyundai : 2015-07-09 Hyundai Motor Company +hyundai + +// ibm : 2014-07-31 International Business Machines Corporation +ibm + +// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited +icbc + +// ice : 2014-10-30 IntercontinentalExchange, Inc. +ice + +// icu : 2015-01-08 ShortDot SA +icu + +// ieee : 2015-07-23 IEEE Global LLC +ieee + +// ifm : 2014-01-30 ifm electronic gmbh +ifm + +// ikano : 2015-07-09 Ikano S.A. +ikano + +// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +imamat + +// imdb : 2015-06-25 Amazon Registry Services, Inc. +imdb + +// immo : 2014-07-10 Binky Moon, LLC +immo + +// immobilien : 2013-11-07 Dog Beach, LLC +immobilien + +// inc : 2018-03-10 Intercap Registry Inc. +inc + +// industries : 2013-12-05 Binky Moon, LLC +industries + +// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. +infiniti + +// ing : 2014-01-23 Charleston Road Registry Inc. +ing + +// ink : 2013-12-05 Top Level Design, LLC +ink + +// institute : 2013-11-07 Binky Moon, LLC +institute + +// insurance : 2015-02-19 fTLD Registry Services LLC +insurance + +// insure : 2014-03-20 Binky Moon, LLC +insure + +// intel : 2015-08-06 Intel Corporation +intel + +// international : 2013-11-07 Binky Moon, LLC +international + +// intuit : 2015-07-30 Intuit Administrative Services, Inc. +intuit + +// investments : 2014-03-20 Binky Moon, LLC +investments + +// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. +ipiranga + +// irish : 2014-08-07 Binky Moon, LLC +irish + +// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +ismaili + +// ist : 2014-08-28 Istanbul Metropolitan Municipality +ist + +// istanbul : 2014-08-28 Istanbul Metropolitan Municipality +istanbul + +// itau : 2014-10-02 Itau Unibanco Holding S.A. +itau + +// itv : 2015-07-09 ITV Services Limited +itv + +// iveco : 2015-09-03 CNH Industrial N.V. +iveco + +// jaguar : 2014-11-13 Jaguar Land Rover Ltd +jaguar + +// java : 2014-06-19 Oracle Corporation +java + +// jcb : 2014-11-20 JCB Co., Ltd. +jcb + +// jcp : 2015-04-23 JCP Media, Inc. +jcp + +// jeep : 2015-07-30 FCA US LLC. +jeep + +// jetzt : 2014-01-09 Binky Moon, LLC +jetzt + +// jewelry : 2015-03-05 Binky Moon, LLC +jewelry + +// jio : 2015-04-02 Reliance Industries Limited +jio + +// jll : 2015-04-02 Jones Lang LaSalle Incorporated +jll + +// jmp : 2015-03-26 Matrix IP LLC +jmp + +// jnj : 2015-06-18 Johnson & Johnson Services, Inc. +jnj + +// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +joburg + +// jot : 2014-12-18 Amazon Registry Services, Inc. +jot + +// joy : 2014-12-18 Amazon Registry Services, Inc. +joy + +// jpmorgan : 2015-04-30 JPMorgan Chase Bank, National Association +jpmorgan + +// jprs : 2014-09-18 Japan Registry Services Co., Ltd. +jprs + +// juegos : 2014-03-20 Uniregistry, Corp. +juegos + +// juniper : 2015-07-30 JUNIPER NETWORKS, INC. +juniper + +// kaufen : 2013-11-07 Dog Beach, LLC +kaufen + +// kddi : 2014-09-12 KDDI CORPORATION +kddi + +// kerryhotels : 2015-04-30 Kerry Trading Co. Limited +kerryhotels + +// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited +kerrylogistics + +// kerryproperties : 2015-04-09 Kerry Trading Co. Limited +kerryproperties + +// kfh : 2014-12-04 Kuwait Finance House +kfh + +// kia : 2015-07-09 KIA MOTORS CORPORATION +kia + +// kim : 2013-09-23 Afilias Limited +kim + +// kinder : 2014-11-07 Ferrero Trading Lux S.A. +kinder + +// kindle : 2015-06-25 Amazon Registry Services, Inc. +kindle + +// kitchen : 2013-09-20 Binky Moon, LLC +kitchen + +// kiwi : 2013-09-20 DOT KIWI LIMITED +kiwi + +// koeln : 2014-01-09 dotKoeln GmbH +koeln + +// komatsu : 2015-01-08 Komatsu Ltd. +komatsu + +// kosher : 2015-08-20 Kosher Marketing Assets LLC +kosher + +// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft) +kpmg + +// kpn : 2015-01-08 Koninklijke KPN N.V. +kpn + +// krd : 2013-12-05 KRG Department of Information Technology +krd + +// kred : 2013-12-19 KredTLD Pty Ltd +kred + +// kuokgroup : 2015-04-09 Kerry Trading Co. Limited +kuokgroup + +// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen +kyoto + +// lacaixa : 2014-01-09 Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa” +lacaixa + +// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A. +lamborghini + +// lamer : 2015-10-01 The Estée Lauder Companies Inc. +lamer + +// lancaster : 2015-02-12 LANCASTER +lancaster + +// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V. +lancia + +// lancome : 2015-07-23 L'Oréal +lancome + +// land : 2013-09-10 Binky Moon, LLC +land + +// landrover : 2014-11-13 Jaguar Land Rover Ltd +landrover + +// lanxess : 2015-07-30 LANXESS Corporation +lanxess + +// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated +lasalle + +// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico +lat + +// latino : 2015-07-30 Dish DBS Corporation +latino + +// latrobe : 2014-06-16 La Trobe University +latrobe + +// law : 2015-01-22 LW TLD Limited +law + +// lawyer : 2014-03-20 Dog Beach, LLC +lawyer + +// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +lds + +// lease : 2014-03-06 Binky Moon, LLC +lease + +// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc +leclerc + +// lefrak : 2015-07-16 LeFrak Organization, Inc. +lefrak + +// legal : 2014-10-16 Binky Moon, LLC +legal + +// lego : 2015-07-16 LEGO Juris A/S +lego + +// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION +lexus + +// lgbt : 2014-05-08 Afilias Limited +lgbt + +// liaison : 2014-10-02 Liaison Technologies, Incorporated +liaison + +// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +lidl + +// life : 2014-02-06 Binky Moon, LLC +life + +// lifeinsurance : 2015-01-15 American Council of Life Insurers +lifeinsurance + +// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc. +lifestyle + +// lighting : 2013-08-27 Binky Moon, LLC +lighting + +// like : 2014-12-18 Amazon Registry Services, Inc. +like + +// lilly : 2015-07-31 Eli Lilly and Company +lilly + +// limited : 2014-03-06 Binky Moon, LLC +limited + +// limo : 2013-10-17 Binky Moon, LLC +limo + +// lincoln : 2014-11-13 Ford Motor Company +lincoln + +// linde : 2014-12-04 Linde Aktiengesellschaft +linde + +// link : 2013-11-14 Uniregistry, Corp. +link + +// lipsy : 2015-06-25 Lipsy Ltd +lipsy + +// live : 2014-12-04 Dog Beach, LLC +live + +// living : 2015-07-30 Lifestyle Domain Holdings, Inc. +living + +// lixil : 2015-03-19 LIXIL Group Corporation +lixil + +// llc : 2017-12-14 Afilias Limited +llc + +// llp : 2019-08-26 Dot Registry LLC +llp + +// loan : 2014-11-20 dot Loan Limited +loan + +// loans : 2014-03-20 Binky Moon, LLC +loans + +// locker : 2015-06-04 Dish DBS Corporation +locker + +// locus : 2015-06-25 Locus Analytics LLC +locus + +// loft : 2015-07-30 Annco, Inc. +loft + +// lol : 2015-01-30 Uniregistry, Corp. +lol + +// london : 2013-11-14 Dot London Domains Limited +london + +// lotte : 2014-11-07 Lotte Holdings Co., Ltd. +lotte + +// lotto : 2014-04-10 Afilias Limited +lotto + +// love : 2014-12-22 Merchant Law Group LLP +love + +// lpl : 2015-07-30 LPL Holdings, Inc. +lpl + +// lplfinancial : 2015-07-30 LPL Holdings, Inc. +lplfinancial + +// ltd : 2014-09-25 Binky Moon, LLC +ltd + +// ltda : 2014-04-17 InterNetX, Corp +ltda + +// lundbeck : 2015-08-06 H. Lundbeck A/S +lundbeck + +// lupin : 2014-11-07 LUPIN LIMITED +lupin + +// luxe : 2014-01-09 Minds + Machines Group Limited +luxe + +// luxury : 2013-10-17 Luxury Partners, LLC +luxury + +// macys : 2015-07-31 Macys, Inc. +macys + +// madrid : 2014-05-01 Comunidad de Madrid +madrid + +// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) +maif + +// maison : 2013-12-05 Binky Moon, LLC +maison + +// makeup : 2015-01-15 L'Oréal +makeup + +// man : 2014-12-04 MAN SE +man + +// management : 2013-11-07 Binky Moon, LLC +management + +// mango : 2013-10-24 PUNTO FA S.L. +mango + +// map : 2016-06-09 Charleston Road Registry Inc. +map + +// market : 2014-03-06 Dog Beach, LLC +market + +// marketing : 2013-11-07 Binky Moon, LLC +marketing + +// markets : 2014-12-11 Dotmarkets Registry Limited +markets + +// marriott : 2014-10-09 Marriott Worldwide Corporation +marriott + +// marshalls : 2015-07-16 The TJX Companies, Inc. +marshalls + +// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V. +maserati + +// mattel : 2015-08-06 Mattel Sites, Inc. +mattel + +// mba : 2015-04-02 Binky Moon, LLC +mba + +// mckinsey : 2015-07-31 McKinsey Holdings, Inc. +mckinsey + +// med : 2015-08-06 Medistry LLC +med + +// media : 2014-03-06 Binky Moon, LLC +media + +// meet : 2014-01-16 Charleston Road Registry Inc. +meet + +// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation +melbourne + +// meme : 2014-01-30 Charleston Road Registry Inc. +meme + +// memorial : 2014-10-16 Dog Beach, LLC +memorial + +// men : 2015-02-26 Exclusive Registry Limited +men + +// menu : 2013-09-11 Dot Menu Registry, LLC +menu + +// merckmsd : 2016-07-14 MSD Registry Holdings, Inc. +merckmsd + +// metlife : 2015-05-07 MetLife Services and Solutions, LLC +metlife + +// miami : 2013-12-19 Minds + Machines Group Limited +miami + +// microsoft : 2014-12-18 Microsoft Corporation +microsoft + +// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +mini + +// mint : 2015-07-30 Intuit Administrative Services, Inc. +mint + +// mit : 2015-07-02 Massachusetts Institute of Technology +mit + +// mitsubishi : 2015-07-23 Mitsubishi Corporation +mitsubishi + +// mlb : 2015-05-21 MLB Advanced Media DH, LLC +mlb + +// mls : 2015-04-23 The Canadian Real Estate Association +mls + +// mma : 2014-11-07 MMA IARD +mma + +// mobile : 2016-06-02 Dish DBS Corporation +mobile + +// moda : 2013-11-07 Dog Beach, LLC +moda + +// moe : 2013-11-13 Interlink Co., Ltd. +moe + +// moi : 2014-12-18 Amazon Registry Services, Inc. +moi + +// mom : 2015-04-16 Uniregistry, Corp. +mom + +// monash : 2013-09-30 Monash University +monash + +// money : 2014-10-16 Binky Moon, LLC +money + +// monster : 2015-09-11 XYZ.COM LLC +monster + +// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +mormon + +// mortgage : 2014-03-20 Dog Beach, LLC +mortgage + +// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +moscow + +// moto : 2015-06-04 Motorola Trademark Holdings, LLC +moto + +// motorcycles : 2014-01-09 DERMotorcycles, LLC +motorcycles + +// mov : 2014-01-30 Charleston Road Registry Inc. +mov + +// movie : 2015-02-05 Binky Moon, LLC +movie + +// movistar : 2014-10-16 Telefónica S.A. +movistar + +// msd : 2015-07-23 MSD Registry Holdings, Inc. +msd + +// mtn : 2014-12-04 MTN Dubai Limited +mtn + +// mtr : 2015-03-12 MTR Corporation Limited +mtr + +// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC +mutual + +// nab : 2015-08-20 National Australia Bank Limited +nab + +// nadex : 2014-12-11 Nadex Domains, Inc. +nadex + +// nagoya : 2013-10-24 GMO Registry, Inc. +nagoya + +// nationwide : 2015-07-23 Nationwide Mutual Insurance Company +nationwide + +// natura : 2015-03-12 NATURA COSMÉTICOS S.A. +natura + +// navy : 2014-03-06 Dog Beach, LLC +navy + +// nba : 2015-07-31 NBA REGISTRY, LLC +nba + +// nec : 2015-01-08 NEC Corporation +nec + +// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +netbank + +// netflix : 2015-06-18 Netflix, Inc. +netflix + +// network : 2013-11-14 Binky Moon, LLC +network + +// neustar : 2013-12-05 Registry Services, LLC +neustar + +// new : 2014-01-30 Charleston Road Registry Inc. +new + +// newholland : 2015-09-03 CNH Industrial N.V. +newholland + +// news : 2014-12-18 Dog Beach, LLC +news + +// next : 2015-06-18 Next plc +next + +// nextdirect : 2015-06-18 Next plc +nextdirect + +// nexus : 2014-07-24 Charleston Road Registry Inc. +nexus + +// nfl : 2015-07-23 NFL Reg Ops LLC +nfl + +// ngo : 2014-03-06 Public Interest Registry +ngo + +// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) +nhk + +// nico : 2014-12-04 DWANGO Co., Ltd. +nico + +// nike : 2015-07-23 NIKE, Inc. +nike + +// nikon : 2015-05-21 NIKON CORPORATION +nikon + +// ninja : 2013-11-07 Dog Beach, LLC +ninja + +// nissan : 2014-03-27 NISSAN MOTOR CO., LTD. +nissan + +// nissay : 2015-10-29 Nippon Life Insurance Company +nissay + +// nokia : 2015-01-08 Nokia Corporation +nokia + +// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC +northwesternmutual + +// norton : 2014-12-04 Symantec Corporation +norton + +// now : 2015-06-25 Amazon Registry Services, Inc. +now + +// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +nowruz + +// nowtv : 2015-05-14 Starbucks (HK) Limited +nowtv + +// nra : 2014-05-22 NRA Holdings Company, INC. +nra + +// nrw : 2013-11-21 Minds + Machines GmbH +nrw + +// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION +ntt + +// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications +nyc + +// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA +obi + +// observer : 2015-04-30 Top Level Spectrum, Inc. +observer + +// off : 2015-07-23 Johnson Shareholdings, Inc. +off + +// office : 2015-03-12 Microsoft Corporation +office + +// okinawa : 2013-12-05 BRregistry, Inc. +okinawa + +// olayan : 2015-05-14 Crescent Holding GmbH +olayan + +// olayangroup : 2015-05-14 Crescent Holding GmbH +olayangroup + +// oldnavy : 2015-07-31 The Gap, Inc. +oldnavy + +// ollo : 2015-06-04 Dish DBS Corporation +ollo + +// omega : 2015-01-08 The Swatch Group Ltd +omega + +// one : 2014-11-07 One.com A/S +one + +// ong : 2014-03-06 Public Interest Registry +ong + +// onl : 2013-09-16 I-Registry Ltd. +onl + +// online : 2015-01-15 DotOnline Inc. +online + +// onyourside : 2015-07-23 Nationwide Mutual Insurance Company +onyourside + +// ooo : 2014-01-09 INFIBEAM AVENUES LIMITED +ooo + +// open : 2015-07-31 American Express Travel Related Services Company, Inc. +open + +// oracle : 2014-06-19 Oracle Corporation +oracle + +// orange : 2015-03-12 Orange Brand Services Limited +orange + +// organic : 2014-03-27 Afilias Limited +organic + +// origins : 2015-10-01 The Estée Lauder Companies Inc. +origins + +// osaka : 2014-09-04 Osaka Registry Co., Ltd. +osaka + +// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. +otsuka + +// ott : 2015-06-04 Dish DBS Corporation +ott + +// ovh : 2014-01-16 MédiaBC +ovh + +// page : 2014-12-04 Charleston Road Registry Inc. +page + +// panasonic : 2015-07-30 Panasonic Corporation +panasonic + +// paris : 2014-01-30 City of Paris +paris + +// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +pars + +// partners : 2013-12-05 Binky Moon, LLC +partners + +// parts : 2013-12-05 Binky Moon, LLC +parts + +// party : 2014-09-11 Blue Sky Registry Limited +party + +// passagens : 2015-03-05 Travel Reservations SRL +passagens + +// pay : 2015-08-27 Amazon Registry Services, Inc. +pay + +// pccw : 2015-05-14 PCCW Enterprises Limited +pccw + +// pet : 2015-05-07 Afilias Limited +pet + +// pfizer : 2015-09-11 Pfizer Inc. +pfizer + +// pharmacy : 2014-06-19 National Association of Boards of Pharmacy +pharmacy + +// phd : 2016-07-28 Charleston Road Registry Inc. +phd + +// philips : 2014-11-07 Koninklijke Philips N.V. +philips + +// phone : 2016-06-02 Dish DBS Corporation +phone + +// photo : 2013-11-14 Uniregistry, Corp. +photo + +// photography : 2013-09-20 Binky Moon, LLC +photography + +// photos : 2013-10-17 Binky Moon, LLC +photos + +// physio : 2014-05-01 PhysBiz Pty Ltd +physio + +// pics : 2013-11-14 Uniregistry, Corp. +pics + +// pictet : 2014-06-26 Pictet Europe S.A. +pictet + +// pictures : 2014-03-06 Binky Moon, LLC +pictures + +// pid : 2015-01-08 Top Level Spectrum, Inc. +pid + +// pin : 2014-12-18 Amazon Registry Services, Inc. +pin + +// ping : 2015-06-11 Ping Registry Provider, Inc. +ping + +// pink : 2013-10-01 Afilias Limited +pink + +// pioneer : 2015-07-16 Pioneer Corporation +pioneer + +// pizza : 2014-06-26 Binky Moon, LLC +pizza + +// place : 2014-04-24 Binky Moon, LLC +place + +// play : 2015-03-05 Charleston Road Registry Inc. +play + +// playstation : 2015-07-02 Sony Interactive Entertainment Inc. +playstation + +// plumbing : 2013-09-10 Binky Moon, LLC +plumbing + +// plus : 2015-02-05 Binky Moon, LLC +plus + +// pnc : 2015-07-02 PNC Domain Co., LLC +pnc + +// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +pohl + +// poker : 2014-07-03 Afilias Limited +poker + +// politie : 2015-08-20 Politie Nederland +politie + +// porn : 2014-10-16 ICM Registry PN LLC +porn + +// pramerica : 2015-07-30 Prudential Financial, Inc. +pramerica + +// praxi : 2013-12-05 Praxi S.p.A. +praxi + +// press : 2014-04-03 DotPress Inc. +press + +// prime : 2015-06-25 Amazon Registry Services, Inc. +prime + +// prod : 2014-01-23 Charleston Road Registry Inc. +prod + +// productions : 2013-12-05 Binky Moon, LLC +productions + +// prof : 2014-07-24 Charleston Road Registry Inc. +prof + +// progressive : 2015-07-23 Progressive Casualty Insurance Company +progressive + +// promo : 2014-12-18 Afilias Limited +promo + +// properties : 2013-12-05 Binky Moon, LLC +properties + +// property : 2014-05-22 Uniregistry, Corp. +property + +// protection : 2015-04-23 XYZ.COM LLC +protection + +// pru : 2015-07-30 Prudential Financial, Inc. +pru + +// prudential : 2015-07-30 Prudential Financial, Inc. +prudential + +// pub : 2013-12-12 Dog Beach, LLC +pub + +// pwc : 2015-10-29 PricewaterhouseCoopers LLP +pwc + +// qpon : 2013-11-14 dotCOOL, Inc. +qpon + +// quebec : 2013-12-19 PointQuébec Inc +quebec + +// quest : 2015-03-26 XYZ.COM LLC +quest + +// qvc : 2015-07-30 QVC, Inc. +qvc + +// racing : 2014-12-04 Premier Registry Limited +racing + +// radio : 2016-07-21 European Broadcasting Union (EBU) +radio + +// raid : 2015-07-23 Johnson Shareholdings, Inc. +raid + +// read : 2014-12-18 Amazon Registry Services, Inc. +read + +// realestate : 2015-09-11 dotRealEstate LLC +realestate + +// realtor : 2014-05-29 Real Estate Domains LLC +realtor + +// realty : 2015-03-19 Fegistry, LLC +realty + +// recipes : 2013-10-17 Binky Moon, LLC +recipes + +// red : 2013-11-07 Afilias Limited +red + +// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. +redstone + +// redumbrella : 2015-03-26 Travelers TLD, LLC +redumbrella + +// rehab : 2014-03-06 Dog Beach, LLC +rehab + +// reise : 2014-03-13 Binky Moon, LLC +reise + +// reisen : 2014-03-06 Binky Moon, LLC +reisen + +// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. +reit + +// reliance : 2015-04-02 Reliance Industries Limited +reliance + +// ren : 2013-12-12 ZDNS International Limited +ren + +// rent : 2014-12-04 XYZ.COM LLC +rent + +// rentals : 2013-12-05 Binky Moon, LLC +rentals + +// repair : 2013-11-07 Binky Moon, LLC +repair + +// report : 2013-12-05 Binky Moon, LLC +report + +// republican : 2014-03-20 Dog Beach, LLC +republican + +// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +rest + +// restaurant : 2014-07-03 Binky Moon, LLC +restaurant + +// review : 2014-11-20 dot Review Limited +review + +// reviews : 2013-09-13 Dog Beach, LLC +reviews + +// rexroth : 2015-06-18 Robert Bosch GMBH +rexroth + +// rich : 2013-11-21 I-Registry Ltd. +rich + +// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited +richardli + +// ricoh : 2014-11-20 Ricoh Company, Ltd. +ricoh + +// rightathome : 2015-07-23 Johnson Shareholdings, Inc. +rightathome + +// ril : 2015-04-02 Reliance Industries Limited +ril + +// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO +rio + +// rip : 2014-07-10 Dog Beach, LLC +rip + +// rmit : 2015-11-19 Royal Melbourne Institute of Technology +rmit + +// rocher : 2014-12-18 Ferrero Trading Lux S.A. +rocher + +// rocks : 2013-11-14 Dog Beach, LLC +rocks + +// rodeo : 2013-12-19 Minds + Machines Group Limited +rodeo + +// rogers : 2015-08-06 Rogers Communications Canada Inc. +rogers + +// room : 2014-12-18 Amazon Registry Services, Inc. +room + +// rsvp : 2014-05-08 Charleston Road Registry Inc. +rsvp + +// rugby : 2016-12-15 World Rugby Strategic Developments Limited +rugby + +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr + +// run : 2015-03-19 Binky Moon, LLC +run + +// rwe : 2015-04-02 RWE AG +rwe + +// ryukyu : 2014-01-09 BRregistry, Inc. +ryukyu + +// saarland : 2013-12-12 dotSaarland GmbH +saarland + +// safe : 2014-12-18 Amazon Registry Services, Inc. +safe + +// safety : 2015-01-08 Safety Registry Services, LLC. +safety + +// sakura : 2014-12-18 SAKURA Internet Inc. +sakura + +// sale : 2014-10-16 Dog Beach, LLC +sale + +// salon : 2014-12-11 Binky Moon, LLC +salon + +// samsclub : 2015-07-31 Wal-Mart Stores, Inc. +samsclub + +// samsung : 2014-04-03 SAMSUNG SDS CO., LTD +samsung + +// sandvik : 2014-11-13 Sandvik AB +sandvik + +// sandvikcoromant : 2014-11-07 Sandvik AB +sandvikcoromant + +// sanofi : 2014-10-09 Sanofi +sanofi + +// sap : 2014-03-27 SAP AG +sap + +// sarl : 2014-07-03 Binky Moon, LLC +sarl + +// sas : 2015-04-02 Research IP LLC +sas + +// save : 2015-06-25 Amazon Registry Services, Inc. +save + +// saxo : 2014-10-31 Saxo Bank A/S +saxo + +// sbi : 2015-03-12 STATE BANK OF INDIA +sbi + +// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +sbs + +// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) +sca + +// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB") +scb + +// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG +schaeffler + +// schmidt : 2014-04-03 SCHMIDT GROUPE S.A.S. +schmidt + +// scholarships : 2014-04-24 Scholarships.com, LLC +scholarships + +// school : 2014-12-18 Binky Moon, LLC +school + +// schule : 2014-03-06 Binky Moon, LLC +schule + +// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +schwarz + +// science : 2014-09-11 dot Science Limited +science + +// scjohnson : 2015-07-23 Johnson Shareholdings, Inc. +scjohnson + +// scor : 2014-10-31 SCOR SE +scor + +// scot : 2014-01-23 Dot Scot Registry Limited +scot + +// search : 2016-06-09 Charleston Road Registry Inc. +search + +// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) +seat + +// secure : 2015-08-27 Amazon Registry Services, Inc. +secure + +// security : 2015-05-14 XYZ.COM LLC +security + +// seek : 2014-12-04 Seek Limited +seek + +// select : 2015-10-08 Registry Services, LLC +select + +// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. +sener + +// services : 2014-02-27 Binky Moon, LLC +services + +// ses : 2015-07-23 SES +ses + +// seven : 2015-08-06 Seven West Media Ltd +seven + +// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG +sew + +// sex : 2014-11-13 ICM Registry SX LLC +sex + +// sexy : 2013-09-11 Uniregistry, Corp. +sexy + +// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR +sfr + +// shangrila : 2015-09-03 Shangri‐La International Hotel Management Limited +shangrila + +// sharp : 2014-05-01 Sharp Corporation +sharp + +// shaw : 2015-04-23 Shaw Cablesystems G.P. +shaw + +// shell : 2015-07-30 Shell Information Technology International Inc +shell + +// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +shia + +// shiksha : 2013-11-14 Afilias Limited +shiksha + +// shoes : 2013-10-02 Binky Moon, LLC +shoes + +// shop : 2016-04-08 GMO Registry, Inc. +shop + +// shopping : 2016-03-31 Binky Moon, LLC +shopping + +// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +shouji + +// show : 2015-03-05 Binky Moon, LLC +show + +// showtime : 2015-08-06 CBS Domains Inc. +showtime + +// shriram : 2014-01-23 Shriram Capital Ltd. +shriram + +// silk : 2015-06-25 Amazon Registry Services, Inc. +silk + +// sina : 2015-03-12 Sina Corporation +sina + +// singles : 2013-08-27 Binky Moon, LLC +singles + +// site : 2015-01-15 DotSite Inc. +site + +// ski : 2015-04-09 Afilias Limited +ski + +// skin : 2015-01-15 L'Oréal +skin + +// sky : 2014-06-19 Sky International AG +sky + +// skype : 2014-12-18 Microsoft Corporation +skype + +// sling : 2015-07-30 DISH Technologies L.L.C. +sling + +// smart : 2015-07-09 Smart Communications, Inc. (SMART) +smart + +// smile : 2014-12-18 Amazon Registry Services, Inc. +smile + +// sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F +sncf + +// soccer : 2015-03-26 Binky Moon, LLC +soccer + +// social : 2013-11-07 Dog Beach, LLC +social + +// softbank : 2015-07-02 SoftBank Group Corp. +softbank + +// software : 2014-03-20 Dog Beach, LLC +software + +// sohu : 2013-12-19 Sohu.com Limited +sohu + +// solar : 2013-11-07 Binky Moon, LLC +solar + +// solutions : 2013-11-07 Binky Moon, LLC +solutions + +// song : 2015-02-26 Amazon Registry Services, Inc. +song + +// sony : 2015-01-08 Sony Corporation +sony + +// soy : 2014-01-23 Charleston Road Registry Inc. +soy + +// spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited +spa + +// space : 2014-04-03 DotSpace Inc. +space + +// sport : 2017-11-16 Global Association of International Sports Federations (GAISF) +sport + +// spot : 2015-02-26 Amazon Registry Services, Inc. +spot + +// spreadbetting : 2014-12-11 Dotspreadbetting Registry Limited +spreadbetting + +// srl : 2015-05-07 InterNetX, Corp +srl + +// stada : 2014-11-13 STADA Arzneimittel AG +stada + +// staples : 2015-07-30 Staples, Inc. +staples + +// star : 2015-01-08 Star India Private Limited +star + +// statebank : 2015-03-12 STATE BANK OF INDIA +statebank + +// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company +statefarm + +// stc : 2014-10-09 Saudi Telecom Company +stc + +// stcgroup : 2014-10-09 Saudi Telecom Company +stcgroup + +// stockholm : 2014-12-18 Stockholms kommun +stockholm + +// storage : 2014-12-22 XYZ.COM LLC +storage + +// store : 2015-04-09 DotStore Inc. +store + +// stream : 2016-01-08 dot Stream Limited +stream + +// studio : 2015-02-11 Dog Beach, LLC +studio + +// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD +study + +// style : 2014-12-04 Binky Moon, LLC +style + +// sucks : 2014-12-22 Vox Populi Registry Ltd. +sucks + +// supplies : 2013-12-19 Binky Moon, LLC +supplies + +// supply : 2013-12-19 Binky Moon, LLC +supply + +// support : 2013-10-24 Binky Moon, LLC +support + +// surf : 2014-01-09 Minds + Machines Group Limited +surf + +// surgery : 2014-03-20 Binky Moon, LLC +surgery + +// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION +suzuki + +// swatch : 2015-01-08 The Swatch Group Ltd +swatch + +// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited +swiftcover + +// swiss : 2014-10-16 Swiss Confederation +swiss + +// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet +sydney + +// symantec : 2014-12-04 Symantec Corporation +symantec + +// systems : 2013-11-07 Binky Moon, LLC +systems + +// tab : 2014-12-04 Tabcorp Holdings Limited +tab + +// taipei : 2014-07-10 Taipei City Government +taipei + +// talk : 2015-04-09 Amazon Registry Services, Inc. +talk + +// taobao : 2015-01-15 Alibaba Group Holding Limited +taobao + +// target : 2015-07-31 Target Domain Holdings, LLC +target + +// tatamotors : 2015-03-12 Tata Motors Ltd +tatamotors + +// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" +tatar + +// tattoo : 2013-08-30 Uniregistry, Corp. +tattoo + +// tax : 2014-03-20 Binky Moon, LLC +tax + +// taxi : 2015-03-19 Binky Moon, LLC +taxi + +// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +tci + +// tdk : 2015-06-11 TDK Corporation +tdk + +// team : 2015-03-05 Binky Moon, LLC +team + +// tech : 2015-01-30 Personals TLD Inc. +tech + +// technology : 2013-09-13 Binky Moon, LLC +technology + +// telefonica : 2014-10-16 Telefónica S.A. +telefonica + +// temasek : 2014-08-07 Temasek Holdings (Private) Limited +temasek + +// tennis : 2014-12-04 Binky Moon, LLC +tennis + +// teva : 2015-07-02 Teva Pharmaceutical Industries Limited +teva + +// thd : 2015-04-02 Home Depot Product Authority, LLC +thd + +// theater : 2015-03-19 Binky Moon, LLC +theater + +// theatre : 2015-05-07 XYZ.COM LLC +theatre + +// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America +tiaa + +// tickets : 2015-02-05 Accent Media Limited +tickets + +// tienda : 2013-11-14 Binky Moon, LLC +tienda + +// tiffany : 2015-01-30 Tiffany and Company +tiffany + +// tips : 2013-09-20 Binky Moon, LLC +tips + +// tires : 2014-11-07 Binky Moon, LLC +tires + +// tirol : 2014-04-24 punkt Tirol GmbH +tirol + +// tjmaxx : 2015-07-16 The TJX Companies, Inc. +tjmaxx + +// tjx : 2015-07-16 The TJX Companies, Inc. +tjx + +// tkmaxx : 2015-07-16 The TJX Companies, Inc. +tkmaxx + +// tmall : 2015-01-15 Alibaba Group Holding Limited +tmall + +// today : 2013-09-20 Binky Moon, LLC +today + +// tokyo : 2013-11-13 GMO Registry, Inc. +tokyo + +// tools : 2013-11-21 Binky Moon, LLC +tools + +// top : 2014-03-20 .TOP Registry +top + +// toray : 2014-12-18 Toray Industries, Inc. +toray + +// toshiba : 2014-04-10 TOSHIBA Corporation +toshiba + +// total : 2015-08-06 Total SA +total + +// tours : 2015-01-22 Binky Moon, LLC +tours + +// town : 2014-03-06 Binky Moon, LLC +town + +// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION +toyota + +// toys : 2014-03-06 Binky Moon, LLC +toys + +// trade : 2014-01-23 Elite Registry Limited +trade + +// trading : 2014-12-11 Dottrading Registry Limited +trading + +// training : 2013-11-07 Binky Moon, LLC +training + +// travel : Dog Beach, LLC +travel + +// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +travelchannel + +// travelers : 2015-03-26 Travelers TLD, LLC +travelers + +// travelersinsurance : 2015-03-26 Travelers TLD, LLC +travelersinsurance + +// trust : 2014-10-16 NCC Group Inc. +trust + +// trv : 2015-03-26 Travelers TLD, LLC +trv + +// tube : 2015-06-11 Latin American Telecom LLC +tube + +// tui : 2014-07-03 TUI AG +tui + +// tunes : 2015-02-26 Amazon Registry Services, Inc. +tunes + +// tushu : 2014-12-18 Amazon Registry Services, Inc. +tushu + +// tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED +tvs + +// ubank : 2015-08-20 National Australia Bank Limited +ubank + +// ubs : 2014-12-11 UBS AG +ubs + +// unicom : 2015-10-15 China United Network Communications Corporation Limited +unicom + +// university : 2014-03-06 Binky Moon, LLC +university + +// uno : 2013-09-11 DotSite Inc. +uno + +// uol : 2014-05-01 UBN INTERNET LTDA. +uol + +// ups : 2015-06-25 UPS Market Driver, Inc. +ups + +// vacations : 2013-12-05 Binky Moon, LLC +vacations + +// vana : 2014-12-11 Lifestyle Domain Holdings, Inc. +vana + +// vanguard : 2015-09-03 The Vanguard Group, Inc. +vanguard + +// vegas : 2014-01-16 Dot Vegas, Inc. +vegas + +// ventures : 2013-08-27 Binky Moon, LLC +ventures + +// verisign : 2015-08-13 VeriSign, Inc. +verisign + +// versicherung : 2014-03-20 tldbox GmbH +versicherung + +// vet : 2014-03-06 Dog Beach, LLC +vet + +// viajes : 2013-10-17 Binky Moon, LLC +viajes + +// video : 2014-10-16 Dog Beach, LLC +video + +// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe +vig + +// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd. +viking + +// villas : 2013-12-05 Binky Moon, LLC +villas + +// vin : 2015-06-18 Binky Moon, LLC +vin + +// vip : 2015-01-22 Minds + Machines Group Limited +vip + +// virgin : 2014-09-25 Virgin Enterprises Limited +virgin + +// visa : 2015-07-30 Visa Worldwide Pte. Limited +visa + +// vision : 2013-12-05 Binky Moon, LLC +vision + +// vistaprint : 2014-09-18 Vistaprint Limited +vistaprint + +// viva : 2014-11-07 Saudi Telecom Company +viva + +// vivo : 2015-07-31 Telefonica Brasil S.A. +vivo + +// vlaanderen : 2014-02-06 DNS.be vzw +vlaanderen + +// vodka : 2013-12-19 Minds + Machines Group Limited +vodka + +// volkswagen : 2015-05-14 Volkswagen Group of America Inc. +volkswagen + +// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag +volvo + +// vote : 2013-11-21 Monolith Registry LLC +vote + +// voting : 2013-11-13 Valuetainment Corp. +voting + +// voto : 2013-11-21 Monolith Registry LLC +voto + +// voyage : 2013-08-27 Binky Moon, LLC +voyage + +// vuelos : 2015-03-05 Travel Reservations SRL +vuelos + +// wales : 2014-05-08 Nominet UK +wales + +// walmart : 2015-07-31 Wal-Mart Stores, Inc. +walmart + +// walter : 2014-11-13 Sandvik AB +walter + +// wang : 2013-10-24 Zodiac Wang Limited +wang + +// wanggou : 2014-12-18 Amazon Registry Services, Inc. +wanggou + +// watch : 2013-11-14 Binky Moon, LLC +watch + +// watches : 2014-12-22 Richemont DNS Inc. +watches + +// weather : 2015-01-08 International Business Machines Corporation +weather + +// weatherchannel : 2015-03-12 International Business Machines Corporation +weatherchannel + +// webcam : 2014-01-23 dot Webcam Limited +webcam + +// weber : 2015-06-04 Saint-Gobain Weber SA +weber + +// website : 2014-04-03 DotWebsite Inc. +website + +// wed : 2013-10-01 Atgron, Inc. +wed + +// wedding : 2014-04-24 Minds + Machines Group Limited +wedding + +// weibo : 2015-03-05 Sina Corporation +weibo + +// weir : 2015-01-29 Weir Group IP Limited +weir + +// whoswho : 2014-02-20 Who's Who Registry +whoswho + +// wien : 2013-10-28 punkt.wien GmbH +wien + +// wiki : 2013-11-07 Top Level Design, LLC +wiki + +// williamhill : 2014-03-13 William Hill Organization Limited +williamhill + +// win : 2014-11-20 First Registry Limited +win + +// windows : 2014-12-18 Microsoft Corporation +windows + +// wine : 2015-06-18 Binky Moon, LLC +wine + +// winners : 2015-07-16 The TJX Companies, Inc. +winners + +// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC +wme + +// wolterskluwer : 2015-08-06 Wolters Kluwer N.V. +wolterskluwer + +// woodside : 2015-07-09 Woodside Petroleum Limited +woodside + +// work : 2013-12-19 Minds + Machines Group Limited +work + +// works : 2013-11-14 Binky Moon, LLC +works + +// world : 2014-06-12 Binky Moon, LLC +world + +// wow : 2015-10-08 Amazon Registry Services, Inc. +wow + +// wtc : 2013-12-19 World Trade Centers Association, Inc. +wtc + +// wtf : 2014-03-06 Binky Moon, LLC +wtf + +// xbox : 2014-12-18 Microsoft Corporation +xbox + +// xerox : 2014-10-24 Xerox DNHC LLC +xerox + +// xfinity : 2015-07-09 Comcast IP Holdings I, LLC +xfinity + +// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +xihuan + +// xin : 2014-12-11 Elegant Leader Limited +xin + +// xn--11b4c3d : 2015-01-15 VeriSign Sarl +कॉम + +// xn--1ck2e1b : 2015-02-26 Amazon Registry Services, Inc. +セール + +// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. +佛山 + +// xn--30rr7y : 2014-06-12 Excellent First Limited +慈善 + +// xn--3bst00m : 2013-09-13 Eagle Horizon Limited +集团 + +// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY +在线 + +// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. +大众汽车 + +// xn--3pxu8k : 2015-01-15 VeriSign Sarl +点看 + +// xn--42c2d9a : 2015-01-15 VeriSign Sarl +คอม + +// xn--45q11c : 2013-11-21 Zodiac Gemini Ltd +八卦 + +// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment +موقع + +// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center +公益 + +// xn--55qx5d : 2013-11-14 China Internet Network Information Center (CNNIC) +公司 + +// xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited +香格里拉 + +// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited +网站 + +// xn--6frz82g : 2013-09-23 Afilias Limited +移动 + +// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited +我爱你 + +// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +москва + +// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +католик + +// xn--80asehdb : 2013-07-14 CORE Association +онлайн + +// xn--80aswg : 2013-07-14 CORE Association +сайт + +// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited +联通 + +// xn--9dbq2a : 2015-01-15 VeriSign Sarl +קום + +// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED +时尚 + +// xn--9krt00a : 2015-03-12 Sina Corporation +微博 + +// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited +淡马锡 + +// xn--bck1b9a5dre4c : 2015-02-26 Amazon Registry Services, Inc. +ファッション + +// xn--c1avg : 2013-11-14 Public Interest Registry +орг + +// xn--c2br7g : 2015-01-15 VeriSign Sarl +नेट + +// xn--cck2b3b : 2015-02-26 Amazon Registry Services, Inc. +ストア + +// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD +삼성 + +// xn--czr694b : 2014-01-16 Internet DotTrademark Organisation Limited +商标 + +// xn--czrs0t : 2013-12-19 Binky Moon, LLC +商店 + +// xn--czru2d : 2013-11-21 Zodiac Aquarius Limited +商城 + +// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” +дети + +// xn--eckvdtc9d : 2014-12-18 Amazon Registry Services, Inc. +ポイント + +// xn--efvy88h : 2014-08-22 Guangzhou YU Wei Information Technology Co., Ltd. +新闻 + +// xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited +工行 + +// xn--fct429k : 2015-04-09 Amazon Registry Services, Inc. +家電 + +// xn--fhbei : 2015-01-15 VeriSign Sarl +كوم + +// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED OY +中文网 + +// xn--fiq64b : 2013-10-14 CITIC Group Corporation +中信 + +// xn--fjq720a : 2014-05-22 Binky Moon, LLC +娱乐 + +// xn--flw351e : 2014-07-31 Charleston Road Registry Inc. +谷歌 + +// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited +電訊盈科 + +// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +购物 + +// xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc. +クラウド + +// xn--gk3at1e : 2015-10-08 Amazon Registry Services, Inc. +通販 + +// xn--hxt814e : 2014-05-15 Zodiac Taurus Limited +网店 + +// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry +संगठन + +// xn--imr513n : 2014-12-11 Internet DotTrademark Organisation Limited +餐厅 + +// xn--io0a7i : 2013-11-14 China Internet Network Information Center (CNNIC) +网络 + +// xn--j1aef : 2015-01-15 VeriSign Sarl +ком + +// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation +诺基亚 + +// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc. +食品 + +// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. +飞利浦 + +// xn--kpu716f : 2014-12-22 Richemont DNS Inc. +手表 + +// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd +手机 + +// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company +ارامكو + +// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH +العليان + +// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +اتصالات + +// xn--mgbab2bd : 2013-10-31 CORE Association +بازار + +// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre +ابوظبي + +// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +كاثوليك + +// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +همراه + +// xn--mk1bu44c : 2015-01-15 VeriSign Sarl +닷컴 + +// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd. +政府 + +// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd. +شبكة + +// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House +بيتك + +// xn--ngbrx : 2015-11-12 League of Arab States +عرب + +// xn--nqv7f : 2013-11-14 Public Interest Registry +机构 + +// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry +组织机构 + +// xn--nyqy26a : 2014-11-07 Stable Tone Limited +健康 + +// xn--otu796d : 2017-08-06 Internet DotTrademark Organisation Limited +招聘 + +// xn--p1acf : 2013-12-12 Rusnames Limited +рус + +// xn--pbt977c : 2014-12-22 Richemont DNS Inc. +珠宝 + +// xn--pssy2u : 2015-01-15 VeriSign Sarl +大拿 + +// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc. +みんな + +// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc. +グーグル + +// xn--rhqv96g : 2013-09-11 Stable Tone Limited +世界 + +// xn--rovu88b : 2015-02-26 Amazon Registry Services, Inc. +書籍 + +// xn--ses554g : 2014-01-16 KNET Co., Ltd. +网址 + +// xn--t60b56a : 2015-01-15 VeriSign Sarl +닷넷 + +// xn--tckwe : 2015-01-15 VeriSign Sarl +コム + +// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +天主教 + +// xn--unup4y : 2013-07-14 Binky Moon, LLC +游戏 + +// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberater + +// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberatung + +// xn--vhquv : 2013-08-27 Binky Moon, LLC +企业 + +// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. +信息 + +// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited +嘉里大酒店 + +// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited +嘉里 + +// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. +广东 + +// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center +政务 + +// xyz : 2013-12-05 XYZ.COM LLC +xyz + +// yachts : 2014-01-09 DERYachts, LLC +yachts + +// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +yahoo + +// yamaxun : 2014-12-18 Amazon Registry Services, Inc. +yamaxun + +// yandex : 2014-04-10 YANDEX, LLC +yandex + +// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +yodobashi + +// yoga : 2014-05-29 Minds + Machines Group Limited +yoga + +// yokohama : 2013-12-12 GMO Registry, Inc. +yokohama + +// you : 2015-04-09 Amazon Registry Services, Inc. +you + +// youtube : 2014-05-01 Charleston Road Registry Inc. +youtube + +// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +yun + +// zappos : 2015-06-25 Amazon Registry Services, Inc. +zappos + +// zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.) +zara + +// zero : 2014-12-18 Amazon Registry Services, Inc. +zero + +// zip : 2014-05-08 Charleston Road Registry Inc. +zip + +// zone : 2013-11-14 Binky Moon, LLC +zone + +// zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich) +zuerich + + +// ===END ICANN DOMAINS=== +// ===BEGIN PRIVATE DOMAINS=== +// (Note: these are in alphabetical order by company name) + +// 1GB LLC : https://www.1gb.ua/ +// Submitted by 1GB LLC +cc.ua +inf.ua +ltd.ua + +// Agnat sp. z o.o. : https://domena.pl +// Submitted by Przemyslaw Plewa +beep.pl + +// alboto.ca : http://alboto.ca +// Submitted by Anton Avramov +barsy.ca + +// Alces Software Ltd : http://alces-software.com +// Submitted by Mark J. Titorenko +*.compute.estate +*.alces.network + +// Altervista: https://www.altervista.org +// Submitted by Carlo Cannas +altervista.org + +// alwaysdata : https://www.alwaysdata.com +// Submitted by Cyril +alwaysdata.net + +// Amazon CloudFront : https://aws.amazon.com/cloudfront/ +// Submitted by Donavan Miller +cloudfront.net + +// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/ +// Submitted by Luke Wells +*.compute.amazonaws.com +*.compute-1.amazonaws.com +*.compute.amazonaws.com.cn +us-east-1.amazonaws.com + +// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ +// Submitted by Luke Wells +cn-north-1.eb.amazonaws.com.cn +cn-northwest-1.eb.amazonaws.com.cn +elasticbeanstalk.com +ap-northeast-1.elasticbeanstalk.com +ap-northeast-2.elasticbeanstalk.com +ap-northeast-3.elasticbeanstalk.com +ap-south-1.elasticbeanstalk.com +ap-southeast-1.elasticbeanstalk.com +ap-southeast-2.elasticbeanstalk.com +ca-central-1.elasticbeanstalk.com +eu-central-1.elasticbeanstalk.com +eu-west-1.elasticbeanstalk.com +eu-west-2.elasticbeanstalk.com +eu-west-3.elasticbeanstalk.com +sa-east-1.elasticbeanstalk.com +us-east-1.elasticbeanstalk.com +us-east-2.elasticbeanstalk.com +us-gov-west-1.elasticbeanstalk.com +us-west-1.elasticbeanstalk.com +us-west-2.elasticbeanstalk.com + +// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ +// Submitted by Luke Wells +*.elb.amazonaws.com +*.elb.amazonaws.com.cn + +// Amazon S3 : https://aws.amazon.com/s3/ +// Submitted by Luke Wells +s3.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-south-1.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-ca-central-1.amazonaws.com +s3-eu-central-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-eu-west-2.amazonaws.com +s3-eu-west-3.amazonaws.com +s3-external-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-us-east-2.amazonaws.com +s3-us-west-1.amazonaws.com +s3-us-west-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3.ap-south-1.amazonaws.com +s3.cn-north-1.amazonaws.com.cn +s3.ca-central-1.amazonaws.com +s3.eu-central-1.amazonaws.com +s3.eu-west-2.amazonaws.com +s3.eu-west-3.amazonaws.com +s3.us-east-2.amazonaws.com +s3.dualstack.ap-northeast-1.amazonaws.com +s3.dualstack.ap-northeast-2.amazonaws.com +s3.dualstack.ap-south-1.amazonaws.com +s3.dualstack.ap-southeast-1.amazonaws.com +s3.dualstack.ap-southeast-2.amazonaws.com +s3.dualstack.ca-central-1.amazonaws.com +s3.dualstack.eu-central-1.amazonaws.com +s3.dualstack.eu-west-1.amazonaws.com +s3.dualstack.eu-west-2.amazonaws.com +s3.dualstack.eu-west-3.amazonaws.com +s3.dualstack.sa-east-1.amazonaws.com +s3.dualstack.us-east-1.amazonaws.com +s3.dualstack.us-east-2.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website.ap-northeast-2.amazonaws.com +s3-website.ap-south-1.amazonaws.com +s3-website.ca-central-1.amazonaws.com +s3-website.eu-central-1.amazonaws.com +s3-website.eu-west-2.amazonaws.com +s3-website.eu-west-3.amazonaws.com +s3-website.us-east-2.amazonaws.com + +// Amune : https://amune.org/ +// Submitted by Team Amune +t3l3p0rt.net +tele.amune.org + +// Apigee : https://apigee.com/ +// Submitted by Apigee Security Team +apigee.io + +// Aptible : https://www.aptible.com/ +// Submitted by Thomas Orozco +on-aptible.com + +// ASEINet : https://www.aseinet.com/ +// Submitted by Asei SEKIGUCHI +user.aseinet.ne.jp +gv.vc +d.gv.vc + +// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/ +// Submitted by Hector Martin +user.party.eus + +// Association potager.org : https://potager.org/ +// Submitted by Lunar +pimienta.org +poivron.org +potager.org +sweetpepper.org + +// ASUSTOR Inc. : http://www.asustor.com +// Submitted by Vincent Tseng +myasustor.com + +// AVM : https://avm.de +// Submitted by Andreas Weise +myfritz.net + +// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com +// Submitted by James Kennedy +*.awdev.ca +*.advisor.ws + +// b-data GmbH : https://www.b-data.io +// Submitted by Olivier Benz +b-data.io + +// backplane : https://www.backplane.io +// Submitted by Anthony Voutas +backplaneapp.io + +// Balena : https://www.balena.io +// Submitted by Petros Angelatos +balena-devices.com + +// Banzai Cloud +// Submitted by Gabor Kozma +app.banzaicloud.io + +// BetaInABox +// Submitted by Adrian +betainabox.com + +// BinaryLane : http://www.binarylane.com +// Submitted by Nathan O'Sullivan +bnr.la + +// Blackbaud, Inc. : https://www.blackbaud.com +// Submitted by Paul Crowder +blackbaudcdn.net + +// Boomla : https://boomla.com +// Submitted by Tibor Halter +boomla.net + +// Boxfuse : https://boxfuse.com +// Submitted by Axel Fontaine +boxfuse.io + +// bplaced : https://www.bplaced.net/ +// Submitted by Miroslav Bozic +square7.ch +bplaced.com +bplaced.de +square7.de +bplaced.net +square7.net + +// BrowserSafetyMark +// Submitted by Dave Tharp +browsersafetymark.io + +// Bytemark Hosting : https://www.bytemark.co.uk +// Submitted by Paul Cammish +uk0.bigv.io +dh.bytemark.co.uk +vm.bytemark.co.uk + +// callidomus : https://www.callidomus.com/ +// Submitted by Marcus Popp +mycd.eu + +// Carrd : https://carrd.co +// Submitted by AJ +carrd.co +crd.co +uwu.ai + +// CentralNic : http://www.centralnic.com/names/domains +// Submitted by registry +ae.org +ar.com +br.com +cn.com +com.de +com.se +de.com +eu.com +gb.com +gb.net +hu.com +hu.net +jp.net +jpn.com +kr.com +mex.com +no.com +qc.com +ru.com +sa.com +se.net +uk.com +uk.net +us.com +uy.com +za.bz +za.com + +// Africa.com Web Solutions Ltd : https://registry.africa.com +// Submitted by Gavin Brown +africa.com + +// iDOT Services Limited : http://www.domain.gr.com +// Submitted by Gavin Brown +gr.com + +// Radix FZC : http://domains.in.net +// Submitted by Gavin Brown +in.net + +// US REGISTRY LLC : http://us.org +// Submitted by Gavin Brown +us.org + +// co.com Registry, LLC : https://registry.co.com +// Submitted by Gavin Brown +co.com + +// c.la : http://www.c.la/ +c.la + +// certmgr.org : https://certmgr.org +// Submitted by B. Blechschmidt +certmgr.org + +// Citrix : https://citrix.com +// Submitted by Alex Stoddard +xenapponazure.com + +// Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ +// Submitted by Rishabh Nambiar +discourse.group + +// ClearVox : http://www.clearvox.nl/ +// Submitted by Leon Rowland +virtueeldomein.nl + +// Clever Cloud : https://www.clever-cloud.com/ +// Submitted by Quentin Adam +cleverapps.io + +// Clerk : https://www.clerk.dev +// Submitted by Colin Sidoti +*.lcl.dev +*.stg.dev + +// Cloud66 : https://www.cloud66.com/ +// Submitted by Khash Sajadi +c66.me +cloud66.ws +cloud66.zone + +// CloudAccess.net : https://www.cloudaccess.net/ +// Submitted by Pawel Panek +jdevcloud.com +wpdevcloud.com +cloudaccess.host +freesite.host +cloudaccess.net + +// cloudControl : https://www.cloudcontrol.com/ +// Submitted by Tobias Wilken +cloudcontrolled.com +cloudcontrolapp.com + +// Cloudera, Inc. : https://www.cloudera.com/ +// Submitted by Philip Langdale +cloudera.site + +// Cloudflare, Inc. : https://www.cloudflare.com/ +// Submitted by Jake Riesterer +trycloudflare.com +workers.dev + +// Clovyr : https://clovyr.io +// Submitted by Patrick Nielsen +wnext.app + +// co.ca : http://registry.co.ca/ +co.ca + +// Co & Co : https://co-co.nl/ +// Submitted by Govert Versluis +*.otap.co + +// i-registry s.r.o. : http://www.i-registry.cz/ +// Submitted by Martin Semrad +co.cz + +// CDN77.com : http://www.cdn77.com +// Submitted by Jan Krpes +c.cdn77.org +cdn77-ssl.net +r.cdn77.net +rsc.cdn77.org +ssl.origin.cdn77-secure.org + +// Cloud DNS Ltd : http://www.cloudns.net +// Submitted by Aleksander Hristov +cloudns.asia +cloudns.biz +cloudns.club +cloudns.cc +cloudns.eu +cloudns.in +cloudns.info +cloudns.org +cloudns.pro +cloudns.pw +cloudns.us + +// Cloudeity Inc : https://cloudeity.com +// Submitted by Stefan Dimitrov +cloudeity.net + +// CNPY : https://cnpy.gdn +// Submitted by Angelo Gladding +cnpy.gdn + +// CoDNS B.V. +co.nl +co.no + +// Combell.com : https://www.combell.com +// Submitted by Thomas Wouters +webhosting.be +hosting-cluster.nl + +// COSIMO GmbH : http://www.cosimo.de +// Submitted by Rene Marticke +dyn.cosidns.de +dynamisches-dns.de +dnsupdater.de +internet-dns.de +l-o-g-i-n.de +dynamic-dns.info +feste-ip.net +knx-server.net +static-access.net + +// Craynic, s.r.o. : http://www.craynic.com/ +// Submitted by Ales Krajnik +realm.cz + +// Cryptonomic : https://cryptonomic.net/ +// Submitted by Andrew Cady +*.cryptonomic.net + +// Cupcake : https://cupcake.io/ +// Submitted by Jonathan Rudenberg +cupcake.is + +// cyon GmbH : https://www.cyon.ch/ +// Submitted by Dominic Luechinger +cyon.link +cyon.site + +// Daplie, Inc : https://daplie.com +// Submitted by AJ ONeal +daplie.me +localhost.daplie.me + +// Datto, Inc. : https://www.datto.com/ +// Submitted by Philipp Heckel +dattolocal.com +dattorelay.com +dattoweb.com +mydatto.com +dattolocal.net +mydatto.net + +// Dansk.net : http://www.dansk.net/ +// Submitted by Anani Voule +biz.dk +co.dk +firm.dk +reg.dk +store.dk + +// dapps.earth : https://dapps.earth/ +// Submitted by Daniil Burdakov +*.dapps.earth +*.bzz.dapps.earth + +// Debian : https://www.debian.org/ +// Submitted by Peter Palfrader / Debian Sysadmin Team +debian.net + +// deSEC : https://desec.io/ +// Submitted by Peter Thomassen +dedyn.io + +// DNShome : https://www.dnshome.de/ +// Submitted by Norbert Auler +dnshome.de + +// DotArai : https://www.dotarai.com/ +// Submitted by Atsadawat Netcharadsang +online.th +shop.th + +// DrayTek Corp. : https://www.draytek.com/ +// Submitted by Paul Fang +drayddns.com + +// DreamHost : http://www.dreamhost.com/ +// Submitted by Andrew Farmer +dreamhosters.com + +// Drobo : http://www.drobo.com/ +// Submitted by Ricardo Padilha +mydrobo.com + +// Drud Holdings, LLC. : https://www.drud.com/ +// Submitted by Kevin Bridges +drud.io +drud.us + +// DuckDNS : http://www.duckdns.org/ +// Submitted by Richard Harper +duckdns.org + +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen +dy.fi +tunk.org + +// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ +dyndns-at-home.com +dyndns-at-work.com +dyndns-blog.com +dyndns-free.com +dyndns-home.com +dyndns-ip.com +dyndns-mail.com +dyndns-office.com +dyndns-pics.com +dyndns-remote.com +dyndns-server.com +dyndns-web.com +dyndns-wiki.com +dyndns-work.com +dyndns.biz +dyndns.info +dyndns.org +dyndns.tv +at-band-camp.net +ath.cx +barrel-of-knowledge.info +barrell-of-knowledge.info +better-than.tv +blogdns.com +blogdns.net +blogdns.org +blogsite.org +boldlygoingnowhere.org +broke-it.net +buyshouses.net +cechire.com +dnsalias.com +dnsalias.net +dnsalias.org +dnsdojo.com +dnsdojo.net +dnsdojo.org +does-it.net +doesntexist.com +doesntexist.org +dontexist.com +dontexist.net +dontexist.org +doomdns.com +doomdns.org +dvrdns.org +dyn-o-saur.com +dynalias.com +dynalias.net +dynalias.org +dynathome.net +dyndns.ws +endofinternet.net +endofinternet.org +endoftheinternet.org +est-a-la-maison.com +est-a-la-masion.com +est-le-patron.com +est-mon-blogueur.com +for-better.biz +for-more.biz +for-our.info +for-some.biz +for-the.biz +forgot.her.name +forgot.his.name +from-ak.com +from-al.com +from-ar.com +from-az.net +from-ca.com +from-co.net +from-ct.com +from-dc.com +from-de.com +from-fl.com +from-ga.com +from-hi.com +from-ia.com +from-id.com +from-il.com +from-in.com +from-ks.com +from-ky.com +from-la.net +from-ma.com +from-md.com +from-me.org +from-mi.com +from-mn.com +from-mo.com +from-ms.com +from-mt.com +from-nc.com +from-nd.com +from-ne.com +from-nh.com +from-nj.com +from-nm.com +from-nv.com +from-ny.net +from-oh.com +from-ok.com +from-or.com +from-pa.com +from-pr.com +from-ri.com +from-sc.com +from-sd.com +from-tn.com +from-tx.com +from-ut.com +from-va.com +from-vt.com +from-wa.com +from-wi.com +from-wv.com +from-wy.com +ftpaccess.cc +fuettertdasnetz.de +game-host.org +game-server.cc +getmyip.com +gets-it.net +go.dyndns.org +gotdns.com +gotdns.org +groks-the.info +groks-this.info +ham-radio-op.net +here-for-more.info +hobby-site.com +hobby-site.org +home.dyndns.org +homedns.org +homeftp.net +homeftp.org +homeip.net +homelinux.com +homelinux.net +homelinux.org +homeunix.com +homeunix.net +homeunix.org +iamallama.com +in-the-band.net +is-a-anarchist.com +is-a-blogger.com +is-a-bookkeeper.com +is-a-bruinsfan.org +is-a-bulls-fan.com +is-a-candidate.org +is-a-caterer.com +is-a-celticsfan.org +is-a-chef.com +is-a-chef.net +is-a-chef.org +is-a-conservative.com +is-a-cpa.com +is-a-cubicle-slave.com +is-a-democrat.com +is-a-designer.com +is-a-doctor.com +is-a-financialadvisor.com +is-a-geek.com +is-a-geek.net +is-a-geek.org +is-a-green.com +is-a-guru.com +is-a-hard-worker.com +is-a-hunter.com +is-a-knight.org +is-a-landscaper.com +is-a-lawyer.com +is-a-liberal.com +is-a-libertarian.com +is-a-linux-user.org +is-a-llama.com +is-a-musician.com +is-a-nascarfan.com +is-a-nurse.com +is-a-painter.com +is-a-patsfan.org +is-a-personaltrainer.com +is-a-photographer.com +is-a-player.com +is-a-republican.com +is-a-rockstar.com +is-a-socialist.com +is-a-soxfan.org +is-a-student.com +is-a-teacher.com +is-a-techie.com +is-a-therapist.com +is-an-accountant.com +is-an-actor.com +is-an-actress.com +is-an-anarchist.com +is-an-artist.com +is-an-engineer.com +is-an-entertainer.com +is-by.us +is-certified.com +is-found.org +is-gone.com +is-into-anime.com +is-into-cars.com +is-into-cartoons.com +is-into-games.com +is-leet.com +is-lost.org +is-not-certified.com +is-saved.org +is-slick.com +is-uberleet.com +is-very-bad.org +is-very-evil.org +is-very-good.org +is-very-nice.org +is-very-sweet.org +is-with-theband.com +isa-geek.com +isa-geek.net +isa-geek.org +isa-hockeynut.com +issmarterthanyou.com +isteingeek.de +istmein.de +kicks-ass.net +kicks-ass.org +knowsitall.info +land-4-sale.us +lebtimnetz.de +leitungsen.de +likes-pie.com +likescandy.com +merseine.nu +mine.nu +misconfused.org +mypets.ws +myphotos.cc +neat-url.com +office-on-the.net +on-the-web.tv +podzone.net +podzone.org +readmyblog.org +saves-the-whales.com +scrapper-site.net +scrapping.cc +selfip.biz +selfip.com +selfip.info +selfip.net +selfip.org +sells-for-less.com +sells-for-u.com +sells-it.net +sellsyourhome.org +servebbs.com +servebbs.net +servebbs.org +serveftp.net +serveftp.org +servegame.org +shacknet.nu +simple-url.com +space-to-rent.com +stuff-4-sale.org +stuff-4-sale.us +teaches-yoga.com +thruhere.net +traeumtgerade.de +webhop.biz +webhop.info +webhop.net +webhop.org +worse-than.tv +writesthisblog.com + +// ddnss.de : https://www.ddnss.de/ +// Submitted by Robert Niedziela +ddnss.de +dyn.ddnss.de +dyndns.ddnss.de +dyndns1.de +dyn-ip24.de +home-webserver.de +dyn.home-webserver.de +myhome-server.de +ddnss.org + +// Definima : http://www.definima.com/ +// Submitted by Maxence Bitterli +definima.net +definima.io + +// dnstrace.pro : https://dnstrace.pro/ +// Submitted by Chris Partridge +bci.dnstrace.pro + +// Dynu.com : https://www.dynu.com/ +// Submitted by Sue Ye +ddnsfree.com +ddnsgeek.com +giize.com +gleeze.com +kozow.com +loseyourip.com +ooguy.com +theworkpc.com +casacam.net +dynu.net +accesscam.org +camdvr.org +freeddns.org +mywire.org +webredirect.org +myddns.rocks +blogsite.xyz + +// dynv6 : https://dynv6.com +// Submitted by Dominik Menke +dynv6.net + +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr +e4.cz + +// Enalean SAS: https://www.enalean.com +// Submitted by Thomas Cottier +mytuleap.com + +// ECG Robotics, Inc: https://ecgrobotics.org +// Submitted by +onred.one +staging.onred.one + +// Enonic : http://enonic.com/ +// Submitted by Erik Kaareng-Sunde +enonic.io +customer.enonic.io + +// EU.org https://eu.org/ +// Submitted by Pierre Beyssac +eu.org +al.eu.org +asso.eu.org +at.eu.org +au.eu.org +be.eu.org +bg.eu.org +ca.eu.org +cd.eu.org +ch.eu.org +cn.eu.org +cy.eu.org +cz.eu.org +de.eu.org +dk.eu.org +edu.eu.org +ee.eu.org +es.eu.org +fi.eu.org +fr.eu.org +gr.eu.org +hr.eu.org +hu.eu.org +ie.eu.org +il.eu.org +in.eu.org +int.eu.org +is.eu.org +it.eu.org +jp.eu.org +kr.eu.org +lt.eu.org +lu.eu.org +lv.eu.org +mc.eu.org +me.eu.org +mk.eu.org +mt.eu.org +my.eu.org +net.eu.org +ng.eu.org +nl.eu.org +no.eu.org +nz.eu.org +paris.eu.org +pl.eu.org +pt.eu.org +q-a.eu.org +ro.eu.org +ru.eu.org +se.eu.org +si.eu.org +sk.eu.org +tr.eu.org +uk.eu.org +us.eu.org + +// Evennode : http://www.evennode.com/ +// Submitted by Michal Kralik +eu-1.evennode.com +eu-2.evennode.com +eu-3.evennode.com +eu-4.evennode.com +us-1.evennode.com +us-2.evennode.com +us-3.evennode.com +us-4.evennode.com + +// eDirect Corp. : https://hosting.url.com.tw/ +// Submitted by C.S. chang +twmail.cc +twmail.net +twmail.org +mymailer.com.tw +url.tw + +// Facebook, Inc. +// Submitted by Peter Ruibal +apps.fbsbx.com + +// FAITID : https://faitid.org/ +// Submitted by Maxim Alzoba +// https://www.flexireg.net/stat_info +ru.net +adygeya.ru +bashkiria.ru +bir.ru +cbg.ru +com.ru +dagestan.ru +grozny.ru +kalmykia.ru +kustanai.ru +marine.ru +mordovia.ru +msk.ru +mytis.ru +nalchik.ru +nov.ru +pyatigorsk.ru +spb.ru +vladikavkaz.ru +vladimir.ru +abkhazia.su +adygeya.su +aktyubinsk.su +arkhangelsk.su +armenia.su +ashgabad.su +azerbaijan.su +balashov.su +bashkiria.su +bryansk.su +bukhara.su +chimkent.su +dagestan.su +east-kazakhstan.su +exnet.su +georgia.su +grozny.su +ivanovo.su +jambyl.su +kalmykia.su +kaluga.su +karacol.su +karaganda.su +karelia.su +khakassia.su +krasnodar.su +kurgan.su +kustanai.su +lenug.su +mangyshlak.su +mordovia.su +msk.su +murmansk.su +nalchik.su +navoi.su +north-kazakhstan.su +nov.su +obninsk.su +penza.su +pokrovsk.su +sochi.su +spb.su +tashkent.su +termez.su +togliatti.su +troitsk.su +tselinograd.su +tula.su +tuva.su +vladikavkaz.su +vladimir.su +vologda.su + +// Fancy Bits, LLC : http://getchannels.com +// Submitted by Aman Gupta +channelsdvr.net + +// Fastly Inc. : http://www.fastly.com/ +// Submitted by Fastly Security +fastly-terrarium.com +fastlylb.net +map.fastlylb.net +freetls.fastly.net +map.fastly.net +a.prod.fastly.net +global.prod.fastly.net +a.ssl.fastly.net +b.ssl.fastly.net +global.ssl.fastly.net + +// FASTVPS EESTI OU : https://fastvps.ru/ +// Submitted by Likhachev Vasiliy +fastpanel.direct +fastvps-server.com + +// Featherhead : https://featherhead.xyz/ +// Submitted by Simon Menke +fhapp.xyz + +// Fedora : https://fedoraproject.org/ +// submitted by Patrick Uiterwijk +fedorainfracloud.org +fedorapeople.org +cloud.fedoraproject.org +app.os.fedoraproject.org +app.os.stg.fedoraproject.org + +// Fermax : https://fermax.com/ +// submitted by Koen Van Isterdael +mydobiss.com + +// Filegear Inc. : https://www.filegear.com +// Submitted by Jason Zhu +filegear.me +filegear-au.me +filegear-de.me +filegear-gb.me +filegear-ie.me +filegear-jp.me +filegear-sg.me + +// Firebase, Inc. +// Submitted by Chris Raynor +firebaseapp.com + +// Flynn : https://flynn.io +// Submitted by Jonathan Rudenberg +flynnhub.com +flynnhosting.net + +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + +// freedesktop.org : https://www.freedesktop.org +// Submitted by Daniel Stone +freedesktop.org + +// Futureweb OG : http://www.futureweb.at +// Submitted by Andreas Schnederle-Wagner +*.futurecms.at +*.ex.futurecms.at +*.in.futurecms.at +futurehosting.at +futuremailing.at +*.ex.ortsinfo.at +*.kunden.ortsinfo.at +*.statics.cloud + +// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains +// Submitted by David Illsley +service.gov.uk + +// Gehirn Inc. : https://www.gehirn.co.jp/ +// Submitted by Kohei YOSHIDA +gehirn.ne.jp +usercontent.jp + +// Gentlent, Limited : https://www.gentlent.com +// Submitted by Tom Klein +lab.ms + +// GitHub, Inc. +// Submitted by Patrick Toomey +github.io +githubusercontent.com + +// GitLab, Inc. +// Submitted by Alex Hanselka +gitlab.io + +// Glitch, Inc : https://glitch.com +// Submitted by Mads Hartmann +glitch.me + +// GMO Pepabo, Inc. : https://pepabo.com/ +// Submitted by dojineko +lolipop.io + +// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ +// Submitted by Tom Whitwell +cloudapps.digital +london.cloudapps.digital + +// UKHomeOffice : https://www.gov.uk/government/organisations/home-office +// Submitted by Jon Shanks +homeoffice.gov.uk + +// GlobeHosting, Inc. +// Submitted by Zoltan Egresi +ro.im +shop.ro + +// GoIP DNS Services : http://www.goip.de +// Submitted by Christian Poulter +goip.de + +// Google, Inc. +// Submitted by Eduardo Vela +run.app +a.run.app +web.app +*.0emm.com +appspot.com +blogspot.ae +blogspot.al +blogspot.am +blogspot.ba +blogspot.be +blogspot.bg +blogspot.bj +blogspot.ca +blogspot.cf +blogspot.ch +blogspot.cl +blogspot.co.at +blogspot.co.id +blogspot.co.il +blogspot.co.ke +blogspot.co.nz +blogspot.co.uk +blogspot.co.za +blogspot.com +blogspot.com.ar +blogspot.com.au +blogspot.com.br +blogspot.com.by +blogspot.com.co +blogspot.com.cy +blogspot.com.ee +blogspot.com.eg +blogspot.com.es +blogspot.com.mt +blogspot.com.ng +blogspot.com.tr +blogspot.com.uy +blogspot.cv +blogspot.cz +blogspot.de +blogspot.dk +blogspot.fi +blogspot.fr +blogspot.gr +blogspot.hk +blogspot.hr +blogspot.hu +blogspot.ie +blogspot.in +blogspot.is +blogspot.it +blogspot.jp +blogspot.kr +blogspot.li +blogspot.lt +blogspot.lu +blogspot.md +blogspot.mk +blogspot.mr +blogspot.mx +blogspot.my +blogspot.nl +blogspot.no +blogspot.pe +blogspot.pt +blogspot.qa +blogspot.re +blogspot.ro +blogspot.rs +blogspot.ru +blogspot.se +blogspot.sg +blogspot.si +blogspot.sk +blogspot.sn +blogspot.td +blogspot.tw +blogspot.ug +blogspot.vn +cloudfunctions.net +cloud.goog +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com + +// Hakaran group: http://hakaran.cz +// Submited by Arseniy Sokolov +fin.ci +free.hr +caa.li +ua.rs +conf.se + +// Handshake : https://handshake.org +// Submitted by Mike Damm +hs.zone +hs.run + +// Hashbang : https://hashbang.sh +hashbang.sh + +// Hasura : https://hasura.io +// Submitted by Shahidh K Muhammed +hasura.app +hasura-app.io + +// Hepforge : https://www.hepforge.org +// Submitted by David Grellscheid +hepforge.org + +// Heroku : https://www.heroku.com/ +// Submitted by Tom Maher +herokuapp.com +herokussl.com + +// Hibernating Rhinos +// Submitted by Oren Eini +myravendb.com +ravendb.community +ravendb.me +development.run +ravendb.run + +// HOSTBIP REGISTRY : https://www.hostbip.com/ +// Submitted by Atanunu Igbunuroghene +bpl.biz +orx.biz +ng.city +biz.gl +ng.ink +col.ng +firm.ng +gen.ng +ltd.ng +ng.school +sch.so + +// Häkkinen.fi +// Submitted by Eero Häkkinen +häkkinen.fi + +// Ici la Lune : http://www.icilalune.com/ +// Submitted by Simon Morvan +*.moonscale.io +moonscale.net + +// iki.fi +// Submitted by Hannu Aronsson +iki.fi + +// Individual Network Berlin e.V. : https://www.in-berlin.de/ +// Submitted by Christian Seitz +dyn-berlin.de +in-berlin.de +in-brb.de +in-butter.de +in-dsl.de +in-dsl.net +in-dsl.org +in-vpn.de +in-vpn.net +in-vpn.org + +// info.at : http://www.info.at/ +biz.at +info.at + +// info.cx : http://info.cx +// Submitted by Jacob Slater +info.cx + +// Interlegis : http://www.interlegis.leg.br +// Submitted by Gabriel Ferreira +ac.leg.br +al.leg.br +am.leg.br +ap.leg.br +ba.leg.br +ce.leg.br +df.leg.br +es.leg.br +go.leg.br +ma.leg.br +mg.leg.br +ms.leg.br +mt.leg.br +pa.leg.br +pb.leg.br +pe.leg.br +pi.leg.br +pr.leg.br +rj.leg.br +rn.leg.br +ro.leg.br +rr.leg.br +rs.leg.br +sc.leg.br +se.leg.br +sp.leg.br +to.leg.br + +// intermetrics GmbH : https://pixolino.com/ +// Submitted by Wolfgang Schwarz +pixolino.com + +// IPiFony Systems, Inc. : https://www.ipifony.com/ +// Submitted by Matthew Hardeman +ipifony.net + +// IServ GmbH : https://iserv.eu +// Submitted by Kim-Alexander Brodowski +mein-iserv.de +test-iserv.de +iserv.dev + +// I-O DATA DEVICE, INC. : http://www.iodata.com/ +// Submitted by Yuji Minagawa +iobb.net + +// Jino : https://www.jino.ru +// Submitted by Sergey Ulyashin +myjino.ru +*.hosting.myjino.ru +*.landing.myjino.ru +*.spectrum.myjino.ru +*.vps.myjino.ru + +// Joyent : https://www.joyent.com/ +// Submitted by Brian Bennett +*.triton.zone +*.cns.joyent.com + +// JS.ORG : http://dns.js.org +// Submitted by Stefan Keim +js.org + +// KaasHosting : http://www.kaashosting.nl/ +// Submitted by Wouter Bakker +kaas.gg +khplay.nl + +// Keyweb AG : https://www.keyweb.de +// Submitted by Martin Dannehl +keymachine.de + +// KingHost : https://king.host +// Submitted by Felipe Keller Braz +kinghost.net +uni5.net + +// KnightPoint Systems, LLC : http://www.knightpoint.com/ +// Submitted by Roy Keene +knightpoint.systems + +// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf +co.krd +edu.krd + +// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de +// Submitted by Lars Laehn +git-repos.de +lcube-server.de +svn-repos.de + +// Leadpages : https://www.leadpages.net +// Submitted by Greg Dallavalle +leadpages.co +lpages.co +lpusercontent.com + +// Lelux.fi : https://lelux.fi/ +// Submitted by Lelux Admin +lelux.site + +// Lifetime Hosting : https://Lifetime.Hosting/ +// Submitted by Mike Fillator +co.business +co.education +co.events +co.financial +co.network +co.place +co.technology + +// Lightmaker Property Manager, Inc. : https://app.lmpm.com/ +// Submitted by Greg Holland +app.lmpm.com + +// Linki Tools UG : https://linki.tools +// Submitted by Paulo Matos +linkitools.space + +// linkyard ldt: https://www.linkyard.ch/ +// Submitted by Mario Siegenthaler +linkyard.cloud +linkyard-cloud.ch + +// Linode : https://linode.com +// Submitted by +members.linode.com +nodebalancer.linode.com + +// LiquidNet Ltd : http://www.liquidnetlimited.com/ +// Submitted by Victor Velchev +we.bs + +// Log'in Line : https://www.loginline.com/ +// Submitted by Rémi Mach +loginline.app +loginline.dev +loginline.io +loginline.services +loginline.site + +// LubMAN UMCS Sp. z o.o : https://lubman.pl/ +// Submitted by Ireneusz Maliszewski +krasnik.pl +leczna.pl +lubartow.pl +lublin.pl +poniatowa.pl +swidnik.pl + +// Lug.org.uk : https://lug.org.uk +// Submitted by Jon Spriggs +uklugs.org +glug.org.uk +lug.org.uk +lugs.org.uk + +// Lukanet Ltd : https://lukanet.com +// Submitted by Anton Avramov +barsy.bg +barsy.co.uk +barsyonline.co.uk +barsycenter.com +barsyonline.com +barsy.club +barsy.de +barsy.eu +barsy.in +barsy.info +barsy.io +barsy.me +barsy.menu +barsy.mobi +barsy.net +barsy.online +barsy.org +barsy.pro +barsy.pub +barsy.shop +barsy.site +barsy.support +barsy.uk + +// Magento Commerce +// Submitted by Damien Tournoud +*.magentosite.cloud + +// May First - People Link : https://mayfirst.org/ +// Submitted by Jamie McClelland +mayfirst.info +mayfirst.org + +// Mail.Ru Group : https://hb.cldmail.ru +// Submitted by Ilya Zaretskiy +hb.cldmail.ru + +// Memset hosting : https://www.memset.com +// Submitted by Tom Whitwell +miniserver.com +memset.net + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Zdeněk Šustr +cloud.metacentrum.cz +custom.metacentrum.cz + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Radim Janča +flt.cloud.muni.cz +usr.cloud.muni.cz + +// Meteor Development Group : https://www.meteor.com/hosting +// Submitted by Pierre Carrier +meteorapp.com +eu.meteorapp.com + +// Michau Enterprises Limited : http://www.co.pl/ +co.pl + +// Microsoft Corporation : http://microsoft.com +// Submitted by Justin Luk +azurecontainer.io +azurewebsites.net +azure-mobile.net +cloudapp.net + +// Mozilla Corporation : https://mozilla.com +// Submitted by Ben Francis +mozilla-iot.org + +// Mozilla Foundation : https://mozilla.org/ +// Submitted by glob +bmoattachments.org + +// MSK-IX : https://www.msk-ix.ru/ +// Submitted by Khannanov Roman +net.ru +org.ru +pp.ru + +// Nabu Casa : https://www.nabucasa.com +// Submitted by Paulus Schoutsen +ui.nabu.casa + +// Names.of.London : https://names.of.london/ +// Submitted by James Stevens or +pony.club +of.fashion +on.fashion +of.football +in.london +of.london +for.men +and.mom +for.mom +for.one +for.sale +of.work +to.work + +// NCTU.ME : https://nctu.me/ +// Submitted by Tocknicsu +nctu.me + +// Netlify : https://www.netlify.com +// Submitted by Jessica Parsons +bitballoon.com +netlify.com + +// Neustar Inc. +// Submitted by Trung Tran +4u.com + +// ngrok : https://ngrok.com/ +// Submitted by Alan Shreve +ngrok.io + +// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ +// Submitted by Nicholas Ford +nh-serv.co.uk + +// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ +// Submitted by Jeff Wheelhouse +nfshost.com + +// Now-DNS : https://now-dns.com +// Submitted by Steve Russell +dnsking.ch +mypi.co +n4t.co +001www.com +ddnslive.com +myiphost.com +forumz.info +16-b.it +32-b.it +64-b.it +soundcast.me +tcp4.me +dnsup.net +hicam.net +now-dns.net +ownip.net +vpndns.net +dynserv.org +now-dns.org +x443.pw +now-dns.top +ntdll.top +freeddns.us +crafting.xyz +zapto.xyz + +// nsupdate.info : https://www.nsupdate.info/ +// Submitted by Thomas Waldmann +nsupdate.info +nerdpol.ovh + +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + +// NodeArt : https://nodeart.io +// Submitted by Konstantin Nosov +stage.nodeart.io + +// Nodum B.V. : https://nodum.io/ +// Submitted by Wietse Wind +nodum.co +nodum.io + +// Nucleos Inc. : https://nucleos.com +// Submitted by Piotr Zduniak +pcloud.host + +// NYC.mn : http://www.information.nyc.mn +// Submitted by Matthew Brown +nyc.mn + +// NymNom : https://nymnom.com/ +// Submitted by Dave McCormack +nom.ae +nom.af +nom.ai +nom.al +nym.by +nym.bz +nom.cl +nym.ec +nom.gd +nom.ge +nom.gl +nym.gr +nom.gt +nym.gy +nym.hk +nom.hn +nym.ie +nom.im +nom.ke +nym.kz +nym.la +nym.lc +nom.li +nym.li +nym.lt +nym.lu +nym.me +nom.mk +nym.mn +nym.mx +nom.nu +nym.nz +nym.pe +nym.pt +nom.pw +nom.qa +nym.ro +nom.rs +nom.si +nym.sk +nom.st +nym.su +nym.sx +nom.tj +nym.tw +nom.ug +nom.uy +nom.vc +nom.vg + +// Octopodal Solutions, LLC. : https://ulterius.io/ +// Submitted by Andrew Sampson +cya.gg + +// Omnibond Systems, LLC. : https://www.omnibond.com +// Submitted by Cole Estep +cloudycluster.net + +// One Fold Media : http://www.onefoldmedia.com/ +// Submitted by Eddie Jones +nid.io + +// OpenCraft GmbH : http://opencraft.com/ +// Submitted by Sven Marnach +opencraft.hosting + +// Opera Software, A.S.A. +// Submitted by Yngve Pettersen +operaunite.com + +// OutSystems +// Submitted by Duarte Santos +outsystemscloud.com + +// OwnProvider GmbH: http://www.ownprovider.com +// Submitted by Jan Moennich +ownprovider.com +own.pm + +// OX : http://www.ox.rs +// Submitted by Adam Grand +ox.rs + +// oy.lc +// Submitted by Charly Coste +oy.lc + +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers +pgfog.com + +// Pagefront : https://www.pagefronthq.com/ +// Submitted by Jason Kriss +pagefrontapp.com + +// .pl domains (grandfathered) +art.pl +gliwice.pl +krakow.pl +poznan.pl +wroc.pl +zakopane.pl + +// Pantheon Systems, Inc. : https://pantheon.io/ +// Submitted by Gary Dylina +pantheonsite.io +gotpantheon.com + +// Peplink | Pepwave : http://peplink.com/ +// Submitted by Steve Leung +mypep.link + +// Planet-Work : https://www.planet-work.com/ +// Submitted by Frédéric VANNIÈRE +on-web.fr + +// Platform.sh : https://platform.sh +// Submitted by Nikola Kotur +*.platform.sh +*.platformsh.site + +// Port53 : https://port53.io/ +// Submitted by Maximilian Schieder +dyn53.io + +// Positive Codes Technology Company : http://co.bn/faq.html +// Submitted by Zulfais +co.bn + +// prgmr.com : https://prgmr.com/ +// Submitted by Sarah Newman +xen.prgmr.com + +// priv.at : http://www.nic.priv.at/ +// Submitted by registry +priv.at + +// privacytools.io : https://www.privacytools.io/ +// Submitted by Jonah Aragon +prvcy.page + +// Protocol Labs : https://protocol.ai/ +// Submitted by Michael Burns +*.dweb.link + +// Protonet GmbH : http://protonet.io +// Submitted by Martin Meier +protonet.io + +// Publication Presse Communication SARL : https://ppcom.fr +// Submitted by Yaacov Akiba Slama +chirurgiens-dentistes-en-france.fr +byen.site + +// pubtls.org: https://www.pubtls.org +// Submitted by Kor Nielsen +pubtls.org + +// Qualifio : https://qualifio.com/ +// Submitted by Xavier De Cock +qualifioapp.com + +// Redstar Consultants : https://www.redstarconsultants.com/ +// Submitted by Jons Slemmer +instantcloud.cn + +// Russian Academy of Sciences +// Submitted by Tech Support +ras.ru + +// QA2 +// Submitted by Daniel Dent (https://www.danieldent.com/) +qa2.com + +// QNAP System Inc : https://www.qnap.com +// Submitted by Nick Chang +dev-myqnapcloud.com +alpha-myqnapcloud.com +myqnapcloud.com + +// Quip : https://quip.com +// Submitted by Patrick Linehan +*.quipelements.com + +// Qutheory LLC : http://qutheory.io +// Submitted by Jonas Schwartz +vapor.cloud +vaporcloud.io + +// Rackmaze LLC : https://www.rackmaze.com +// Submitted by Kirill Pertsev +rackmaze.com +rackmaze.net + +// Rancher Labs, Inc : https://rancher.com +// Submitted by Vincent Fiduccia +*.on-rancher.cloud +*.on-rio.io + +// Read The Docs, Inc : https://www.readthedocs.org +// Submitted by David Fischer +readthedocs.io + +// Red Hat, Inc. OpenShift : https://openshift.redhat.com/ +// Submitted by Tim Kramer +rhcloud.com + +// Render : https://render.com +// Submitted by Anurag Goel +app.render.com +onrender.com + +// Repl.it : https://repl.it +// Submitted by Mason Clayton +repl.co +repl.run + +// Resin.io : https://resin.io +// Submitted by Tim Perry +resindevice.io +devices.resinstaging.io + +// RethinkDB : https://www.rethinkdb.com/ +// Submitted by Chris Kastorff +hzc.io + +// Revitalised Limited : http://www.revitalised.co.uk +// Submitted by Jack Price +wellbeingzone.eu +ptplus.fit +wellbeingzone.co.uk + +// Rochester Institute of Technology : http://www.rit.edu/ +// Submitted by Jennifer Herting +git-pages.rit.edu + +// Sandstorm Development Group, Inc. : https://sandcats.io/ +// Submitted by Asheesh Laroia +sandcats.io + +// SBE network solutions GmbH : https://www.sbe.de/ +// Submitted by Norman Meilick +logoip.de +logoip.com + +// schokokeks.org GbR : https://schokokeks.org/ +// Submitted by Hanno Böck +schokokeks.net + +// Scottish Government: https://www.gov.scot +// Submitted by Martin Ellis +gov.scot + +// Scry Security : http://www.scrysec.com +// Submitted by Shante Adam +scrysec.com + +// Securepoint GmbH : https://www.securepoint.de +// Submitted by Erik Anders +firewall-gateway.com +firewall-gateway.de +my-gateway.de +my-router.de +spdns.de +spdns.eu +firewall-gateway.net +my-firewall.org +myfirewall.org +spdns.org + +// Service Online LLC : http://drs.ua/ +// Submitted by Serhii Bulakh +biz.ua +co.ua +pp.ua + +// ShiftEdit : https://shiftedit.net/ +// Submitted by Adam Jimenez +shiftedit.io + +// Shopblocks : http://www.shopblocks.com/ +// Submitted by Alex Bowers +myshopblocks.com + +// Shopit : https://www.shopitcommerce.com/ +// Submitted by Craig McMahon +shopitsite.com + +// Siemens Mobility GmbH +// Submitted by Oliver Graebner +mo-siemens.io + +// SinaAppEngine : http://sae.sina.com.cn/ +// Submitted by SinaAppEngine +1kapp.com +appchizi.com +applinzi.com +sinaapp.com +vipsinaapp.com + +// Siteleaf : https://www.siteleaf.com/ +// Submitted by Skylar Challand +siteleaf.net + +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// Stackhero : https://www.stackhero.io +// Submitted by Adrien Gillon +stackhero-network.com + +// staticland : https://static.land +// Submitted by Seth Vincent +static.land +dev.static.land +sites.static.land + +// SourceLair PC : https://www.sourcelair.com +// Submitted by Antonis Kalipetis +apps.lair.io +*.stolos.io + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan +spacekit.io + +// SpeedPartner GmbH: https://www.speedpartner.de/ +// Submitted by Stefan Neufeind +customer.speedpartner.de + +// Standard Library : https://stdlib.com +// Submitted by Jacob Lee +api.stdlib.com + +// Storj Labs Inc. : https://storj.io/ +// Submitted by Philip Hutchins +storj.farm + +// Studenten Net Twente : http://www.snt.utwente.nl/ +// Submitted by Silke Hofstra +utwente.io + +// Student-Run Computing Facility : https://www.srcf.net/ +// Submitted by Edwin Balani +soc.srcf.net +user.srcf.net + +// Sub 6 Limited: http://www.sub6.com +// Submitted by Dan Miller +temp-dns.com + +// Swisscom Application Cloud: https://developer.swisscom.com +// Submitted by Matthias.Winzeler +applicationcloud.io +scapp.io + +// Symfony, SAS : https://symfony.com/ +// Submitted by Fabien Potencier +*.s5y.io +*.sensiosite.cloud + +// Syncloud : https://syncloud.org +// Submitted by Boris Rybalkin +syncloud.it + +// Synology, Inc. : https://www.synology.com/ +// Submitted by Rony Weng +diskstation.me +dscloud.biz +dscloud.me +dscloud.mobi +dsmynas.com +dsmynas.net +dsmynas.org +familyds.com +familyds.net +familyds.org +i234.me +myds.me +synology.me +vpnplus.to +direct.quickconnect.to + +// TAIFUN Software AG : http://taifun-software.de +// Submitted by Bjoern Henke +taifun-dns.de + +// TASK geographical domains (www.task.gda.pl/uslugi/dns) +gda.pl +gdansk.pl +gdynia.pl +med.pl +sopot.pl + +// Teckids e.V. : https://www.teckids.org +// Submitted by Dominik George +edugit.org + +// Telebit : https://telebit.cloud +// Submitted by AJ ONeal +telebit.app +telebit.io +*.telebit.xyz + +// The Gwiddle Foundation : https://gwiddlefoundation.org.uk +// Submitted by Joshua Bayfield +gwiddle.co.uk + +// Thingdust AG : https://thingdust.com/ +// Submitted by Adrian Imboden +thingdustdata.com +cust.dev.thingdust.io +cust.disrec.thingdust.io +cust.prod.thingdust.io +cust.testing.thingdust.io + +// Tlon.io : https://tlon.io +// Submitted by Mark Staarink +arvo.network +azimuth.network + +// TownNews.com : http://www.townnews.com +// Submitted by Dustin Ward +bloxcms.com +townnews-staging.com + +// TrafficPlex GmbH : https://www.trafficplex.de/ +// Submitted by Phillipp Röll +12hp.at +2ix.at +4lima.at +lima-city.at +12hp.ch +2ix.ch +4lima.ch +lima-city.ch +trafficplex.cloud +de.cool +12hp.de +2ix.de +4lima.de +lima-city.de +1337.pictures +clan.rip +lima-city.rocks +webspace.rocks +lima.zone + +// TransIP : https://www.transip.nl +// Submitted by Rory Breuk +*.transurl.be +*.transurl.eu +*.transurl.nl + +// TuxFamily : http://tuxfamily.org +// Submitted by TuxFamily administrators +tuxfamily.org + +// TwoDNS : https://www.twodns.de/ +// Submitted by TwoDNS-Support +dd-dns.de +diskstation.eu +diskstation.org +dray-dns.de +draydns.de +dyn-vpn.de +dynvpn.de +mein-vigor.de +my-vigor.de +my-wan.de +syno-ds.de +synology-diskstation.de +synology-ds.de + +// Uberspace : https://uberspace.de +// Submitted by Moritz Werner +uber.space +*.uberspace.de + +// UDR Limited : http://www.udr.hk.com +// Submitted by registry +hk.com +hk.org +ltd.hk +inc.hk + +// United Gameserver GmbH : https://united-gameserver.de +// Submitted by Stefan Schwarz +virtualuser.de +virtual-user.de + +// .US +// Submitted by Ed Moore +lib.de.us + +// VeryPositive SIA : http://very.lv +// Submitted by Danko Aleksejevs +2038.io + +// Viprinet Europe GmbH : http://www.viprinet.com +// Submitted by Simon Kissel +router.management + +// Virtual-Info : https://www.virtual-info.info/ +// Submitted by Adnan RIHAN +v-info.info + +// Voorloper.com: https://voorloper.com +// Submitted by Nathan van Bakel +voorloper.cloud + +// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com +// Submitted by Masayuki Note +wafflecell.com + +// WebHare bv: https://www.webhare.com/ +// Submitted by Arnold Hendriks +*.webhare.dev + +// WeDeploy by Liferay, Inc. : https://www.wedeploy.com +// Submitted by Henrique Vicente +wedeploy.io +wedeploy.me +wedeploy.sh + +// Western Digital Technologies, Inc : https://www.wdc.com +// Submitted by Jung Jin +remotewd.com + +// Wikimedia Labs : https://wikitech.wikimedia.org +// Submitted by Yuvi Panda +wmflabs.org + +// XenonCloud GbR: https://xenoncloud.net +// Submitted by Julian Uphoff +half.host + +// XnBay Technology : http://www.xnbay.com/ +// Submitted by XnBay Developer +xnbay.com +u2.xnbay.com +u2-local.xnbay.com + +// XS4ALL Internet bv : https://www.xs4all.nl/ +// Submitted by Daniel Mostertman +cistron.nl +demon.nl +xs4all.space + +// Yandex.Cloud LLC: https://cloud.yandex.com +// Submitted by Alexander Lodin +yandexcloud.net +storage.yandexcloud.net +website.yandexcloud.net + +// YesCourse Pty Ltd : https://yescourse.com +// Submitted by Atul Bhouraskar +official.academy + +// Yola : https://www.yola.com/ +// Submitted by Stefano Rivera +yolasite.com + +// Yombo : https://yombo.net +// Submitted by Mitch Schwenk +ybo.faith +yombo.me +homelink.one +ybo.party +ybo.review +ybo.science +ybo.trade + +// Yunohost : https://yunohost.org +// Submitted by Valentin Grimaud +nohost.me +noho.st + +// ZaNiC : http://www.za.net/ +// Submitted by registry +za.net +za.org + +// Zeit, Inc. : https://zeit.domains/ +// Submitted by Olli Vanhoja +now.sh + +// Zine EOOD : https://zine.bg/ +// Submitted by Martin Angelov +bss.design + +// Zitcom A/S : https://www.zitcom.dk +// Submitted by Emil Stahl +basicserver.io +virtualserver.io +site.builder.nu +enterprisecloud.nu + +// ===END PRIVATE DOMAINS=== diff --git a/pdns/epollmplexer.cc b/pdns/epollmplexer.cc new file mode 100644 index 0000000..433687d --- /dev/null +++ b/pdns/epollmplexer.cc @@ -0,0 +1,203 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "mplexer.hh" +#include "sstuff.hh" +#include +#include +#include "misc.hh" +#ifdef __linux__ +#include +#endif + +#include "namespaces.hh" + +class EpollFDMultiplexer : public FDMultiplexer +{ +public: + EpollFDMultiplexer(); + virtual ~EpollFDMultiplexer() + { + close(d_epollfd); + } + + virtual int run(struct timeval* tv, int timeout=500) override; + virtual void getAvailableFDs(std::vector& fds, int timeout) override; + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override; + virtual void removeFD(callbackmap_t& cbmap, int fd) override; + string getName() const override + { + return "epoll"; + } +private: + int d_epollfd; + boost::shared_array d_eevents; + static int s_maxevents; // not a hard maximum +}; + + +static FDMultiplexer* makeEpoll() +{ + return new EpollFDMultiplexer(); +} + +static struct EpollRegisterOurselves +{ + EpollRegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makeEpoll)); // priority 0! + } +} doItEpoll; + +int EpollFDMultiplexer::s_maxevents=1024; + +EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event[s_maxevents]) +{ + d_epollfd=epoll_create(s_maxevents); // not hard max + if(d_epollfd < 0) + throw FDMultiplexerException("Setting up epoll: "+stringerror()); + int fd=socket(AF_INET, SOCK_DGRAM, 0); // for self-test + if(fd < 0) + return; + try { + addReadFD(fd, 0); + removeReadFD(fd); + close(fd); + return; + } + catch(FDMultiplexerException &fe) { + close(fd); + close(d_epollfd); + throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe.what())); + } + +} + +void EpollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd) +{ + accountingAddFD(cbmap, fd, toDo, parameter, ttd); + + struct epoll_event eevent; + + eevent.events = (&cbmap == &d_readCallbacks) ? EPOLLIN : EPOLLOUT; + + eevent.data.u64=0; // placate valgrind (I love it so much) + eevent.data.fd=fd; + + if(epoll_ctl(d_epollfd, EPOLL_CTL_ADD, fd, &eevent) < 0) { + cbmap.erase(fd); + throw FDMultiplexerException("Adding fd to epoll set: "+stringerror()); + } +} + +void EpollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + if(!cbmap.erase(fd)) + throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); + + struct epoll_event dummy; + dummy.events = 0; + dummy.data.u64 = 0; + + if(epoll_ctl(d_epollfd, EPOLL_CTL_DEL, fd, &dummy) < 0) + throw FDMultiplexerException("Removing fd from epoll set: "+stringerror()); +} + +void EpollFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) +{ + int ret=epoll_wait(d_epollfd, d_eevents.get(), s_maxevents, timeout); + + if(ret < 0 && errno!=EINTR) + throw FDMultiplexerException("epoll returned error: "+stringerror()); + + for(int n=0; n < ret; ++n) { + fds.push_back(d_eevents[n].data.fd); + } +} + +int EpollFDMultiplexer::run(struct timeval* now, int timeout) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + + int ret=epoll_wait(d_epollfd, d_eevents.get(), s_maxevents, timeout); + gettimeofday(now,0); // MANDATORY + + if(ret < 0 && errno!=EINTR) + throw FDMultiplexerException("epoll returned error: "+stringerror()); + + if(ret < 1) // thanks AB! + return 0; + + d_inrun=true; + for(int n=0; n < ret; ++n) { + d_iter=d_readCallbacks.find(d_eevents[n].data.fd); + + if(d_iter != d_readCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + continue; // so we don't refind ourselves as writable! + } + d_iter=d_writeCallbacks.find(d_eevents[n].data.fd); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + } + } + d_inrun=false; + return ret; +} + +#if 0 +void acceptData(int fd, funcparam_t& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "< +#include + +/* This class implements a filtering policy that is able to fully implement RPZ, but is not bound to it. + In other words, it is generic enough to support RPZ, but could get its data from other places. + + + We know the following actions: + + No action - just pass it on + Drop - drop a query, no response + NXDOMAIN - fake up an NXDOMAIN for the query + NODATA - just return no data for this qtype + Truncate - set TC bit + Modified - "we fake an answer for you" + + These actions can be caused by the following triggers: + + qname - the query name + client-ip - the IP address of the requestor + response-ip - an IP address in the response + ns-name - the name of a server used in the delegation + ns-ip - the IP address of a server used in the delegation + + This means we get several hook points: + 1) when the query comes in: qname & client-ip + 2) during processing: ns-name & ns-ip + 3) after processing: response-ip + + Triggers meanwhile can apply to: + Verbatim domain names + Wildcard versions (*.domain.com does NOT match domain.com) + Netmasks (IPv4 and IPv6) + Finally, triggers are grouped in different zones. The "first" zone that has a match + is consulted. Then within that zone, rules again have precedences. +*/ + + +class DNSFilterEngine +{ +public: + enum class PolicyKind { NoAction, Drop, NXDOMAIN, NODATA, Truncate, Custom}; + enum class PolicyType { None, QName, ClientIP, ResponseIP, NSDName, NSIP }; + + static std::string getKindToString(PolicyKind kind); + static std::string getTypeToString(PolicyType type); + + struct Policy + { + Policy(): d_name(nullptr), d_kind(PolicyKind::NoAction), d_type(PolicyType::None), d_ttl(0) + { + } + + Policy(PolicyKind kind, PolicyType type, int32_t ttl=0, std::shared_ptr name=nullptr, const std::vector>& custom={}): d_custom(custom), d_name(name), d_kind(kind), d_type(type), d_ttl(ttl) + { + } + + bool operator==(const Policy& rhs) const + { + return d_kind == rhs.d_kind && d_type == rhs.d_type && d_ttl == rhs.d_ttl && d_custom == rhs.d_custom; + } + std::vector getCustomRecords(const DNSName& qname, uint16_t qtype) const; + std::vector getRecords(const DNSName& qname) const; + + std::vector> d_custom; + std::shared_ptr d_name; // the name of the policy + PolicyKind d_kind; + PolicyType d_type; + /* Yup, we are currently using the same TTL for every record for a given name */ + int32_t d_ttl; + + private: + DNSRecord getRecordFromCustom(const DNSName& qname, const std::shared_ptr& custom) const; +}; + + class Zone { + public: + void clear() + { + d_qpolAddr.clear(); + d_postpolAddr.clear(); + d_propolName.clear(); + d_propolNSAddr.clear(); + d_qpolName.clear(); + } + void reserve(size_t entriesCount) + { + d_qpolName.reserve(entriesCount); + } + void setName(const std::string& name) + { + d_name = std::make_shared(name); + } + void setDomain(const DNSName& domain) + { + d_domain = domain; + } + void setSerial(uint32_t serial) + { + d_serial = serial; + } + void setRefresh(uint32_t refresh) + { + d_refresh = refresh; + } + const std::shared_ptr getName() const + { + return d_name; + } + + DNSName getDomain() const + { + return d_domain; + } + + uint32_t getRefresh() const + { + return d_refresh; + } + + uint32_t getSerial() const + { + return d_serial; + } + + size_t size() const + { + return d_qpolAddr.size() + d_postpolAddr.size() + d_propolName.size() + d_propolNSAddr.size() + d_qpolName.size(); + + } + + void dump(FILE * fp) const; + + void addClientTrigger(const Netmask& nm, Policy&& pol); + void addQNameTrigger(const DNSName& nm, Policy&& pol, bool ignoreDuplicate=false); + void addNSTrigger(const DNSName& dn, Policy&& pol); + void addNSIPTrigger(const Netmask& nm, Policy&& pol); + void addResponseTrigger(const Netmask& nm, Policy&& pol); + + bool rmClientTrigger(const Netmask& nm, const Policy& pol); + bool rmQNameTrigger(const DNSName& nm, const Policy& pol); + bool rmNSTrigger(const DNSName& dn, const Policy& pol); + bool rmNSIPTrigger(const Netmask& nm, const Policy& pol); + bool rmResponseTrigger(const Netmask& nm, const Policy& pol); + + bool findQNamePolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const; + bool findNSPolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const; + bool findNSIPPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const; + bool findResponsePolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const; + bool findClientPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const; + + private: + static DNSName maskToRPZ(const Netmask& nm); + bool findNamedPolicy(const std::unordered_map& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol) const; + void dumpNamedPolicy(FILE* fp, const DNSName& name, const Policy& pol) const; + void dumpAddrPolicy(FILE* fp, const Netmask& nm, const DNSName& name, const Policy& pol) const; + + std::unordered_map d_qpolName; // QNAME trigger (RPZ) + NetmaskTree d_qpolAddr; // Source address + std::unordered_map d_propolName; // NSDNAME (RPZ) + NetmaskTree d_propolNSAddr; // NSIP (RPZ) + NetmaskTree d_postpolAddr; // IP trigger (RPZ) + DNSName d_domain; + std::shared_ptr d_name; + uint32_t d_serial{0}; + uint32_t d_refresh{0}; + }; + + DNSFilterEngine(); + void clear() + { + for(auto& z : d_zones) { + z->clear(); + } + } + const std::shared_ptr getZone(size_t zoneIdx) const + { + std::shared_ptr result{nullptr}; + if (zoneIdx < d_zones.size()) { + result = d_zones[zoneIdx]; + } + return result; + } + const std::shared_ptr getZone(const std::string& name) const + { + for (const auto zone : d_zones) { + const auto& zName = zone->getName(); + if (zName && *zName == name) { + return zone; + } + } + return nullptr; + } + size_t addZone(std::shared_ptr newZone) + { + d_zones.push_back(newZone); + return (d_zones.size() - 1); + } + void setZone(size_t zoneIdx, std::shared_ptr newZone) + { + if (newZone) { + assureZones(zoneIdx); + d_zones[zoneIdx] = newZone; + } + } + + Policy getQueryPolicy(const DNSName& qname, const ComboAddress& nm, const std::unordered_map& discardedPolicies) const; + Policy getProcessingPolicy(const DNSName& qname, const std::unordered_map& discardedPolicies) const; + Policy getProcessingPolicy(const ComboAddress& address, const std::unordered_map& discardedPolicies) const; + Policy getPostPolicy(const vector& records, const std::unordered_map& discardedPolicies) const; + + size_t size() const { + return d_zones.size(); + } +private: + void assureZones(size_t zone); + vector> d_zones; +}; diff --git a/pdns/fuzz_dnsdistcache.cc b/pdns/fuzz_dnsdistcache.cc new file mode 100644 index 0000000..8b2ed7d --- /dev/null +++ b/pdns/fuzz_dnsdistcache.cc @@ -0,0 +1,47 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-cache.hh" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + + if (size > std::numeric_limits::max()) { + return 0; + } + + /* dnsdist's version */ + try { + uint16_t qtype; + uint16_t qclass; + unsigned int consumed; + DNSName qname(reinterpret_cast(data), size, sizeof(dnsheader), false, &qtype, &qclass, &consumed); + DNSDistPacketCache::getKey(qname.toString(), consumed, data, size, false); + boost::optional subnet; + DNSDistPacketCache::getClientSubnet(reinterpret_cast(data), consumed, size, subnet); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_moadnsparser.cc b/pdns/fuzz_moadnsparser.cc new file mode 100644 index 0000000..ea5fe25 --- /dev/null +++ b/pdns/fuzz_moadnsparser.cc @@ -0,0 +1,63 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsparser.hh" +#include "dnsrecords.hh" +#include "statbag.hh" + +StatBag S; + +static void init() +{ + reportAllTypes(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static bool initialized = false; + + if (!initialized) { + init(); + initialized = true; + } + + if (size > std::numeric_limits::max()) { + return 0; + } + + try { + MOADNSParser moaQuery(true, reinterpret_cast(data), size); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + try { + MOADNSParser moaAnswer(false, reinterpret_cast(data), size); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_packetcache.cc b/pdns/fuzz_packetcache.cc new file mode 100644 index 0000000..faea016 --- /dev/null +++ b/pdns/fuzz_packetcache.cc @@ -0,0 +1,57 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "packetcache.hh" +#include "statbag.hh" + +StatBag S; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + + if (size > std::numeric_limits::max()) { + return 0; + } + + std::string input(reinterpret_cast(data), size); + + /* auth's version */ + try { + PacketCache::canHashPacket(input); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + /* recursor's version */ + try { + uint16_t ecsBegin = 0; + uint16_t ecsEnd = 0; + PacketCache::canHashPacket(input, &ecsBegin, &ecsEnd); + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/fuzz_zoneparsertng.cc b/pdns/fuzz_zoneparsertng.cc new file mode 100644 index 0000000..a6f30d3 --- /dev/null +++ b/pdns/fuzz_zoneparsertng.cc @@ -0,0 +1,60 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsname.hh" +#include "dnsparser.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "zoneparser-tng.hh" + +StatBag S; + +static void init() +{ + reportAllTypes(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static bool initialized = false; + + if (!initialized) { + init(); + initialized = true; + } + + try { + std::vector lines; + std::string tmp(reinterpret_cast(data), size); + boost::split(lines, tmp, boost::is_any_of("\n")); + + ZoneParserTNG zpt(lines, g_rootdnsname); + DNSResourceRecord drr; + while (zpt.get(drr)) { + } + } + catch(const std::exception& e) { + } + catch(const PDNSException& e) { + } + + return 0; +} diff --git a/pdns/gettime.cc b/pdns/gettime.cc new file mode 100644 index 0000000..b6d95a4 --- /dev/null +++ b/pdns/gettime.cc @@ -0,0 +1,52 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "gettime.hh" +#include "config.h" + +#ifdef HAVE_CLOCK_GETTIME +#include + +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +#endif + +int gettime(struct timespec *tp, bool needRealTime) +{ + return clock_gettime(needRealTime ? CLOCK_REALTIME : CLOCK_MONOTONIC, tp); +} + +#else +#include + +int gettime(struct timespec *tp, bool needRealTime) +{ + struct timeval tv; + + int ret = gettimeofday(&tv, NULL); + if(ret < 0) return ret; + + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000; + return ret; +} + +#endif diff --git a/pdns/gettime.hh b/pdns/gettime.hh new file mode 100644 index 0000000..29c0fca --- /dev/null +++ b/pdns/gettime.hh @@ -0,0 +1,24 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +extern int gettime(struct timespec *tp, bool needRealTime=false); diff --git a/pdns/gss_context.cc b/pdns/gss_context.cc new file mode 100644 index 0000000..3c2ed29 --- /dev/null +++ b/pdns/gss_context.cc @@ -0,0 +1,490 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "namespaces.hh" +#include "dns.hh" +#include "dnsparser.hh" +#include "dnspacket.hh" +#include "dnsrecords.hh" +#include "logger.hh" +#include "lock.hh" +#include "arguments.hh" + +#include +#include +#include "gss_context.hh" + +#ifndef ENABLE_GSS_TSIG + +bool GssContext::supported() { return false; } +GssContext::GssContext() : d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {} +GssContext::GssContext(const DNSName& label) : d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {} +void GssContext::setLocalPrincipal(const std::string& name) {} +bool GssContext::getLocalPrincipal(std::string& name) { return false; } +void GssContext::setPeerPrincipal(const std::string& name) {} +bool GssContext::getPeerPrincipal(std::string& name) { return false; } +void GssContext::generateLabel(const std::string& suffix) {} +void GssContext::setLabel(const DNSName& label) {} +bool GssContext::init(const std::string &input, std::string& output) { return false; } +bool GssContext::accept(const std::string &input, std::string& output) { return false; } +bool GssContext::destroy() { return false; } +bool GssContext::expired() { return false; } +bool GssContext::valid() { return false; } +bool GssContext::sign(const std::string &input, std::string& output) { return false; } +bool GssContext::verify(const std::string &input, const std::string &signature) { return false; } +GssContextError GssContext::getError() { return GSS_CONTEXT_UNSUPPORTED; } + +#else + +class GssCredential : boost::noncopyable { +public: + GssCredential(const std::string& name, const gss_cred_usage_t usage) : + d_valid(false), d_nameS(name), d_name(GSS_C_NO_NAME), d_cred(GSS_C_NO_CREDENTIAL), d_usage(usage) { + gss_buffer_desc buffer; + + if (name.empty() == false) { + buffer.length = name.size(); + buffer.value = (void*)name.c_str(); + d_maj = gss_import_name(&d_min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name); + if (d_maj != GSS_S_COMPLETE) { + d_valid = false; + return; + } + } + + renew(); + }; + + ~GssCredential() { + OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + if (d_cred != GSS_C_NO_CREDENTIAL) + tmp_maj = gss_release_cred(&tmp_min, &d_cred); + if (d_name != GSS_C_NO_NAME) + tmp_maj = gss_release_name(&tmp_min, &d_name); + }; + + bool expired() const { + if (d_expires == -1) return false; + return time((time_t*)NULL)>d_expires; + } + + bool renew() { + OM_uint32 time_rec, tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + d_maj = gss_acquire_cred(&d_min, d_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, d_usage, &d_cred, NULL, &time_rec); + + if (d_maj != GSS_S_COMPLETE) { + d_valid = false; + tmp_maj = gss_release_name(&tmp_min, &d_name); + d_name = GSS_C_NO_NAME; + return false; + } + + d_valid = true; + + if (time_rec > GSS_C_INDEFINITE) { + d_expires = time((time_t*)NULL)+time_rec; + } else { + d_expires = -1; + } + + return true; + } + + bool valid() { + return d_valid && !expired(); + } + + OM_uint32 d_maj,d_min; + + bool d_valid; + int64_t d_expires; + std::string d_nameS; + gss_name_t d_name; + gss_cred_id_t d_cred; + gss_cred_usage_t d_usage; +}; + +std::map > s_gss_accept_creds; +std::map > s_gss_init_creds; + +class GssSecContext : boost::noncopyable { +public: + GssSecContext(boost::shared_ptr cred) { + if (cred->valid() == false) throw PDNSException("Invalid credential " + cred->d_nameS); + d_cred = cred; + d_state = GssStateInitial; + d_ctx = GSS_C_NO_CONTEXT; + d_expires = 0; + d_maj = d_min = 0; + d_peer_name = GSS_C_NO_NAME; + d_type = GSS_CONTEXT_NONE; + } + + ~GssSecContext() { + OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + if (d_ctx != GSS_C_NO_CONTEXT) { + tmp_maj = gss_delete_sec_context(&tmp_min, &d_ctx, GSS_C_NO_BUFFER); + } + if (d_peer_name != GSS_C_NO_NAME) { + tmp_maj = gss_release_name(&tmp_min, &(d_peer_name)); + } + } + + GssContextType d_type; + gss_ctx_id_t d_ctx; + gss_name_t d_peer_name; + int64_t d_expires; + boost::shared_ptr d_cred; + OM_uint32 d_maj,d_min; + + enum { + GssStateInitial, + GssStateNegotiate, + GssStateComplete, + GssStateError + } d_state; + +}; + +std::map > s_gss_sec_context; + +bool GssContext::supported() { return true; } + +void GssContext::initialize() { + d_peerPrincipal = ""; + d_localPrincipal = ""; + d_error = GSS_CONTEXT_NO_ERROR; + d_type = GSS_CONTEXT_NONE; +} + +GssContext::GssContext() { + initialize(); + generateLabel("pdns.tsig."); +} + +GssContext::GssContext(const DNSName& label) { + initialize(); + setLabel(label); +} + +void GssContext::generateLabel(const std::string& suffix) { + std::ostringstream oss; + oss << std::hex << time((time_t*)NULL) << "." << suffix; + setLabel(DNSName(oss.str())); +} + +void GssContext::setLabel(const DNSName& label) { + d_label = label; + if (s_gss_sec_context.find(d_label) != s_gss_sec_context.end()) { + d_ctx = s_gss_sec_context[d_label]; + d_type = d_ctx->d_type; + } +} + +bool GssContext::expired() { + return (!d_ctx || (d_ctx->d_expires > -1 && d_ctx->d_expires < time((time_t*)NULL))); +} + +bool GssContext::valid() { + return (d_ctx && !expired() && d_ctx->d_state == GssSecContext::GssStateComplete); +} + +bool GssContext::init(const std::string &input, std::string& output) { + OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + OM_uint32 maj,min; + gss_buffer_desc recv_tok, send_tok, buffer; + OM_uint32 flags; + OM_uint32 expires; + + boost::shared_ptr cred; + if (d_label.empty()) { + d_error = GSS_CONTEXT_INVALID; + return false; + } + + d_type = GSS_CONTEXT_INIT; + + if (s_gss_init_creds.find(d_localPrincipal) != s_gss_init_creds.end()) { + cred = s_gss_init_creds[d_localPrincipal]; + } else { + s_gss_init_creds[d_localPrincipal] = boost::make_shared(d_localPrincipal, GSS_C_INITIATE); + cred = s_gss_init_creds[d_localPrincipal]; + } + + // see if we can find a context in non-completed state + if (d_ctx) { + if (d_ctx->d_state != GssSecContext::GssStateNegotiate) { + d_error = GSS_CONTEXT_INVALID; + return false; + } + } else { + // make context + s_gss_sec_context[d_label] = boost::make_shared(cred); + s_gss_sec_context[d_label]->d_type = d_type; + d_ctx = s_gss_sec_context[d_label]; + d_ctx->d_state = GssSecContext::GssStateNegotiate; + } + + recv_tok.length = input.size(); + recv_tok.value = (void*)input.c_str(); + + if (d_peerPrincipal.empty() == false) { + buffer.value = (void*)d_peerPrincipal.c_str(); + buffer.length = d_peerPrincipal.size(); + maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &(d_ctx->d_peer_name)); + if (maj != GSS_S_COMPLETE) { + processError("gss_import_name", maj, min); + return false; + } + } + + maj = gss_init_sec_context(&min, cred->d_cred, &(d_ctx->d_ctx), d_ctx->d_peer_name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &recv_tok, NULL, &send_tok, &flags, &expires); + + if (send_tok.length>0) { + output.assign((const char*)send_tok.value, send_tok.length); + tmp_maj = gss_release_buffer(&tmp_min, &send_tok); + } + + if (maj == GSS_S_COMPLETE) { + if (expires > GSS_C_INDEFINITE) { + d_ctx->d_expires = time((time_t*)NULL) + expires; + } else { + d_ctx->d_expires = -1; + } + d_ctx->d_state = GssSecContext::GssStateComplete; + return true; + } else if (maj != GSS_S_CONTINUE_NEEDED) { + processError("gss_init_sec_context", maj,min); + } + + return (maj == GSS_S_CONTINUE_NEEDED); +} + +bool GssContext::accept(const std::string &input, std::string& output) { + OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + OM_uint32 maj,min; + gss_buffer_desc recv_tok, send_tok; + OM_uint32 flags; + OM_uint32 expires; + + boost::shared_ptr cred; + if (d_label.empty()) { + d_error = GSS_CONTEXT_INVALID; + return false; + } + + d_type = GSS_CONTEXT_ACCEPT; + + if (s_gss_accept_creds.find(d_localPrincipal) != s_gss_accept_creds.end()) { + cred = s_gss_accept_creds[d_localPrincipal]; + } else { + s_gss_accept_creds[d_localPrincipal] = boost::make_shared(d_localPrincipal, GSS_C_ACCEPT); + cred = s_gss_accept_creds[d_localPrincipal]; + } + + // see if we can find a context in non-completed state + if (d_ctx) { + if (d_ctx->d_state != GssSecContext::GssStateNegotiate) { + d_error = GSS_CONTEXT_INVALID; + return false; + } + } else { + // make context + s_gss_sec_context[d_label] = boost::make_shared(cred); + s_gss_sec_context[d_label]->d_type = d_type; + d_ctx = s_gss_sec_context[d_label]; + d_ctx->d_state = GssSecContext::GssStateNegotiate; + } + + recv_tok.length = input.size(); + recv_tok.value = (void*)input.c_str(); + + maj = gss_accept_sec_context(&min, &(d_ctx->d_ctx), cred->d_cred, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &(d_ctx->d_peer_name), NULL, &send_tok, &flags, &expires, NULL); + + if (send_tok.length>0) { + output.assign((const char*)send_tok.value, send_tok.length); + tmp_maj = gss_release_buffer(&tmp_min, &send_tok); + } + + if (maj == GSS_S_COMPLETE) { + if (expires > GSS_C_INDEFINITE) { + d_ctx->d_expires = time((time_t*)NULL) + expires; + } else { + d_ctx->d_expires = -1; + } + d_ctx->d_state = GssSecContext::GssStateComplete; + return true; + } else if (maj != GSS_S_CONTINUE_NEEDED) { + processError("gss_accept_sec_context", maj,min); + } + return (maj == GSS_S_CONTINUE_NEEDED); +}; + +bool GssContext::sign(const std::string& input, std::string& output) { + OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused)); + OM_uint32 maj,min; + + gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + + recv_tok.length = input.size(); + recv_tok.value = (void*)input.c_str(); + + maj = gss_get_mic(&min, d_ctx->d_ctx, GSS_C_QOP_DEFAULT, &recv_tok, &send_tok); + + if (send_tok.length>0) { + output.assign((const char*)send_tok.value, send_tok.length); + tmp_maj = gss_release_buffer(&tmp_min, &send_tok); + } + + if (maj != GSS_S_COMPLETE) { + processError("gss_get_mic", maj,min); + } + + return (maj == GSS_S_COMPLETE); +} + +bool GssContext::verify(const std::string& input, const std::string& signature) { + OM_uint32 maj,min; + + gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; + gss_buffer_desc sign_tok = GSS_C_EMPTY_BUFFER; + + recv_tok.length = input.size(); + recv_tok.value = (void*)input.c_str(); + sign_tok.length = signature.size(); + sign_tok.value = (void*)signature.c_str(); + + maj = gss_verify_mic(&min, d_ctx->d_ctx, &recv_tok, &sign_tok, NULL); + + if (maj != GSS_S_COMPLETE) { + processError("gss_get_mic", maj,min); + } + + return (maj == GSS_S_COMPLETE); +} + +bool GssContext::destroy() { + return false; +} + +void GssContext::setLocalPrincipal(const std::string& name) { + d_localPrincipal = name; +} + +bool GssContext::getLocalPrincipal(std::string& name) { + name = d_localPrincipal; + return name.size()>0; +} + +void GssContext::setPeerPrincipal(const std::string& name) { + d_peerPrincipal = name; +} + +bool GssContext::getPeerPrincipal(std::string& name) { + gss_buffer_desc value; + OM_uint32 maj,min; + + if (d_ctx->d_peer_name != GSS_C_NO_NAME) { + maj = gss_display_name(&min, d_ctx->d_peer_name, &value, NULL); + if (maj == GSS_S_COMPLETE && value.length > 0) { + name.assign((const char*)value.value, value.length); + maj = gss_release_buffer(&min, &value); + return true; + } else { + return false; + } + } else { + return false; + } +} + +void GssContext::processError(const std::string& method, OM_uint32 maj, OM_uint32 min) { + OM_uint32 tmp_min; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + ostringstream oss; + gss_display_status(&tmp_min, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); + oss << method << ": " << (char*)msg.value; + d_gss_errors.push_back(oss.str()); + if (!msg_ctx) break; + } + msg_ctx = 0; + while (1) { + ostringstream oss; + gss_display_status(&tmp_min, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); + oss << method << ": " << (char*)msg.value; + d_gss_errors.push_back(oss.str()); + if (!msg_ctx) break; + } +} + +#endif + +bool gss_add_signature(const DNSName& context, const std::string& message, std::string& mac) { + string tmp_mac; + GssContext gssctx(context); + if (!gssctx.valid()) { + g_log< +#include +#include +#endif + +//! Generic errors +enum GssContextError { + GSS_CONTEXT_NO_ERROR, + GSS_CONTEXT_UNSUPPORTED, + GSS_CONTEXT_NOT_FOUND, + GSS_CONTEXT_NOT_INITIALIZED, + GSS_CONTEXT_INVALID, + GSS_CONTEXT_EXPIRED, + GSS_CONTEXT_ALREADY_INITIALIZED +}; + +//! GSS context types +enum GssContextType { + GSS_CONTEXT_NONE, + GSS_CONTEXT_INIT, + GSS_CONTEXT_ACCEPT +}; + +class GssSecContext; + +/*! Class for representing GSS names, such as host/host.domain.com@REALM. +*/ +class GssName { +public: + //! Initialize to empty name + GssName() { + setName(""); + }; + + //! Initialize using specific name + GssName(const std::string& name) { + setName(name); + }; + + //! Parse name into native representation + bool setName(const std::string& name) { +#ifdef ENABLE_GSS_TSIG + gss_buffer_desc buffer; + d_name = GSS_C_NO_NAME; + + if (!name.empty()) { + buffer.length = name.size(); + buffer.value = (void*)name.c_str(); + d_maj = gss_import_name(&d_min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name); + return d_maj == GSS_S_COMPLETE; + } + + return true; +#endif + return false; + }; + + ~GssName() { +#ifdef ENABLE_GSS_TSIG + if (d_name != GSS_C_NO_NAME) + gss_release_name(&d_min, &d_name); +#endif + }; + + //! Compare two Gss Names, if no gss support is compiled in, returns false always + //! This is not necessarily same as string comparison between two non-parsed names + bool operator==(const GssName& rhs) { +#ifdef ENABLE_GSS_TSIG + OM_uint32 maj,min; + int result; + maj = gss_compare_name(&min, d_name, rhs.d_name, &result); + return (maj == GSS_S_COMPLETE && result != 0); +#endif + return false; + } + + //! Compare two Gss Names, if no gss support is compiled in, returns false always + //! This is not necessarily same as string comparison between two non-parsed names + bool match(const std::string& name) { +#ifdef ENABLE_GSS_TSIG + OM_uint32 maj,min; + int result; + gss_name_t comp; + gss_buffer_desc buffer; + buffer.length = name.size(); + buffer.value = (void*)name.c_str(); + maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &comp); + if (maj != GSS_S_COMPLETE) + throw PDNSException("Could not import " + name + ": " + std::to_string(maj) + string(",") + std::to_string(min)); + // do comparison + maj = gss_compare_name(&min, d_name, comp, &result); + gss_release_name(&min, &comp); + return (maj == GSS_S_COMPLETE && result != 0); +#else + return false; +#endif + }; + + //! Check if GSS name was parsed successfully. + bool valid() { +#ifdef ENABLE_GSS_TSIG + return d_maj == GSS_S_COMPLETE; +#else + return false; +#endif + } +private: +#ifdef ENABLE_GSS_TSIG + OM_uint32 d_maj,d_min; + gss_name_t d_name; +#endif +}; + +class GssContext { +public: + static bool supported(); // getErrorStrings() { return d_gss_errors; } // d_gss_errors; // d_ctx; // +#include + +#include +#include +#include +#include + +struct LogHistogramBin +{ + double percentile; + double latLimit; + double latAverage; + double latMedian; + double latStddev; + uint64_t count; + double cumulLatAverage; + double cumulLatMedian; +}; + +template +std::vector createLogHistogram(const T& bins, + std::deque percentiles={0.001, 0.01, 0.1, 0.2, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 94, 95, 96, 97, 97.5, 98, 98.5, 99, 99.5, 99.6, 99.9, 99.99, 99.999, 99.9999}) +{ + uint64_t totcumul=0, sum=0; + + for(const auto& c: bins) { + totcumul += c.second; + } + + namespace ba=boost::accumulators; + ba::accumulator_set, unsigned> acc; + + ba::accumulator_set, unsigned int> cumulstats; + + uint64_t bincount=0; + std::vector ret; + for(const auto& c: bins) { + if(percentiles.empty()) + break; + sum += c.second; + bincount += c.second; + + acc(c.first/1000.0, ba::weight=c.second); + for(unsigned int i=0; i < c.second; ++i) + cumulstats(c.first/1000.0, ba::weight=1); // "weighted" does not work for median + if(sum > percentiles.front() * totcumul / 100.0) { + ret.push_back({100.0-percentiles.front(), (double)c.first/1000.0, ba::mean(acc), ba::median(acc), sqrt(ba::variance(acc)), bincount, ba::mean(cumulstats), ba::median(cumulstats)}); + + percentiles.pop_front(); + acc=decltype(acc)(); + bincount=0; + } + } + std::sort(ret.begin(), ret.end(), [](const LogHistogramBin& a, const LogHistogramBin& b) { + return a.percentile < b.percentile; + }); + return ret; +} + +template +void writeLogHistogramFile(const T& bins, std::ostream& out, std::deque percentiles={0.001, 0.01, 0.1, 0.2, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 94, 95, 96, 97, 97.5, 98, 98.5, 99, 99.5, 99.6, 99.9, 99.99, 99.999, 99.9999} ) +{ + + auto vec = createLogHistogram(bins, percentiles); + out<< R"(# set logscale xy +# set mxtics 10 +# set mytics 10 +# set grid xtics +# set grid ytics +# set xlabel "Slowest percentile" +# set ylabel "Millisecond response time" +# set terminal svg +# set output 'log-histogram.svg' +# plot 'log-histogram' using 1:2 with linespoints title 'Average latency per percentile', \ +# 'log-histogram' using 1:6 with linespoints title 'Cumulative average latency', \ +# 'log-histogram' using 1:7 with linespoints title 'Cumulative median latency')"<<"\n"; + + out<<"# slow-percentile usec-latency-mean usec-latency-max usec-latency-median usec-latency-stddev usec-latency-cumul usec-latency-median-cumul num-queries\n"; + + + for(const auto& e : vec) { + out< +void writeFullHistogramFile(const T& bins, double binMsec, std::ofstream& out) +{ + std::map reducedBins; + for(const auto& b : bins) { + reducedBins[b.first/(1000.0*binMsec)]+=b.second; + } + out<<"# msec-bin-low count\n"; + for(const auto& rb : reducedBins) { + out< +#include +#include + +#include +#include +#include +#include +#include "iputils.hh" +#include "statbag.hh" +#include + +#include "namespaces.hh" +using namespace boost::multi_index; + +struct TimeTag{}; + +template class Inflighter +{ +public: + Inflighter(Container& c, SenderReceiver& sr) : d_container(c), d_sr(sr), d_init(false) + { + d_burst = 2; + d_maxInFlight = 5; + d_timeoutSeconds = 3; + d_unexpectedResponse = d_timeouts = 0; + } + void init() + { + d_iter = d_container.begin(); + d_init=true; + } + + bool run(); //!< keep calling this as long as it returns 1, or if it throws an exception + + unsigned int d_maxInFlight; + unsigned int d_timeoutSeconds; + int d_burst; + + uint64_t getTimeouts() + { + return d_timeouts; + } + + uint64_t getUnexpecteds() + { + return d_unexpectedResponse; + } + +private: + struct TTDItem + { + typename Container::iterator iter; + typename SenderReceiver::Identifier id; + struct timeval sentTime, ttd; + }; + + typedef multi_index_container< + TTDItem, + indexed_by< + ordered_unique< + member + >, + ordered_non_unique< + tag, + member + > + > + >ttdwatch_t; + + Container& d_container; + SenderReceiver& d_sr; + + ttdwatch_t d_ttdWatch; + typename Container::iterator d_iter; + bool d_init; + + uint64_t d_unexpectedResponse, d_timeouts; +}; + +template bool Inflighter::run() +{ + if(!d_init) + init(); + + for(;;) { + int burst = 0; + + // 'send' as many items as allowed, limited by 'max in flight' and our burst parameter (which limits query rate growth) + while(d_iter != d_container.end() && d_ttdWatch.size() < d_maxInFlight) { + TTDItem ttdi; + ttdi.iter = d_iter++; + ttdi.id = d_sr.send(*ttdi.iter); + gettimeofday(&ttdi.sentTime, 0); + ttdi.ttd = ttdi.sentTime; + ttdi.ttd.tv_sec += d_timeoutSeconds; + if(d_ttdWatch.count(ttdi.id)) { +// cerr<<"DUPLICATE INSERT!"<sentTime.tv_sec) + (now.tv_usec - ival->sentTime.tv_usec); + d_sr.deliverAnswer(*ival->iter, answer, usec); // deliver to sender/receiver + d_ttdWatch.erase(ival); + break; // we can send new questions! + } + else { + // cerr<<"UNEXPECTED ANSWER: "< 10000 */ ) { // no new responses, time for some cleanup of the ttdWatch + struct timeval now; + gettimeofday(&now, 0); + + typedef typename ttdwatch_t::template index::type waiters_by_ttd_index_t; + waiters_by_ttd_index_t& waiters_index = boost::multi_index::get(d_ttdWatch); + + // this provides a list of items sorted by age + for(typename waiters_by_ttd_index_t::iterator valiter = waiters_index.begin(); valiter != waiters_index.end(); ) { + if(valiter->ttd.tv_sec < now.tv_sec || (valiter->ttd.tv_sec == now.tv_sec && valiter->ttd.tv_usec < now.tv_usec)) { + d_sr.deliverTimeout(valiter->id); // so backend can release id + waiters_index.erase(valiter++); + // cerr<<"Have timeout for id="<< valiter->id < 0) { + char buf[512]; + + int len = recv(d_socket, buf, sizeof(buf), 0); + string msg(buf, len); + if(sscanf(msg.c_str(), "%d %d", &id, &i) != 2) { + throw runtime_error("Invalid input"); + } + return 1; + } + return 0; + } + + void deliverAnswer(int& i, int j) + { + cerr<<"We sent "< numbers; + SendReceive sr; + Inflighter, SendReceive> inflighter(numbers, sr); + + for(int n=0; n < 100; ++n) + numbers.push_back(n*n); + + + for(;;) { + try { + inflighter.run(); + break; + } + catch(exception& e) { + cerr<<"Caught exception: "< +#include + +/* +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out); +*/ +std::string makeIPCipherKey(const std::string& password) +{ + static const char salt[]="ipcipheripcipher"; + unsigned char out[16]; + + PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(), (const unsigned char*)salt, sizeof(salt)-1, 50000, sizeof(out), out); + + return std::string((const char*)out, (const char*)out + sizeof(out)); +} + +static ComboAddress encryptCA4(const ComboAddress& ca, const std::string &key) +{ + if(key.size() != 16) + throw std::runtime_error("Need 128 bits of key for ipcrypt"); + + ComboAddress ret=ca; + + // always returns 0, has no failure mode + ipcrypt_encrypt( (unsigned char*)&ret.sin4.sin_addr.s_addr, + (const unsigned char*) &ca.sin4.sin_addr.s_addr, + (const unsigned char*)key.c_str()); + return ret; +} + +static ComboAddress decryptCA4(const ComboAddress& ca, const std::string &key) +{ + if(key.size() != 16) + throw std::runtime_error("Need 128 bits of key for ipcrypt"); + + ComboAddress ret=ca; + + // always returns 0, has no failure mode + ipcrypt_decrypt( (unsigned char*)&ret.sin4.sin_addr.s_addr, + (const unsigned char*) &ca.sin4.sin_addr.s_addr, + (const unsigned char*)key.c_str()); + return ret; +} + + +static ComboAddress encryptCA6(const ComboAddress& ca, const std::string &key) +{ + if(key.size() != 16) + throw std::runtime_error("Need 128 bits of key for ipcrypt"); + + ComboAddress ret=ca; + + AES_KEY wctx; + AES_set_encrypt_key((const unsigned char*)key.c_str(), 128, &wctx); + AES_encrypt((const unsigned char*)&ca.sin6.sin6_addr.s6_addr, + (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx); + + return ret; +} + +static ComboAddress decryptCA6(const ComboAddress& ca, const std::string &key) +{ + if(key.size() != 16) + throw std::runtime_error("Need 128 bits of key for ipcrypt"); + + ComboAddress ret=ca; + AES_KEY wctx; + AES_set_decrypt_key((const unsigned char*)key.c_str(), 128, &wctx); + AES_decrypt((const unsigned char*)&ca.sin6.sin6_addr.s6_addr, + (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx); + + return ret; +} + + +ComboAddress encryptCA(const ComboAddress& ca, const std::string& key) +{ + if(ca.sin4.sin_family == AF_INET) + return encryptCA4(ca, key); + else if(ca.sin4.sin_family == AF_INET6) + return encryptCA6(ca, key); + else + throw std::runtime_error("ipcrypt can't encrypt non-IP addresses"); +} + +ComboAddress decryptCA(const ComboAddress& ca, const std::string& key) +{ + if(ca.sin4.sin_family == AF_INET) + return decryptCA4(ca, key); + else if(ca.sin4.sin_family == AF_INET6) + return decryptCA6(ca, key); + else + throw std::runtime_error("ipcrypt can't decrypt non-IP addresses"); + +} diff --git a/pdns/ipcipher.hh b/pdns/ipcipher.hh new file mode 100644 index 0000000..cbb932d --- /dev/null +++ b/pdns/ipcipher.hh @@ -0,0 +1,9 @@ +#pragma once +#include "iputils.hh" +#include + +// see https://powerdns.org/ipcipher + +ComboAddress encryptCA(const ComboAddress& ca, const std::string& key); +ComboAddress decryptCA(const ComboAddress& ca, const std::string& key); +std::string makeIPCipherKey(const std::string& password); diff --git a/pdns/iputils.cc b/pdns/iputils.cc new file mode 100644 index 0000000..f58d0e3 --- /dev/null +++ b/pdns/iputils.cc @@ -0,0 +1,415 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "iputils.hh" +#include + +/** these functions provide a very lightweight wrapper to the Berkeley sockets API. Errors -> exceptions! */ + +static void RuntimeError(const boost::format& fmt) +{ + throw runtime_error(fmt.str()); +} + +static void NetworkErr(const boost::format& fmt) +{ + throw NetworkError(fmt.str()); +} + +int SSocket(int family, int type, int flags) +{ + int ret = socket(family, type, flags); + if(ret < 0) + RuntimeError(boost::format("creating socket of type %d: %s") % family % strerror(errno)); + return ret; +} + +int SConnect(int sockfd, const ComboAddress& remote) +{ + int ret = connect(sockfd, reinterpret_cast(&remote), remote.getSocklen()); + if(ret < 0) { + int savederrno = errno; + RuntimeError(boost::format("connecting socket to %s: %s") % remote.toStringWithPort() % strerror(savederrno)); + } + return ret; +} + +int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout) +{ + int ret = connect(sockfd, reinterpret_cast(&remote), remote.getSocklen()); + if(ret < 0) { + int savederrno = errno; + if (savederrno == EINPROGRESS) { + if (timeout <= 0) { + return savederrno; + } + + /* we wait until the connection has been established */ + bool error = false; + bool disconnected = false; + int res = waitForRWData(sockfd, false, timeout, 0, &error, &disconnected); + if (res == 1) { + if (error) { + savederrno = 0; + socklen_t errlen = sizeof(savederrno); + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&savederrno, &errlen) == 0) { + NetworkErr(boost::format("connecting to %s failed: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + else { + NetworkErr(boost::format("connecting to %s failed") % remote.toStringWithPort()); + } + } + if (disconnected) { + NetworkErr(boost::format("%s closed the connection") % remote.toStringWithPort()); + } + return 0; + } + else if (res == 0) { + NetworkErr(boost::format("timeout while connecting to %s") % remote.toStringWithPort()); + } else if (res < 0) { + savederrno = errno; + NetworkErr(boost::format("waiting to connect to %s: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + } + else { + NetworkErr(boost::format("connecting to %s: %s") % remote.toStringWithPort() % string(strerror(savederrno))); + } + } + + return 0; +} + +int SBind(int sockfd, const ComboAddress& local) +{ + int ret = bind(sockfd, (struct sockaddr*)&local, local.getSocklen()); + if(ret < 0) { + int savederrno = errno; + RuntimeError(boost::format("binding socket to %s: %s") % local.toStringWithPort() % strerror(savederrno)); + } + return ret; +} + +int SAccept(int sockfd, ComboAddress& remote) +{ + socklen_t remlen = remote.getSocklen(); + + int ret = accept(sockfd, (struct sockaddr*)&remote, &remlen); + if(ret < 0) + RuntimeError(boost::format("accepting new connection on socket: %s") % strerror(errno)); + return ret; +} + +int SListen(int sockfd, int limit) +{ + int ret = listen(sockfd, limit); + if(ret < 0) + RuntimeError(boost::format("setting socket to listen: %s") % strerror(errno)); + return ret; +} + +int SSetsockopt(int sockfd, int level, int opname, int value) +{ + int ret = setsockopt(sockfd, level, opname, &value, sizeof(value)); + if(ret < 0) + RuntimeError(boost::format("setsockopt for level %d and opname %d to %d failed: %s") % level % opname % value % strerror(errno)); + return ret; +} + +void setSocketIgnorePMTU(int sockfd) +{ +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) +#ifdef IP_PMTUDISC_OMIT + /* Linux 3.15+ has IP_PMTUDISC_OMIT, which discards PMTU information to prevent + poisoning, but still allows fragmentation if the packet size exceeds the + outgoing interface MTU, which is good. + */ + try { + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_OMIT); + return; + } + catch(const std::exception& e) { + /* failed, let's try IP_PMTUDISC_DONT instead */ + } +#endif /* IP_PMTUDISC_OMIT */ + + /* IP_PMTUDISC_DONT disables Path MTU discovery */ + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); +#endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) */ +} + +bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv) +{ +#ifdef SO_TIMESTAMP + struct cmsghdr *cmsg; + for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(msgh,cmsg)) { + if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP || cmsg->cmsg_type == SCM_TIMESTAMP) && + CMSG_LEN(sizeof(*tv)) == cmsg->cmsg_len) { + memcpy(tv, CMSG_DATA(cmsg), sizeof(*tv)); + return true; + } + } +#endif + return false; +} +bool HarvestDestinationAddress(const struct msghdr* msgh, ComboAddress* destination) +{ + destination->reset(); +#ifdef __NetBSD__ + struct cmsghdr* cmsg; +#else + const struct cmsghdr* cmsg; +#endif + for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(const_cast(msgh), const_cast(cmsg))) { +#if defined(IP_PKTINFO) + if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { + struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); + destination->sin4.sin_addr = i->ipi_addr; + destination->sin4.sin_family = AF_INET; + return true; + } +#elif defined(IP_RECVDSTADDR) + if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) { + struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg); + destination->sin4.sin_addr = *i; + destination->sin4.sin_family = AF_INET; + return true; + } +#endif + + if ((cmsg->cmsg_level == IPPROTO_IPV6) && (cmsg->cmsg_type == IPV6_PKTINFO)) { + struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg); + destination->sin6.sin6_addr = i->ipi6_addr; + destination->sin4.sin_family = AF_INET6; + return true; + } + } + return false; +} + +bool IsAnyAddress(const ComboAddress& addr) +{ + if(addr.sin4.sin_family == AF_INET) + return addr.sin4.sin_addr.s_addr == 0; + else if(addr.sin4.sin_family == AF_INET6) + return !memcmp(&addr.sin6.sin6_addr, &in6addr_any, sizeof(addr.sin6.sin6_addr)); + + return false; +} + +ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to) +{ + struct msghdr msgh; + struct iovec iov; + char cbuf[256]; + + /* Set up iov and msgh structures. */ + memset(&msgh, 0, sizeof(struct msghdr)); + iov.iov_base = (void*)data; + iov.iov_len = len; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_name = (struct sockaddr*)&to; + msgh.msg_namelen = to.getSocklen(); + + if(from.sin4.sin_family) { + addCMsgSrcAddr(&msgh, cbuf, &from, 0); + } + else { + msgh.msg_control=NULL; + } + return sendmsg(sock, &msgh, flags); +} + +// be careful: when using this for receive purposes, make sure addr->sin4.sin_family is set appropriately so getSocklen works! +// be careful: when using this function for *send* purposes, be sure to set cbufsize to 0! +// be careful: if you don't call addCMsgSrcAddr after fillMSGHdr, make sure to set msg_control to NULL +void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr) +{ + iov->iov_base = data; + iov->iov_len = datalen; + + memset(msgh, 0, sizeof(struct msghdr)); + + msgh->msg_control = cbuf; + msgh->msg_controllen = cbufsize; + msgh->msg_name = addr; + msgh->msg_namelen = addr->getSocklen(); + msgh->msg_iov = iov; + msgh->msg_iovlen = 1; + msgh->msg_flags = 0; +} + +// warning: various parts of PowerDNS assume 'truncate' will never throw +void ComboAddress::truncate(unsigned int bits) noexcept +{ + uint8_t* start; + int len=4; + if(sin4.sin_family==AF_INET) { + if(bits >= 32) + return; + start = (uint8_t*)&sin4.sin_addr.s_addr; + len=4; + } + else { + if(bits >= 128) + return; + start = (uint8_t*)&sin6.sin6_addr.s6_addr; + len=16; + } + + auto tozero= len*8 - bits; // if set to 22, this will clear 1 byte, as it should + + memset(start + len - tozero/8, 0, tozero/8); // blot out the whole bytes on the right + + auto bitsleft=tozero % 8; // 2 bits left to clear + + // a b c d, to truncate to 22 bits, we just zeroed 'd' and need to zero 2 bits from c + // so and by '11111100', which is ~((1<<2)-1) = ~3 + uint8_t* place = start + len - 1 - tozero/8; + *place &= (~((1<(const_cast(dest)); + msgh.msg_namelen = dest->getSocklen(); + } + else { + msgh.msg_name = nullptr; + msgh.msg_namelen = 0; + } + + msgh.msg_flags = 0; + + if (localItf != 0 && local) { + addCMsgSrcAddr(&msgh, cbuf, local, localItf); + } + + iov.iov_base = reinterpret_cast(const_cast(buffer)); + iov.iov_len = len; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_flags = 0; + + size_t sent = 0; + bool firstTry = true; + + do { + +#ifdef MSG_FASTOPEN + if (flags & MSG_FASTOPEN && firstTry == false) { + flags &= ~MSG_FASTOPEN; + } +#endif /* MSG_FASTOPEN */ + + ssize_t res = sendmsg(fd, &msgh, flags); + + if (res > 0) { + size_t written = static_cast(res); + sent += written; + + if (sent == len) { + return sent; + } + + /* partial write */ + firstTry = false; + iov.iov_len -= written; + iov.iov_base = reinterpret_cast(reinterpret_cast(iov.iov_base) + written); + written = 0; + } + else if (res == 0) { + return res; + } + else if (res == -1) { + if (errno == EINTR) { + continue; + } + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) { + /* EINPROGRESS might happen with non blocking socket, + especially with TCP Fast Open */ + return sent; + } + else { + unixDie("failed in sendMsgWithTimeout"); + } + } + } + while (true); + + return 0; +} + +template class NetmaskTree; + +/* requires a non-blocking socket. + On Linux, we could use MSG_DONTWAIT on a blocking socket + but this is not portable. +*/ +bool isTCPSocketUsable(int sock) +{ + int err = 0; + char buf = '\0'; + size_t buf_size = sizeof(buf); + + do { + ssize_t got = recv(sock, &buf, buf_size, MSG_PEEK); + + if (got > 0) { + /* socket is usable, some data is even waiting to be read */ + return true; + } + else if (got == 0) { + /* other end has closed the socket */ + return false; + } + else { + err = errno; + + if (err == EAGAIN || err == EWOULDBLOCK) { + /* socket is usable, no data waiting */ + return true; + } + else { + if (err != EINTR) { + /* something is wrong, could be ECONNRESET, + ENOTCONN, EPIPE, but anyway this socket is + not usable. */ + return false; + } + } + } + } while (err == EINTR); + + return false; +} diff --git a/pdns/iputils.hh b/pdns/iputils.hh new file mode 100644 index 0000000..18d6e88 --- /dev/null +++ b/pdns/iputils.hh @@ -0,0 +1,1069 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_IPUTILSHH +#define PDNS_IPUTILSHH + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pdnsexception.hh" +#include "misc.hh" +#include +#include +#include +#include +#include + +#include "namespaces.hh" + +#ifdef __APPLE__ +#include + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) + +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) + +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) +#endif + +#ifdef __sun + +#define htobe16(x) BE_16(x) +#define htole16(x) LE_16(x) +#define be16toh(x) BE_IN16(&(x)) +#define le16toh(x) LE_IN16(&(x)) + +#define htobe32(x) BE_32(x) +#define htole32(x) LE_32(x) +#define be32toh(x) BE_IN32(&(x)) +#define le32toh(x) LE_IN32(&(x)) + +#define htobe64(x) BE_64(x) +#define htole64(x) LE_64(x) +#define be64toh(x) BE_IN64(&(x)) +#define le64toh(x) LE_IN64(&(x)) + +#endif + +#ifdef __FreeBSD__ +#include +#endif + +#if defined(__NetBSD__) && defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR) +// The IP_PKTINFO option in NetBSD was incompatible with Linux until a +// change that also introduced IP_SENDSRCADDR for FreeBSD compatibility. +#undef IP_PKTINFO +#endif + +union ComboAddress { + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + + bool operator==(const ComboAddress& rhs) const + { + if(boost::tie(sin4.sin_family, sin4.sin_port) != boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port)) + return false; + if(sin4.sin_family == AF_INET) + return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr; + else + return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0; + } + + bool operator!=(const ComboAddress& rhs) const + { + return(!operator==(rhs)); + } + + bool operator<(const ComboAddress& rhs) const + { + if(sin4.sin_family == 0) { + return false; + } + if(boost::tie(sin4.sin_family, sin4.sin_port) < boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port)) + return true; + if(boost::tie(sin4.sin_family, sin4.sin_port) > boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port)) + return false; + + if(sin4.sin_family == AF_INET) + return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr; + else + return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0; + } + + bool operator>(const ComboAddress& rhs) const + { + return rhs.operator<(*this); + } + + struct addressOnlyHash + { + uint32_t operator()(const ComboAddress& ca) const + { + const unsigned char* start; + int len; + if(ca.sin4.sin_family == AF_INET) { + start =(const unsigned char*)&ca.sin4.sin_addr.s_addr; + len=4; + } + else { + start =(const unsigned char*)&ca.sin6.sin6_addr.s6_addr; + len=16; + } + return burtle(start, len, 0); + } + }; + + struct addressOnlyLessThan: public std::binary_function + { + bool operator()(const ComboAddress& a, const ComboAddress& b) const + { + if(a.sin4.sin_family < b.sin4.sin_family) + return true; + if(a.sin4.sin_family > b.sin4.sin_family) + return false; + if(a.sin4.sin_family == AF_INET) + return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr; + else + return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0; + } + }; + + struct addressOnlyEqual: public std::binary_function + { + bool operator()(const ComboAddress& a, const ComboAddress& b) const + { + if(a.sin4.sin_family != b.sin4.sin_family) + return false; + if(a.sin4.sin_family == AF_INET) + return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr; + else + return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)); + } + }; + + + socklen_t getSocklen() const + { + if(sin4.sin_family == AF_INET) + return sizeof(sin4); + else + return sizeof(sin6); + } + + ComboAddress() + { + sin4.sin_family=AF_INET; + sin4.sin_addr.s_addr=0; + sin4.sin_port=0; + sin6.sin6_scope_id = 0; + sin6.sin6_flowinfo = 0; + } + + ComboAddress(const struct sockaddr *sa, socklen_t salen) { + setSockaddr(sa, salen); + }; + + ComboAddress(const struct sockaddr_in6 *sa) { + setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6)); + }; + + ComboAddress(const struct sockaddr_in *sa) { + setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in)); + }; + + void setSockaddr(const struct sockaddr *sa, socklen_t salen) { + if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6"); + memcpy(this, sa, salen); + } + + // 'port' sets a default value in case 'str' does not set a port + explicit ComboAddress(const string& str, uint16_t port=0) + { + memset(&sin6, 0, sizeof(sin6)); + sin4.sin_family = AF_INET; + sin4.sin_port = 0; + if(makeIPv4sockaddr(str, &sin4)) { + sin6.sin6_family = AF_INET6; + if(makeIPv6sockaddr(str, &sin6) < 0) + throw PDNSException("Unable to convert presentation address '"+ str +"'"); + + } + if(!sin4.sin_port) // 'str' overrides port! + sin4.sin_port=htons(port); + } + + bool isIPv6() const + { + return sin4.sin_family == AF_INET6; + } + bool isIPv4() const + { + return sin4.sin_family == AF_INET; + } + + bool isMappedIPv4() const + { + if(sin4.sin_family!=AF_INET6) + return false; + + int n=0; + const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr; + for(n=0; n < 10; ++n) + if(ptr[n]) + return false; + + for(; n < 12; ++n) + if(ptr[n]!=0xff) + return false; + + return true; + } + + ComboAddress mapToIPv4() const + { + if(!isMappedIPv4()) + throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4"); + ComboAddress ret; + ret.sin4.sin_family=AF_INET; + ret.sin4.sin_port=sin4.sin_port; + + const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr; + ptr+=(sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr)); + memcpy(&ret.sin4.sin_addr.s_addr, ptr, sizeof(ret.sin4.sin_addr.s_addr)); + return ret; + } + + string toString() const + { + char host[1024]; + int retval = 0; + if(sin4.sin_family && !(retval = getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST))) + return string(host); + else + return "invalid "+string(gai_strerror(retval)); + } + + string toStringWithPort() const + { + if(sin4.sin_family==AF_INET) + return toString() + ":" + std::to_string(ntohs(sin4.sin_port)); + else + return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port)); + } + + string toStringWithPortExcept(int port) const + { + if(ntohs(sin4.sin_port) == port) + return toString(); + if(sin4.sin_family==AF_INET) + return toString() + ":" + std::to_string(ntohs(sin4.sin_port)); + else + return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port)); + } + + string toLogString() const + { + return toStringWithPortExcept(53); + } + + void truncate(unsigned int bits) noexcept; + + uint16_t getPort() const + { + return ntohs(sin4.sin_port); + } + + ComboAddress setPort(uint16_t port) const + { + ComboAddress ret(*this); + ret.sin4.sin_port=htons(port); + return ret; + } + + void reset() + { + memset(&sin4, 0, sizeof(sin4)); + memset(&sin6, 0, sizeof(sin6)); + } + +}; + +/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */ +class NetmaskException: public PDNSException +{ +public: + NetmaskException(const string &a) : PDNSException(a) {} +}; + +inline ComboAddress makeComboAddress(const string& str) +{ + ComboAddress address; + address.sin4.sin_family=AF_INET; + if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) { + address.sin4.sin_family=AF_INET6; + if(makeIPv6sockaddr(str, &address.sin6) < 0) + throw NetmaskException("Unable to convert '"+str+"' to a netmask"); + } + return address; +} + +inline ComboAddress makeComboAddressFromRaw(uint8_t version, const char* raw, size_t len) +{ + ComboAddress address; + + if (version == 4) { + address.sin4.sin_family = AF_INET; + if (len != sizeof(address.sin4.sin_addr)) throw NetmaskException("invalid raw address length"); + memcpy(&address.sin4.sin_addr, raw, sizeof(address.sin4.sin_addr)); + } + else if (version == 6) { + address.sin6.sin6_family = AF_INET6; + if (len != sizeof(address.sin6.sin6_addr)) throw NetmaskException("invalid raw address length"); + memcpy(&address.sin6.sin6_addr, raw, sizeof(address.sin6.sin6_addr)); + } + else throw NetmaskException("invalid address family"); + + return address; +} + +inline ComboAddress makeComboAddressFromRaw(uint8_t version, const string &str) +{ + return makeComboAddressFromRaw(version, str.c_str(), str.size()); +} + +/** This class represents a netmask and can be queried to see if a certain + IP address is matched by this mask */ +class Netmask +{ +public: + Netmask() + { + d_network.sin4.sin_family=0; // disable this doing anything useful + d_network.sin4.sin_port = 0; // this guarantees d_network compares identical + d_mask=0; + d_bits=0; + } + + Netmask(const ComboAddress& network, uint8_t bits=0xff): d_network(network) + { + d_network.sin4.sin_port=0; + if(bits > 128) + bits = (network.sin4.sin_family == AF_INET) ? 32 : 128; + + d_bits = bits; + if(d_bits<32) + d_mask=~(0xFFFFFFFF>>d_bits); + else + d_mask=0xFFFFFFFF; // not actually used for IPv6 + } + + //! Constructor supplies the mask, which cannot be changed + Netmask(const string &mask) + { + pair split=splitField(mask,'/'); + d_network=makeComboAddress(split.first); + + if(!split.second.empty()) { + d_bits = (uint8_t)pdns_stou(split.second); + if(d_bits<32) + d_mask=~(0xFFFFFFFF>>d_bits); + else + d_mask=0xFFFFFFFF; + } + else if(d_network.sin4.sin_family==AF_INET) { + d_bits = 32; + d_mask = 0xFFFFFFFF; + } + else { + d_bits=128; + d_mask=0; // silence silly warning - d_mask is unused for IPv6 + } + } + + bool match(const ComboAddress& ip) const + { + return match(&ip); + } + + //! If this IP address in socket address matches + bool match(const ComboAddress *ip) const + { + if(d_network.sin4.sin_family != ip->sin4.sin_family) { + return false; + } + if(d_network.sin4.sin_family == AF_INET) { + return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr)); + } + if(d_network.sin6.sin6_family == AF_INET6) { + uint8_t bytes=d_bits/8, n; + const uint8_t *us=(const uint8_t*) &d_network.sin6.sin6_addr.s6_addr; + const uint8_t *them=(const uint8_t*) &ip->sin6.sin6_addr.s6_addr; + + for(n=0; n < bytes; ++n) { + if(us[n]!=them[n]) { + return false; + } + } + // still here, now match remaining bits + uint8_t bits= d_bits % 8; + uint8_t mask= (uint8_t) ~(0xFF>>bits); + + return((us[n] & mask) == (them[n] & mask)); + } + return false; + } + + //! If this ASCII IP address matches + bool match(const string &ip) const + { + ComboAddress address=makeComboAddress(ip); + return match(&address); + } + + //! If this IP address in native format matches + bool match4(uint32_t ip) const + { + return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask); + } + + string toString() const + { + return d_network.toString()+"/"+std::to_string((unsigned int)d_bits); + } + + string toStringNoMask() const + { + return d_network.toString(); + } + const ComboAddress& getNetwork() const + { + return d_network; + } + const ComboAddress getMaskedNetwork() const + { + ComboAddress result(d_network); + if(isIpv4()) { + result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask); + } + else if(isIpv6()) { + size_t idx; + uint8_t bytes=d_bits/8; + uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr; + uint8_t bits= d_bits % 8; + uint8_t mask= (uint8_t) ~(0xFF>>bits); + + if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) { + us[bytes] &= mask; + } + + for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) { + us[idx] = 0; + } + } + return result; + } + uint8_t getBits() const + { + return d_bits; + } + bool isIpv6() const + { + return d_network.sin6.sin6_family == AF_INET6; + } + bool isIpv4() const + { + return d_network.sin4.sin_family == AF_INET; + } + + bool operator<(const Netmask& rhs) const + { + if (empty() && !rhs.empty()) + return false; + + if (!empty() && rhs.empty()) + return true; + + if (d_bits > rhs.d_bits) + return true; + if (d_bits < rhs.d_bits) + return false; + + return d_network < rhs.d_network; + } + + bool operator>(const Netmask& rhs) const + { + return rhs.operator<(*this); + } + + bool operator==(const Netmask& rhs) const + { + return tie(d_network, d_bits) == tie(rhs.d_network, rhs.d_bits); + } + + bool empty() const + { + return d_network.sin4.sin_family==0; + } + +private: + ComboAddress d_network; + uint32_t d_mask; + uint8_t d_bits; +}; + +/** Per-bit binary tree map implementation with pair. + * + * This is an binary tree implementation for storing attributes for IPv4 and IPv6 prefixes. + * The most simple use case is simple NetmaskTree used by NetmaskGroup, which only + * wants to know if given IP address is matched in the prefixes stored. + * + * This element is useful for anything that needs to *STORE* prefixes, and *MATCH* IP addresses + * to a *LIST* of *PREFIXES*. Not the other way round. + * + * You can store IPv4 and IPv6 addresses to same tree, separate payload storage is kept per AFI. + * + * To erase something copy values to new tree sans the value you want to erase. + * + * Use swap if you need to move the tree to another NetmaskTree instance, it is WAY faster + * than using copy ctor or assignment operator, since it moves the nodes and tree root to + * new home instead of actually recreating the tree. + * + * Please see NetmaskGroup for example of simple use case. Other usecases can be found + * from GeoIPBackend and Sortlist, and from dnsdist. + */ +template +class NetmaskTree { +public: + typedef Netmask key_type; + typedef T value_type; + typedef std::pair node_type; + typedef size_t size_type; + +private: + /** Single node in tree, internal use only. + */ + class TreeNode : boost::noncopyable { + public: + explicit TreeNode(int bits) noexcept : parent(NULL),d_bits(bits) { + } + + //(new TreeNode(d_bits+1)); + left->parent = this; + } + return left.get(); + } + + //(new TreeNode(d_bits+1)); + right->parent = this; + } + return right.get(); + } + + unique_ptr left; + unique_ptr right; + TreeNode* parent; + + unique_ptr node4; // node6; //first).second = node->second; + } + + NetmaskTree& operator=(const NetmaskTree& rhs) { + clear(); + // see above. + for(auto const& node: rhs._nodes) + insert(node->first).second = node->second; + d_cleanup_tree = rhs.d_cleanup_tree; + return *this; + } + + const typename std::set::const_iterator begin() const { return _nodes.begin(); } + const typename std::set::const_iterator end() const { return _nodes.end(); } + + typename std::set::iterator begin() { return _nodes.begin(); } + typename std::set::iterator end() { return _nodes.end(); } + + node_type& insert(const string &mask) { + return insert(key_type(mask)); + } + + //(new TreeNode(0)); + TreeNode* node = root.get(); + node_type* value = nullptr; + + if (key.getNetwork().sin4.sin_family == AF_INET) { + std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr)); + int bits = 0; + // we turn left on 0 and right on 1 + while(bits < key.getBits()) { + uint8_t val = addr[31-bits]; + if (val) + node = node->make_right(); + else + node = node->make_left(); + bits++; + } + // only create node if not yet assigned + if (!node->node4) { + node->node4 = unique_ptr(new node_type()); + _nodes.insert(node->node4.get()); + } + value = node->node4.get(); + } else { + uint64_t addr[2]; + memcpy(addr, key.getNetwork().sin6.sin6_addr.s6_addr, sizeof(addr)); + std::bitset<64> addr_low(be64toh(addr[1])); + std::bitset<64> addr_high(be64toh(addr[0])); + int bits = 0; + while(bits < key.getBits()) { + uint8_t val; + // we use high address until we are + if (bits < 64) val = addr_high[63-bits]; + // past 64 bits, and start using low address + else val = addr_low[127-bits]; + + // we turn left on 0 and right on 1 + if (val) + node = node->make_right(); + else + node = node->make_left(); + bits++; + } + // only create node if not yet assigned + if (!node->node6) { + node->node6 = unique_ptr(new node_type()); + _nodes.insert(node->node6.get()); + } + value = node->node6.get(); + } + // assign key + value->first = key; + return *value; + } + + //first == key; + } + + // addr(be32toh(value.sin4.sin_addr.s_addr)); + int bits = 0; + + while(bits < max_bits) { + // ...we keep track of last non-empty node + if (node->node4) ret = node->node4.get(); + uint8_t val = addr[31-bits]; + // ...and we don't create left/right hand + if (val) { + if (node->right) node = node->right.get(); + // ..and we break when road ends + else break; + } else { + if (node->left) node = node->left.get(); + else break; + } + bits++; + } + // needed if we did not find one in loop + if (node->node4) ret = node->node4.get(); + } else { + uint64_t addr[2]; + memcpy(addr, value.sin6.sin6_addr.s6_addr, sizeof(addr)); + max_bits = std::max(0,std::min(max_bits,128)); + std::bitset<64> addr_low(be64toh(addr[1])); + std::bitset<64> addr_high(be64toh(addr[0])); + int bits = 0; + while(bits < max_bits) { + if (node->node6) ret = node->node6.get(); + uint8_t val; + if (bits < 64) val = addr_high[63-bits]; + else val = addr_low[127-bits]; + if (val) { + if (node->right) node = node->right.get(); + else break; + } else { + if (node->left) node = node->left.get(); + else break; + } + bits++; + } + if (node->node6) ret = node->node6.get(); + } + + // this can be nullptr. + return ret; + } + + void cleanup_tree(TreeNode* node) + { + // only cleanup this node if it has no children and node4 and node6 are both empty + if (!(node->left || node->right || node->node6 || node->node4)) { + // get parent node ptr + TreeNode* parent = node->parent; + // delete this node + if (parent) { + if (parent->left.get() == node) + parent->left.reset(); + else + parent->right.reset(); + // now recurse up to the parent + cleanup_tree(parent); + } + } + } + + // addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr)); + int bits = 0; + while(node && bits < key.getBits()) { + uint8_t val = addr[31-bits]; + if (val) { + node = node->right.get(); + } else { + node = node->left.get(); + } + bits++; + } + if (node) { + _nodes.erase(node->node4.get()); + node->node4.reset(); + + if (d_cleanup_tree) + cleanup_tree(node); + } + } else { + uint64_t addr[2]; + memcpy(addr, key.getNetwork().sin6.sin6_addr.s6_addr, sizeof(addr)); + std::bitset<64> addr_low(be64toh(addr[1])); + std::bitset<64> addr_high(be64toh(addr[0])); + int bits = 0; + while(node && bits < key.getBits()) { + uint8_t val; + if (bits < 64) val = addr_high[63-bits]; + else val = addr_low[127-bits]; + if (val) { + node = node->right.get(); + } else { + node = node->left.get(); + } + bits++; + } + if (node) { + _nodes.erase(node->node6.get()); + node->node6.reset(); + + if (d_cleanup_tree) + cleanup_tree(node); + } + } + } + + void erase(const string& key) { + erase(key_type(key)); + } + + // root; // _nodes; //second; + return false; + } + + bool match(const ComboAddress& ip) const + { + return match(&ip); + } + + bool lookup(const ComboAddress* ip, Netmask* nmp) const + { + const auto &ret = tree.lookup(*ip); + if (ret) { + if (nmp != nullptr) + *nmp = ret->first; + + return ret->second; + } + return false; + } + + bool lookup(const ComboAddress& ip, Netmask* nmp) const + { + return lookup(&ip, nmp); + } + + //! Add this string to the list of possible matches + void addMask(const string &ip, bool positive=true) + { + if(!ip.empty() && ip[0] == '!') { + addMask(Netmask(ip.substr(1)), false); + } else { + addMask(Netmask(ip), positive); + } + } + + //! Add this Netmask to the list of possible matches + void addMask(const Netmask& nm, bool positive=true) + { + tree.insert(nm).second=positive; + } + + //! Delete this Netmask from the list of possible matches + void deleteMask(const Netmask& nm) + { + tree.erase(nm); + } + + void deleteMask(const std::string& ip) + { + if (!ip.empty()) + deleteMask(Netmask(ip)); + } + + void clear() + { + tree.clear(); + } + + bool empty() const + { + return tree.empty(); + } + + size_t size() const + { + return tree.size(); + } + + string toString() const + { + ostringstream str; + for(auto iter = tree.begin(); iter != tree.end(); ++iter) { + if(iter != tree.begin()) + str <<", "; + if(!((*iter)->second)) + str<<"!"; + str<<(*iter)->first.toString(); + } + return str.str(); + } + + void toStringVector(vector* vec) const + { + for(auto iter = tree.begin(); iter != tree.end(); ++iter) { + vec->push_back(((*iter)->second ? "" : "!") + (*iter)->first.toString()); + } + } + + void toMasks(const string &ips) + { + vector parts; + stringtok(parts, ips, ", \t"); + + for (vector::const_iterator iter = parts.begin(); iter != parts.end(); ++iter) + addMask(*iter); + } + +private: + NetmaskTree tree; +}; + + +struct SComboAddress +{ + SComboAddress(const ComboAddress& orig) : ca(orig) {} + ComboAddress ca; + bool operator<(const SComboAddress& rhs) const + { + return ComboAddress::addressOnlyLessThan()(ca, rhs.ca); + } + operator const ComboAddress&() + { + return ca; + } +}; + +class NetworkError : public runtime_error +{ +public: + NetworkError(const string& why="Network Error") : runtime_error(why.c_str()) + {} + NetworkError(const char *why="Network Error") : runtime_error(why) + {} +}; + +int SSocket(int family, int type, int flags); +int SConnect(int sockfd, const ComboAddress& remote); +/* tries to connect to remote for a maximum of timeout seconds. + sockfd should be set to non-blocking beforehand. + returns 0 on success (the socket is writable), throw a + runtime_error otherwise */ +int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout); +int SBind(int sockfd, const ComboAddress& local); +int SAccept(int sockfd, ComboAddress& remote); +int SListen(int sockfd, int limit); +int SSetsockopt(int sockfd, int level, int opname, int value); +void setSocketIgnorePMTU(int sockfd); + +#if defined(IP_PKTINFO) + #define GEN_IP_PKTINFO IP_PKTINFO +#elif defined(IP_RECVDSTADDR) + #define GEN_IP_PKTINFO IP_RECVDSTADDR +#endif + +bool IsAnyAddress(const ComboAddress& addr); +bool HarvestDestinationAddress(const struct msghdr* msgh, ComboAddress* destination); +bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv); +void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr); +ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to); +size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags); + +/* requires a non-blocking, connected TCP socket */ +bool isTCPSocketUsable(int sock); + +extern template class NetmaskTree; + +#endif diff --git a/pdns/ixfr.cc b/pdns/ixfr.cc new file mode 100644 index 0000000..0a7dca9 --- /dev/null +++ b/pdns/ixfr.cc @@ -0,0 +1,259 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "ixfr.hh" +#include "sstuff.hh" +#include "dns_random.hh" +#include "dnsrecords.hh" +#include "dnssecinfra.hh" +#include "tsigverifier.hh" + +vector, vector > > processIXFRRecords(const ComboAddress& master, const DNSName& zone, + const vector& records, const std::shared_ptr& masterSOA) +{ + vector, vector > > ret; + + if (records.size() == 0 || masterSOA == nullptr) { + return ret; + } + + // we start at 1 to skip the first SOA record + // we don't increase pos because the final SOA + // of the previous sequence is also the first SOA + // of this one + for(unsigned int pos = 1; pos < records.size(); ) { + vector remove, add; + + // cerr<<"Looking at record in position "<(records[pos]); + if (!sr) { + throw std::runtime_error("Error getting the content of the first SOA record of this IXFR sequence for zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()+"'"); + } + + // cerr<<"Serial is "<d_st.serial<<", final serial is "<d_st.serial<d_st.serial == masterSOA->d_st.serial) { + if (records.size() == 2) { + // if the entire update is two SOAs records with the same + // serial, this is actually an empty AXFR! + return {{remove, records}}; + } + + // if it's the final SOA, there is nothing for us to see + break; + } + + remove.push_back(records[pos]); // this adds the SOA + + // process removals + for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) { + remove.push_back(records[pos]); + } + + if (pos >= records.size()) { + throw std::runtime_error("No SOA record to finish the removals part of the IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + + sr = getRR(records[pos]); + if (!sr) { + throw std::runtime_error("Invalid SOA record to finish the removals part of the IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + + // this is the serial of the zone after the removals + // and updates, but that might not be the final serial + // because there might be several sequences + uint32_t newSerial = sr->d_st.serial; + add.push_back(records[pos]); // this adds the new SOA + + // process additions + for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) { + add.push_back(records[pos]); + } + + if (pos >= records.size()) { + throw std::runtime_error("No SOA record to finish the additions part of the IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + + sr = getRR(records[pos]); + if (!sr) { + throw std::runtime_error("Invalid SOA record to finish the additions part of the IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + + if (sr->d_st.serial != newSerial) { + throw std::runtime_error("Invalid serial (" + std::to_string(sr->d_st.serial) + ", expecting " + std::to_string(newSerial) + ") in the SOA record finishing the additions part of the IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + + if (newSerial == masterSOA->d_st.serial) { + // this was the last sequence + if (pos != (records.size() - 1)) { + throw std::runtime_error("Trailing records after the last IXFR sequence of zone '" + zone.toLogString() + "' from " + master.toStringWithPort()); + } + } + + ret.push_back(make_pair(remove,add)); + } + + return ret; +} + +// Returns pairs of "remove & add" vectors. If you get an empty remove, it means you got an AXFR! +vector, vector > > getIXFRDeltas(const ComboAddress& master, const DNSName& zone, const DNSRecord& oursr, + const TSIGTriplet& tt, const ComboAddress* laddr, size_t maxReceivedBytes) +{ + vector, vector > > ret; + vector packet; + DNSPacketWriter pw(packet, zone, QType::IXFR); + pw.getHeader()->qr=0; + pw.getHeader()->rd=0; + pw.getHeader()->id=dns_random(0xffff); + pw.startRecord(zone, QType::SOA, 0, QClass::IN, DNSResourceRecord::AUTHORITY); + oursr.d_content->toPacket(pw); + + pw.commit(); + TSIGRecordContent trc; + TSIGTCPVerifier tsigVerifier(tt, master, trc); + if(!tt.algo.empty()) { + TSIGHashEnum the; + getTSIGHashEnum(tt.algo, the); + try { + trc.d_algoName = getTSIGAlgoName(the); + } catch(PDNSException& pe) { + throw std::runtime_error("TSIG algorithm '"+tt.algo.toLogString()+"' is unknown."); + } + trc.d_time = time((time_t*)NULL); + trc.d_fudge = 300; + trc.d_origID=ntohs(pw.getHeader()->id); + trc.d_eRcode=0; + addTSIG(pw, trc, tt.name, tt.secret, "", false); + } + uint16_t len=htons(packet.size()); + string msg((const char*)&len, 2); + msg.append((const char*)&packet[0], packet.size()); + + Socket s(master.sin4.sin_family, SOCK_STREAM); + // cout<<"going to connect"< masterSOA = nullptr; + vector records; + size_t receivedBytes = 0; + int8_t ixfrInProgress = -2; + std::string reply; + + for(;;) { + // IXFR end + if (ixfrInProgress >= 0) + break; + + if(s.read((char*)&len, sizeof(len)) != sizeof(len)) + break; + + len=ntohs(len); + // cout<<"Got chunk of "< 0 && (maxReceivedBytes - receivedBytes) < (size_t) len) + throw std::runtime_error("Reached the maximum number of received bytes in an IXFR delta for zone '"+zone.toLogString()+"' from master "+master.toStringWithPort()); + + reply.resize(len); + readn2(s.getHandle(), &reply.at(0), len); + receivedBytes += len; + + MOADNSParser mdp(false, reply); + if(mdp.d_header.rcode) + throw std::runtime_error("Got an error trying to IXFR zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()+"': "+RCode::to_s(mdp.d_header.rcode)); + + // cout<<"Got a response, rcode: "<getZoneRepresentation()<(r.first); + if (!sr) { + throw std::runtime_error("Error getting the content of the first SOA record of the IXFR answer for zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()+"'"); + } + + if(sr->d_st.serial == std::dynamic_pointer_cast(oursr.d_content)->d_st.serial) { + // we are up to date + return ret; + } + masterSOA = sr; + } else if (r.first.d_type == QType::SOA) { + auto sr = getRR(r.first); + if (!sr) { + throw std::runtime_error("Error getting the content of SOA record of IXFR answer for zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()+"'"); + } + + // we hit the last SOA record + // IXFR is considered to be done if we hit the last SOA record twice + if (masterSOA->d_st.serial == sr->d_st.serial) { + ixfrInProgress++; + } + } + + if(r.first.d_place != DNSResourceRecord::ANSWER) { + if(r.first.d_type == QType::TSIG) + continue; + + if(r.first.d_type == QType::OPT) + continue; + + throw std::runtime_error("Unexpected record (" +QType(r.first.d_type).getName()+") in non-answer section ("+std::to_string(r.first.d_place)+")in IXFR response for zone '"+zone.toLogString()+"' from master '"+master.toStringWithPort()); + } + + r.first.d_name.makeUsRelative(zone); + records.push_back(r.first); + } + } + + // cout<<"Got "<, vector > > getIXFRDeltas(const ComboAddress& master, const DNSName& zone, + const DNSRecord& sr, const TSIGTriplet& tt=TSIGTriplet(), + const ComboAddress* laddr=0, size_t maxReceivedBytes=0); + +vector, vector > > processIXFRRecords(const ComboAddress& master, const DNSName& zone, + const vector& records, const std::shared_ptr& masterSOA); diff --git a/pdns/ixfrdist-stats.cc b/pdns/ixfrdist-stats.cc new file mode 100644 index 0000000..3aa9720 --- /dev/null +++ b/pdns/ixfrdist-stats.cc @@ -0,0 +1,108 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "ixfrdist-stats.hh" + +std::string ixfrdistStats::getStats() { + std::stringstream stats; + const std::string prefix = "ixfrdist_"; + + stats<<"# HELP "< +#include +#include + +#include "dnsname.hh" +#include "pdnsexception.hh" + +class ixfrdistStats { + public: + ixfrdistStats() { + progStats.startTime = time(nullptr); + } + + std::string getStats(); + + void setSOASerial(const DNSName& d, const uint32_t serial) { + auto stat = getRegisteredDomain(d); + stat->second.currentSOA = serial; + stat->second.haveZone = true; + } + void incrementSOAChecks(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numSOAChecks += amount; + } + void incrementSOAChecksFailed(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numSOAChecksFailed += amount; + } + void incrementSOAinQueries(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numSOAinQueries += amount; + } + void incrementAXFRinQueries(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numAXFRinQueries += amount; + } + void incrementIXFRinQueries(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numIXFRinQueries += amount; + } + void incrementAXFRFailures(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numAXFRFailures += amount; + } + void incrementIXFRFailures(const DNSName& d, const uint64_t amount = 1) { + getRegisteredDomain(d)->second.numIXFRFailures += amount; + } + void registerDomain(const DNSName& d) { + domainStats[d].haveZone = false; + } + private: + class perDomainStat { + public: + bool haveZone; + std::atomic currentSOA; // NOTE: this will wrongly be zero for unavailable zones + + std::atomic numSOAChecks; + std::atomic numSOAChecksFailed; + + std::atomic numSOAinQueries; + std::atomic numAXFRinQueries; + std::atomic numIXFRinQueries; + + std::atomic numAXFRFailures; + std::atomic numIXFRFailures; + }; + class programStats { + public: + time_t startTime; + }; + + std::map domainStats; + programStats progStats; + + std::map::iterator getRegisteredDomain(const DNSName& d) { + auto ret = domainStats.find(d); + if (ret == domainStats.end()) { + throw PDNSException("Domain '" + d.toLogString() + "' not defined in the statistics map"); + } + return ret; + }; +}; diff --git a/pdns/ixfrdist-web.cc b/pdns/ixfrdist-web.cc new file mode 100644 index 0000000..485e720 --- /dev/null +++ b/pdns/ixfrdist-web.cc @@ -0,0 +1,51 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "ixfrdist-web.hh" +#include +#include "threadname.hh" +#include "iputils.hh" +#include "ixfrdist-stats.hh" + +string doGetStats(); + +IXFRDistWebServer::IXFRDistWebServer(const ComboAddress &listenAddress, const NetmaskGroup &acl, const string &loglevel) : + d_ws(std::unique_ptr(new WebServer(listenAddress.toString(), listenAddress.getPort()))) +{ + d_ws->setACL(acl); + d_ws->setLogLevel(loglevel); + d_ws->registerWebHandler("/metrics", boost::bind(&IXFRDistWebServer::getMetrics, this, _1, _2)); + d_ws->bind(); +} + +void IXFRDistWebServer::go() { + setThreadName("ixfrdist/web"); + d_ws->go(); +} + +void IXFRDistWebServer::getMetrics(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + resp->body = doGetStats(); + resp->headers["Content-Type"] = "text/plain; version=0.0.4"; // https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format + resp->status = 200; +} diff --git a/pdns/ixfrdist-web.hh b/pdns/ixfrdist-web.hh new file mode 100644 index 0000000..e1c1734 --- /dev/null +++ b/pdns/ixfrdist-web.hh @@ -0,0 +1,37 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include "webserver.hh" +#include "iputils.hh" + +class IXFRDistWebServer +{ + public: + explicit IXFRDistWebServer(const ComboAddress &listenAddress, const NetmaskGroup &acl, const string &loglevel); + void go(); + + private: + std::unique_ptr d_ws; + + // All endpoints + void getMetrics(HttpRequest* req, HttpResponse* resp); +}; diff --git a/pdns/ixfrdist.cc b/pdns/ixfrdist.cc new file mode 100644 index 0000000..0b7f58f --- /dev/null +++ b/pdns/ixfrdist.cc @@ -0,0 +1,1393 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "threadname.hh" +#include +#include +#include +#include "ixfr.hh" +#include "ixfrutils.hh" +#include "resolver.hh" +#include "dns_random.hh" +#include "sstuff.hh" +#include "mplexer.hh" +#include "misc.hh" +#include "iputils.hh" +#include "logger.hh" +#include "ixfrdist-stats.hh" +#include "ixfrdist-web.hh" +#include + +/* BEGIN Needed because of deeper dependencies */ +#include "arguments.hh" +#include "statbag.hh" +StatBag S; + +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} +/* END Needed because of deeper dependencies */ + +// Allows reading/writing ComboAddresses and DNSNames in YAML-cpp +namespace YAML { +template<> +struct convert { + static Node encode(const ComboAddress& rhs) { + return Node(rhs.toStringWithPort()); + } + static bool decode(const Node& node, ComboAddress& rhs) { + if (!node.IsScalar()) { + return false; + } + try { + rhs = ComboAddress(node.as(), 53); + return true; + } catch(const runtime_error &e) { + return false; + } catch (const PDNSException &e) { + return false; + } + } +}; + +template<> +struct convert { + static Node encode(const DNSName& rhs) { + return Node(rhs.toStringRootDot()); + } + static bool decode(const Node& node, DNSName& rhs) { + if (!node.IsScalar()) { + return false; + } + try { + rhs = DNSName(node.as()); + return true; + } catch(const runtime_error &e) { + return false; + } catch (const PDNSException &e) { + return false; + } + } +}; + +template<> +struct convert { + static Node encode(const Netmask& rhs) { + return Node(rhs.toString()); + } + static bool decode(const Node& node, Netmask& rhs) { + if (!node.IsScalar()) { + return false; + } + try { + rhs = Netmask(node.as()); + return true; + } catch(const runtime_error &e) { + return false; + } catch (const PDNSException &e) { + return false; + } + } +}; +} // namespace YAML + +struct ixfrdiff_t { + shared_ptr oldSOA; + shared_ptr newSOA; + vector removals; + vector additions; + uint32_t oldSOATTL; + uint32_t newSOATTL; +}; + +struct ixfrinfo_t { + shared_ptr soa; // The SOA of the latest AXFR + records_t latestAXFR; // The most recent AXFR + vector> ixfrDiffs; + uint32_t soaTTL; +}; + +// Why a struct? This way we can add more options to a domain in the future +struct ixfrdistdomain_t { + set masters; // A set so we can do multiple master addresses in the future +}; + +// This contains the configuration for each domain +static map g_domainConfigs; + +// Map domains and their data +static std::map> g_soas; +static std::mutex g_soas_mutex; + +// Condition variable for TCP handling +static std::condition_variable g_tcpHandlerCV; +static std::queue> g_tcpRequestFDs; +static std::mutex g_tcpRequestFDsMutex; + +namespace po = boost::program_options; + +static bool g_exiting = false; + +static NetmaskGroup g_acl; +static bool g_compress = false; + +static ixfrdistStats g_stats; + +// g_stats is static, so local to this file. But the webserver needs this info +string doGetStats() { + return g_stats.getStats(); +} + +static void handleSignal(int signum) { + g_log< zoneVersions; + struct dirent *d; + while ((d = readdir(dp)) != nullptr) { + if(!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) { + continue; + } + zoneVersions.push_back(std::stoi(d->d_name)); + } + closedir(dp); + g_log< guard(g_soas_mutex); + for (auto iter = zoneVersions.cbegin(); iter != zoneVersions.cend() - keep; ++iter) { + string fname = dir + "/" + std::to_string(*iter); + g_log<& soa, uint32_t& soaTTL) { + for (const auto& dnsrecord : records) { + if (dnsrecord.d_type == QType::SOA) { + soa = getRR(dnsrecord); + if (soa == nullptr) { + throw PDNSException("Unable to determine SOARecordContent from old records"); + } + soaTTL = dnsrecord.d_ttl; + return; + } + } + throw PDNSException("No SOA in supplied records"); +} + +static void makeIXFRDiff(const records_t& from, const records_t& to, std::shared_ptr& diff, const shared_ptr& fromSOA = nullptr, uint32_t fromSOATTL=0, const shared_ptr& toSOA = nullptr, uint32_t toSOATTL = 0) { + set_difference(from.cbegin(), from.cend(), to.cbegin(), to.cend(), back_inserter(diff->removals), from.value_comp()); + set_difference(to.cbegin(), to.cend(), from.cbegin(), from.cend(), back_inserter(diff->additions), from.value_comp()); + diff->oldSOA = fromSOA; + diff->oldSOATTL = fromSOATTL; + if (fromSOA == nullptr) { + getSOAFromRecords(from, diff->oldSOA, diff->oldSOATTL); + } + diff->newSOA = toSOA; + diff->newSOATTL = toSOATTL; + if (toSOA == nullptr) { + getSOAFromRecords(to, diff->newSOA, diff->newSOATTL); + } +} + +/* you can _never_ alter the content of the resulting shared pointer */ +static std::shared_ptr getCurrentZoneInfo(const DNSName& domain) +{ + std::lock_guard guard(g_soas_mutex); + return g_soas[domain]; +} + +static void updateCurrentZoneInfo(const DNSName& domain, std::shared_ptr& newInfo) +{ + std::lock_guard guard(g_soas_mutex); + g_soas[domain] = newInfo; + g_stats.setSOASerial(domain, newInfo->soa->d_st.serial); + // FIXME: also report zone size? +} + +void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& axfrTimeout, const uint16_t& soaRetry, const uint32_t axfrMaxRecords) { + setThreadName("ixfrdist/update"); + std::map lastCheck; + + // Initialize the serials we have + for (const auto &domainConfig : g_domainConfigs) { + DNSName domain = domainConfig.first; + lastCheck[domain] = 0; + string dir = workdir + "/" + domain.toString(); + try { + g_log< soa; + uint32_t soaTTL; + { + string fname = workdir + "/" + domain.toString() + "/" + std::to_string(serial); + loadSOAFromDisk(domain, fname, soa, soaTTL); + records_t records; + if (soa != nullptr) { + loadZoneFromDisk(records, fname, domain); + } + auto zoneInfo = std::make_shared(); + zoneInfo->latestAXFR = std::move(records); + zoneInfo->soa = soa; + zoneInfo->soaTTL = soaTTL; + updateCurrentZoneInfo(domain, zoneInfo); + } + if (soa != nullptr) { + g_log<d_st.serial< current_soa; + const auto& zoneInfo = getCurrentZoneInfo(domain); + if (zoneInfo != nullptr) { + current_soa = zoneInfo->soa; + } + + auto& zoneLastCheck = lastCheck[domain]; + if ((current_soa != nullptr && now - zoneLastCheck < current_soa->d_st.refresh) || // Only check if we have waited `refresh` seconds + (current_soa == nullptr && now - zoneLastCheck < soaRetry)) { // Or if we could not get an update at all still, every 30 seconds + continue; + } + + // TODO Keep track of 'down' masters + set::const_iterator it(domainConfig.second.masters.begin()); + std::advance(it, dns_random(domainConfig.second.masters.size())); + ComboAddress master = *it; + + string dir = workdir + "/" + domain.toString(); + g_log< sr; + try { + zoneLastCheck = now; + g_stats.incrementSOAChecks(domain); + auto newSerial = getSerialFromMaster(master, domain, sr); // TODO TSIG + if(current_soa != nullptr) { + g_log<d_st.serial; + if (newSerial == current_soa->d_st.serial) { + g_log< soa; + uint32_t soaTTL = 0; + records_t records; + try { + AXFRRetriever axfr(master, domain, tt, &local); + uint32_t nrecords=0; + Resolver::res_t nop; + vector chunk; + time_t t_start = time(nullptr); + time_t axfr_now = time(nullptr); + while(axfr.getChunk(nop, &chunk, (axfr_now - t_start + axfrTimeout))) { + for(auto& dr : chunk) { + if(dr.d_type == QType::TSIG) + continue; + if(!dr.d_name.isPartOf(domain)) { + throw PDNSException("Out-of-zone data received during AXFR of "+domain.toLogString()); + } + dr.d_name.makeUsRelative(domain); + records.insert(dr); + nrecords++; + if (dr.d_type == QType::SOA) { + soa = getRR(dr); + soaTTL = dr.d_ttl; + } + } + if (axfrMaxRecords != 0 && nrecords > axfrMaxRecords) { + throw PDNSException("Received more than " + std::to_string(axfrMaxRecords) + " records in AXFR, aborted"); + } + axfr_now = time(nullptr); + if (axfr_now - t_start > axfrTimeout) { + g_stats.incrementAXFRFailures(domain); + throw PDNSException("Total AXFR time exceeded!"); + } + } + if (soa == nullptr) { + g_stats.incrementAXFRFailures(domain); + g_log<d_st.serial<<" to "<(); + + if (oldZoneInfo && !oldZoneInfo->latestAXFR.empty()) { + auto diff = std::make_shared(); + zoneInfo->ixfrDiffs = oldZoneInfo->ixfrDiffs; + g_log<latestAXFR, records, diff, oldZoneInfo->soa, oldZoneInfo->soaTTL, soa, soaTTL); + g_log<removals.size()<<" removals and "<additions.size()<<" additions"<ixfrDiffs.push_back(std::move(diff)); + } + + // Clean up the diffs + while (zoneInfo->ixfrDiffs.size() > keep) { + zoneInfo->ixfrDiffs.erase(zoneInfo->ixfrDiffs.begin()); + } + + g_log<latestAXFR.size() : 0)<<" entries, "<latestAXFR = std::move(records); + zoneInfo->soa = soa; + zoneInfo->soaTTL = soaTTL; + updateCurrentZoneInfo(domain, zoneInfo); + } catch (PDNSException &e) { + g_stats.incrementAXFRFailures(domain); + g_log< info_msg; + + g_log< that represents the full positive response to a SOA + * query. QNAME is read from mdp. + */ +static bool makeSOAPacket(const MOADNSParser& mdp, vector& packet) { + + auto zoneInfo = getCurrentZoneInfo(mdp.d_qname); + if (zoneInfo == nullptr) { + return false; + } + + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + + pw.startRecord(mdp.d_qname, QType::SOA, zoneInfo->soaTTL); + zoneInfo->soa->toPacket(pw); + pw.commit(); + + return true; +} + +/* + * Returns a vector that represents the full REFUSED response to a + * query. QNAME and type are read from mdp. + */ +static bool makeRefusedPacket(const MOADNSParser& mdp, vector& packet) { + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + pw.getHeader()->rcode = RCode::Refused; + + return true; +} + +static vector getSOAPacket(const MOADNSParser& mdp, const shared_ptr& soa, uint32_t soaTTL) { + vector packet; + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + + // Add the first SOA + pw.startRecord(mdp.d_qname, QType::SOA, soaTTL); + soa->toPacket(pw); + pw.commit(); + return packet; +} + +static bool sendPacketOverTCP(int fd, const std::vector& packet) +{ + char sendBuf[2]; + sendBuf[0]=packet.size()/256; + sendBuf[1]=packet.size()%256; + + writen2(fd, sendBuf, 2); + writen2(fd, &packet[0], packet.size()); + return true; +} + +static bool addRecordToWriter(DNSPacketWriter& pw, const DNSName& zoneName, const DNSRecord& record, bool compress) +{ + pw.startRecord(record.d_name + zoneName, record.d_type, record.d_ttl, QClass::IN, DNSResourceRecord::ANSWER, compress); + record.d_content->toPacket(pw); + if (pw.size() > 16384) { + pw.rollback(); + return false; + } + return true; +} + +template static bool sendRecordsOverTCP(int fd, const MOADNSParser& mdp, const T& records) +{ + vector packet; + + for (auto it = records.cbegin(); it != records.cend();) { + bool recordsAdded = false; + packet.clear(); + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + + while (it != records.cend()) { + if (it->d_type == QType::SOA) { + it++; + continue; + } + + if (addRecordToWriter(pw, mdp.d_qname, *it, g_compress)) { + recordsAdded = true; + it++; + } + else { + if (recordsAdded) { + pw.commit(); + sendPacketOverTCP(fd, packet); + } + if (it == records.cbegin()) { + /* something is wrong */ + return false; + } + + break; + } + } + + if (it == records.cend() && recordsAdded) { + pw.commit(); + sendPacketOverTCP(fd, packet); + } + } + + return true; +} + + +static bool handleAXFR(int fd, const MOADNSParser& mdp) { + /* we get a shared pointer of the zone info that we can't modify, ever. + A newer one may arise in the meantime, but this one will stay valid + until we release it. + */ + + g_stats.incrementAXFRinQueries(mdp.d_qname); + + auto zoneInfo = getCurrentZoneInfo(mdp.d_qname); + if (zoneInfo == nullptr) { + return false; + } + + shared_ptr soa = zoneInfo->soa; + uint32_t soaTTL = zoneInfo->soaTTL; + const records_t& records = zoneInfo->latestAXFR; + + // Initial SOA + const auto soaPacket = getSOAPacket(mdp, soa, soaTTL); + if (!sendPacketOverTCP(fd, soaPacket)) { + return false; + } + + if (!sendRecordsOverTCP(fd, mdp, records)) { + return false; + } + + // Final SOA + if (!sendPacketOverTCP(fd, soaPacket)) { + return false; + } + + return true; +} + +/* Produces an IXFR if one can be made according to the rules in RFC 1995 and + * creates a SOA or AXFR packet when required by the RFC. + */ +static bool handleIXFR(int fd, const ComboAddress& destination, const MOADNSParser& mdp, const shared_ptr& clientSOA) { + vector> toSend; + + /* we get a shared pointer of the zone info that we can't modify, ever. + A newer one may arise in the meantime, but this one will stay valid + until we release it. + */ + + g_stats.incrementIXFRinQueries(mdp.d_qname); + + auto zoneInfo = getCurrentZoneInfo(mdp.d_qname); + if (zoneInfo == nullptr) { + return false; + } + + uint32_t ourLatestSerial = zoneInfo->soa->d_st.serial; + + if (rfc1982LessThan(ourLatestSerial, clientSOA->d_st.serial) || ourLatestSerial == clientSOA->d_st.serial) { + /* RFC 1995 Section 2 + * If an IXFR query with the same or newer version number than that of + * the server is received, it is replied to with a single SOA record of + * the server's current version. + */ + vector packet; + bool ret = makeSOAPacket(mdp, packet); + if (ret) { + sendPacketOverTCP(fd, packet); + } + return ret; + } + + // as we use push_back in the updater, we know the vector is sorted as oldest first + bool shouldAdd = false; + // Get all relevant IXFR differences + for (const auto& diff : zoneInfo->ixfrDiffs) { + if (shouldAdd) { + toSend.push_back(diff); + continue; + } + if (diff->oldSOA->d_st.serial == clientSOA->d_st.serial) { + toSend.push_back(diff); + // Add all consecutive diffs + shouldAdd = true; + } + } + + if (toSend.empty()) { + // FIXME: incrementIXFRFallbacks + g_log<d_st.serial<<" for zone "<> packets; + for (const auto& diff : toSend) { + /* An IXFR packet's ANSWER section looks as follows: + * SOA new_serial + * SOA old_serial + * ... removed records ... + * SOA new_serial + * ... added records ... + * SOA new_serial + */ + + const auto newSOAPacket = getSOAPacket(mdp, diff->newSOA, diff->newSOATTL); + const auto oldSOAPacket = getSOAPacket(mdp, diff->oldSOA, diff->oldSOATTL); + + if (!sendPacketOverTCP(fd, newSOAPacket)) { + return false; + } + + if (!sendPacketOverTCP(fd, oldSOAPacket)) { + return false; + } + + if (!sendRecordsOverTCP(fd, mdp, diff->removals)) { + return false; + } + + if (!sendPacketOverTCP(fd, newSOAPacket)) { + return false; + } + + if (!sendRecordsOverTCP(fd, mdp, diff->additions)) { + return false; + } + + if (!sendPacketOverTCP(fd, newSOAPacket)) { + return false; + } + } + + return true; +} + +static bool allowedByACL(const ComboAddress& addr) { + return g_acl.match(addr); +} + +static void handleUDPRequest(int fd, boost::any&) { + // TODO make the buffer-size configurable + char buf[4096]; + ComboAddress saddr; + socklen_t fromlen = sizeof(saddr); + int res = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*) &saddr, &fromlen); + + if (res == 0) { + g_log< packet; + if (checkQuery(mdp, saddr)) { + /* RFC 1995 Section 2 + * Transport of a query may be by either UDP or TCP. If an IXFR query + * is via UDP, the IXFR server may attempt to reply using UDP if the + * entire response can be contained in a single DNS packet. If the UDP + * reply does not fit, the query is responded to with a single SOA + * record of the server's current version to inform the client that a + * TCP query should be initiated. + * + * Let's not complicate this with IXFR over UDP (and looking if we need to truncate etc). + * Just send the current SOA and let the client try over TCP + */ + g_stats.incrementSOAinQueries(mdp.d_qname); // FIXME: this also counts IXFR queries (but the response is the same as to a SOA query) + makeSOAPacket(mdp, packet); + } else { + makeRefusedPacket(mdp, packet); + } + + if(sendto(fd, &packet[0], packet.size(), 0, (struct sockaddr*) &saddr, fromlen) < 0) { + auto savedErrno = errno; + g_log< lg(g_tcpRequestFDsMutex); + g_tcpRequestFDs.push({cfd, saddr}); + } + g_tcpHandlerCV.notify_one(); +} + +/* Thread to handle TCP traffic + */ +static void tcpWorker(int tid) { + setThreadName("ixfrdist/tcpWor"); + string prefix = "TCP Worker " + std::to_string(tid) + ": "; + + while(true) { + g_log< lk(g_tcpRequestFDsMutex); + g_tcpHandlerCV.wait(lk, []{return g_tcpRequestFDs.size() || g_exiting ;}); + if (g_exiting) { + g_log<(sizeof(buf))); + res = readn2WithTimeout(cfd, &buf, toRead, 2); + g_log< packet; + bool ret = makeSOAPacket(mdp, packet); + if (!ret) { + close(cfd); + continue; + } + sendPacketOverTCP(cfd, packet); + } + else if (mdp.d_qtype == QType::AXFR) { + if (!handleAXFR(cfd, mdp)) { + close(cfd); + continue; + } + } + else if (mdp.d_qtype == QType::IXFR) { + /* RFC 1995 section 3: + * The IXFR query packet format is the same as that of a normal DNS + * query, but with the query type being IXFR and the authority section + * containing the SOA record of client's version of the zone. + */ + shared_ptr clientSOA; + for (auto &answer : mdp.d_answers) { + // from dnsparser.hh: + // typedef vector > answers_t; + if (answer.first.d_type == QType::SOA && answer.first.d_place == DNSResourceRecord::AUTHORITY) { + clientSOA = getRR(answer.first); + if (clientSOA != nullptr) { + break; + } + } + } /* for (auto const &answer : mdp.d_answers) */ + + if (clientSOA == nullptr) { + g_log<(); + } catch (const runtime_error &e) { + g_log<(); + } catch (const runtime_error &e) { + g_log<(); + } catch (const runtime_error &e) { + g_log<(); + } catch (const runtime_error &e) { + g_log<(); + } catch (const runtime_error &e) { + g_log<>(); + } catch (const runtime_error &e) { + g_log<>(); + } catch (const runtime_error &e) { + g_log<(); + } catch(const runtime_error &e) { + g_log<(); + } catch(const runtime_error &e) { + g_log<(); + } catch(const runtime_error &e) { + g_log<(); + } catch (const runtime_error &e) { + g_log<()<<"': "<()<<"' has no master configured!"<(); + } catch (const runtime_error &e) { + g_log<()<<"' master address: "<(); + } + catch (const runtime_error &e) { + g_log<(); + } + catch (const runtime_error &e) { + g_log<>(); + } + catch (const runtime_error &e) { + g_log<(); + } + catch (const runtime_error &e) { + g_log<()->default_value(SYSCONFDIR + string("/ixfrdist.yml")), "Configuration file to use") + ; + + po::store(po::command_line_parser(argc, argv).options(desc).run(), g_vm); + po::notify(g_vm); + + if (g_vm.count("help") > 0) { + usage(desc); + return EXIT_SUCCESS; + } + + if (g_vm.count("version") > 0) { + cout<<"ixfrdist "< 0) { + g_log.setLoglevel(Logger::Debug); + g_log.toConsole(Logger::Debug); + } + + g_log<(), config)) { + // parseAndCheckConfig already logged whatever was wrong + return EXIT_FAILURE; + } + + /* From hereon out, we known that all the values in config are valid. */ + + for (auto const &domain : config["domains"]) { + set s; + s.insert(domain["master"].as()); + g_domainConfigs[domain["domain"].as()].masters = s; + g_stats.registerDomain(domain["domain"].as()); + } + + for (const auto &addr : config["acl"].as>()) { + try { + g_acl.addMask(addr); + } catch (const NetmaskException &e) { + g_log<(); + if (g_compress) { + g_log< allSockets; + for (const auto& addr : config["listen"].as>()) { + for (const auto& stype : {SOCK_DGRAM, SOCK_STREAM}) { + try { + int s = SSocket(addr.sin4.sin_family, stype, 0); + setNonBlocking(s); + setReuseAddr(s); + SBind(s, addr); + if (stype == SOCK_STREAM) { + SListen(s, 30); // TODO make this configurable + } + fdm->addReadFD(s, stype == SOCK_DGRAM ? handleUDPRequest : handleTCPRequest); + allSockets.insert(s); + } catch(runtime_error &e) { + g_log<(); + if (!(newgid = atoi(gid.c_str()))) { + struct group *gr = getgrnam(gid.c_str()); + if (gr == nullptr) { + g_log<gr_gid; + } + } + g_log<>()) { + wsACL.addMask(acl); + } + } + + string loglevel = "normal"; + if (config["webserver-loglevel"]) { + loglevel = config["webserver-loglevel"].as(); + } + + // Launch the webserver! + try { + std::thread(&IXFRDistWebServer::go, IXFRDistWebServer(config["webserver-address"].as(), wsACL, loglevel)).detach(); + } catch (const PDNSException &e) { + g_log<(); + if (!(newuid = atoi(uid.c_str()))) { + struct passwd *pw = getpwnam(uid.c_str()); + if (pw == nullptr) { + g_log<pw_uid; + } + } + + struct passwd *pw = getpwuid(newuid); + if (pw == nullptr) { + if (setgroups(0, nullptr) < 0) { + g_log<pw_name, newgid) < 0) { + g_log<(), + config["keep"].as(), + config["axfr-timeout"].as(), + config["failed-soa-retry"].as(), + config["axfr-max-records"].as()); + + vector tcpHandlers; + tcpHandlers.reserve(config["tcp-in-threads"].as()); + for (size_t i = 0; i < tcpHandlers.capacity(); ++i) { + tcpHandlers.push_back(std::thread(tcpWorker, i)); + } + + struct timeval now; + for(;;) { + gettimeofday(&now, 0); + fdm->run(&now); + if (g_exiting) { + g_log< +#include +#include +#include "ixfrutils.hh" +#include "sstuff.hh" +#include "dnssecinfra.hh" +#include "zoneparser-tng.hh" +#include "dnsparser.hh" + +uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr& sr, const TSIGTriplet& tt, const uint16_t timeout) +{ + vector packet; + DNSPacketWriter pw(packet, zone, QType::SOA); + if(!tt.algo.empty()) { + TSIGRecordContent trc; + trc.d_algoName = tt.algo; + trc.d_time = time(nullptr); + trc.d_fudge = 300; + trc.d_origID=ntohs(pw.getHeader()->id); + trc.d_eRcode=0; + addTSIG(pw, trc, tt.name, tt.secret, "", false); + } + + Socket s(master.sin4.sin_family, SOCK_DGRAM); + s.connect(master); + string msg((const char*)&packet[0], packet.size()); + s.writen(msg); + + string reply; + reply.resize(4096); + // will throw a NetworkError on timeout + ssize_t got = s.readWithTimeout(&reply[0], reply.size(), timeout); + if (got < 0 || static_cast(got) < sizeof(dnsheader)) { + throw std::runtime_error("Invalid response size " + std::to_string(got)); + } + + reply.resize(got); + + MOADNSParser mdp(false, reply); + if(mdp.d_header.rcode) { + throw std::runtime_error("RCODE from response is not NoError but " + RCode::to_s(mdp.d_header.rcode)); + } + for(const auto& r: mdp.d_answers) { + if(r.first.d_type == QType::SOA) { + sr = getRR(r.first); + if(sr != nullptr) { + return sr->d_st.serial; + } + } + } + return 0; +} + +uint32_t getSerialsFromDir(const std::string& dir) +{ + uint32_t ret=0; + DIR* dirhdl=opendir(dir.c_str()); + if(!dirhdl) + throw runtime_error("Could not open IXFR directory '" + dir + "': " + strerror(errno)); + struct dirent *entry; + + while((entry = readdir(dirhdl))) { + uint32_t num = atoi(entry->d_name); + if(std::to_string(num) == entry->d_name) + ret = max(num, ret); + } + closedir(dirhdl); + return ret; +} + +uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret) +{ + DNSName root("."); + uint16_t t=QType::SOA; + + auto found = records.equal_range(tie(root, t)); + + for(auto iter = found.first; iter != found.second; ++iter) { + auto soa = std::dynamic_pointer_cast(iter->d_content); + if (soa) { + soaret = *iter; + return soa->d_st.serial; + } + } + return 0; +} + +static void writeRecords(FILE* fp, const records_t& records) +{ + for(const auto& r: records) { + fprintf(fp, "%s\t%" PRIu32 "\tIN\t%s\t%s\n", + r.d_name.isRoot() ? "@" : r.d_name.toStringNoDot().c_str(), + r.d_ttl, + DNSRecordContent::NumberToType(r.d_type).c_str(), + r.d_content->getZoneRepresentation().c_str()); + } +} + +void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory) +{ + DNSRecord soa; + auto serial = getSerialFromRecords(records, soa); + string fname=directory +"/"+std::to_string(serial); + FILE* fp=fopen((fname+".partial").c_str(), "w"); + if(!fp) + throw runtime_error("Unable to open file '"+fname+".partial' for writing: "+string(strerror(errno))); + + records_t soarecord; + soarecord.insert(soa); + fprintf(fp, "$ORIGIN %s\n", zone.toString().c_str()); + + writeRecords(fp, soarecord); + writeRecords(fp, records); + writeRecords(fp, soarecord); + + fclose(fp); + if (rename( (fname+".partial").c_str(), fname.c_str()) != 0) { + throw std::runtime_error("Unable to move the zone file for " + zone.toLogString() + " from " + fname + ".partial to " + fname + ": " + string(strerror(errno))); + } +} + +void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zone) +{ + ZoneParserTNG zpt(fname, zone); + + DNSResourceRecord rr; + bool seenSOA=false; + while(zpt.get(rr)) { + if(rr.qtype.getCode() == QType::CNAME && rr.content.empty()) + rr.content="."; + rr.qname = rr.qname.makeRelative(zone); + + if(rr.qtype.getCode() != QType::SOA || seenSOA==false) + records.insert(DNSRecord(rr)); + if(rr.qtype.getCode() == QType::SOA) { + seenSOA=true; + } + } + if(!(rr.qtype.getCode() == QType::SOA && seenSOA)) { + records.clear(); + throw runtime_error("Zone not complete!"); + } +} + +/* + * Load the zone `zone` from `fname` and put the first found SOA into `soa` + * Does NOT check for nullptr + */ +void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr& soa, uint32_t& soaTTL) +{ + ZoneParserTNG zpt(fname, zone); + DNSResourceRecord rr; + + while(zpt.get(rr)) { + if (rr.qtype == QType::SOA) { + soa = getRR(DNSRecord(rr)); + soaTTL = rr.ttl; + return; + } + } +} diff --git a/pdns/ixfrutils.hh b/pdns/ixfrutils.hh new file mode 100644 index 0000000..ea66bfa --- /dev/null +++ b/pdns/ixfrutils.hh @@ -0,0 +1,57 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#include +#include "dnsparser.hh" +#include "dnsrecords.hh" + +using namespace boost::multi_index; + +struct CIContentCompareStruct +{ + bool operator()(const shared_ptr&a, const shared_ptr& b) const + { + return toLower(a->getZoneRepresentation()) < toLower(b->getZoneRepresentation()); + } +}; + + +typedef multi_index_container < + DNSRecord, + indexed_by< + ordered_non_unique< + composite_key, + member, + member, + member, &DNSRecord::d_content> >, + composite_key_compare, std::less, CIContentCompareStruct > + > /* ordered_non_uniquw */ + > /* indexed_by */ +> /* multi_index_container */ records_t; + +uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr& sr, const TSIGTriplet& tt = TSIGTriplet(), const uint16_t timeout = 2); +uint32_t getSerialsFromDir(const std::string& dir); +uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret); +void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory); +void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zone); +void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr& soa, uint32_t& soaTTL); diff --git a/pdns/ixplore.cc b/pdns/ixplore.cc new file mode 100644 index 0000000..b59a842 --- /dev/null +++ b/pdns/ixplore.cc @@ -0,0 +1,252 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "arguments.hh" +#include "base64.hh" + +#include "misc.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "base32.hh" +#include "dnssecinfra.hh" + +#include "dns_random.hh" +#include "gss_context.hh" +#include +#include "resolver.hh" +#include +#include "ixfr.hh" +#include "ixfrutils.hh" +StatBag S; + +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} + +void usage() { + cerr<<"Syntax: ixplore diff ZONE BEFORE_FILE AFTER_FILE"< diff; + + set_difference(before.cbegin(), before.cend(), after.cbegin(), after.cend(), back_inserter(diff), before.value_comp()); + for(const auto& d : diff) { + cout<<'-'<< (d.d_name+zone) <<" IN "<getZoneRepresentation()<getZoneRepresentation()< 6) + tt.name=DNSName(toLower(argv[6])); + if(argc > 7) + tt.algo=DNSName(toLower(argv[7])); + + if(argc > 8) { + if(B64Decode(argv[8], tt.secret) < 0) { + cerr<<"Could not decode tsig secret!"< chunk; + char wheel[]="|/-\\"; + int count=0; + time_t last=0; + while(axfr.getChunk(nop, &chunk)) { + for(auto& dr : chunk) { + if(dr.d_type == QType::TSIG) + continue; + dr.d_name.makeUsRelative(zone); + records.insert(dr); + nrecords++; + } + + if(last != time(0)) { + cout << '\r' << wheel[count % (sizeof(wheel)-1)] << ' ' < sr; + uint32_t serial = getSerialFromMaster(master, zone, sr, tt); + if(ourSerial == serial) { + cout<<"still up to date, their serial is "<d_st.refresh<<" seconds"<d_st.refresh); + continue; + } + + cout<<"got new serial: "<(rr.d_content)->d_st.serial; + } + } + + cout<<"This delta ("<getZoneRepresentation()<getZoneRepresentation()< +#include +#include "json11.hpp" + +int intFromJson(const json11::Json container, const std::string& key); +int intFromJson(const json11::Json container, const std::string& key, const int default_value); +double doubleFromJson(const json11::Json container, const std::string& key); +double doubleFromJson(const json11::Json container, const std::string& key, const double default_value); +std::string stringFromJson(const json11::Json container, const std::string &key); +bool boolFromJson(const json11::Json container, const std::string& key); +bool boolFromJson(const json11::Json container, const std::string& key, const bool default_value); + +class JsonException : public std::runtime_error +{ +public: + JsonException(const std::string& what) : std::runtime_error(what) { + } +}; diff --git a/pdns/kqueuemplexer.cc b/pdns/kqueuemplexer.cc new file mode 100644 index 0000000..0c193d1 --- /dev/null +++ b/pdns/kqueuemplexer.cc @@ -0,0 +1,193 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "mplexer.hh" +#include "sstuff.hh" +#include +#include +#include "misc.hh" +#include +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#include +#endif +#include + +#include "namespaces.hh" + +class KqueueFDMultiplexer : public FDMultiplexer +{ +public: + KqueueFDMultiplexer(); + virtual ~KqueueFDMultiplexer() + { + close(d_kqueuefd); + } + + virtual int run(struct timeval* tv, int timeout=500) override; + virtual void getAvailableFDs(std::vector& fds, int timeout) override; + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd=nullptr) override; + virtual void removeFD(callbackmap_t& cbmap, int fd) override; + string getName() const override + { + return "kqueue"; + } +private: + int d_kqueuefd; + boost::shared_array d_kevents; + static unsigned int s_maxevents; // not a hard maximum +}; + +unsigned int KqueueFDMultiplexer::s_maxevents=1024; + +static FDMultiplexer* make() +{ + return new KqueueFDMultiplexer(); +} + +static struct KqueueRegisterOurselves +{ + KqueueRegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &make)); // priority 0! + } +} kQueuedoIt; + +KqueueFDMultiplexer::KqueueFDMultiplexer() : d_kevents(new struct kevent[s_maxevents]) +{ + d_kqueuefd=kqueue(); + if(d_kqueuefd < 0) + throw FDMultiplexerException("Setting up kqueue: "+stringerror()); +} + +void KqueueFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd) +{ + accountingAddFD(cbmap, fd, toDo, parameter, ttd); + + struct kevent kqevent; + EV_SET(&kqevent, fd, (&cbmap == &d_readCallbacks) ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0,0,0); + + if(kevent(d_kqueuefd, &kqevent, 1, 0, 0, 0) < 0) { + cbmap.erase(fd); + throw FDMultiplexerException("Adding fd to kqueue set: "+stringerror()); + } +} + +void KqueueFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + accountingRemoveFD(cbmap, fd); + + struct kevent kqevent; + EV_SET(&kqevent, fd, (&cbmap == &d_readCallbacks) ? EVFILT_READ : EVFILT_WRITE, EV_DELETE, 0,0,0); + + if(kevent(d_kqueuefd, &kqevent, 1, 0, 0, 0) < 0) // ponder putting Callback back on the map.. + throw FDMultiplexerException("Removing fd from kqueue set: "+stringerror()); +} + +void KqueueFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) +{ + struct timespec ts; + ts.tv_sec=timeout/1000; + ts.tv_nsec=(timeout % 1000) * 1000000; + + int ret = kevent(d_kqueuefd, 0, 0, d_kevents.get(), s_maxevents, &ts); + + if(ret < 0 && errno != EINTR) + throw FDMultiplexerException("kqueue returned error: "+stringerror()); + + for(int n=0; n < ret; ++n) { + fds.push_back(d_kevents[n].ident); + } +} + +int KqueueFDMultiplexer::run(struct timeval* now, int timeout) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + + struct timespec ts; + ts.tv_sec=timeout/1000; + ts.tv_nsec=(timeout % 1000) * 1000000; + + int ret=kevent(d_kqueuefd, 0, 0, d_kevents.get(), s_maxevents, &ts); + gettimeofday(now,0); // MANDATORY! + + if(ret < 0 && errno!=EINTR) + throw FDMultiplexerException("kqueue returned error: "+stringerror()); + + if(ret < 0) // nothing - thanks AB! + return 0; + + d_inrun=true; + + for(int n=0; n < ret; ++n) { + d_iter=d_readCallbacks.find(d_kevents[n].ident); + if(d_iter != d_readCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + continue; // so we don't find ourselves as writable again + } + + d_iter=d_writeCallbacks.find(d_kevents[n].ident); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + } + } + + d_inrun=false; + return ret; +} + +#if 0 +void acceptData(int fd, boost::any& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "< parts; + stringtok(parts, query); + if(parts.size()<2) + continue; + string response; + if(parts[0]=="DOMAIN") + response= (parts[1].find("xxx") != string::npos) ? "1" : "0"; + else if(parts[0]=="IP") + response= (parts[1]=="127.0.0.1") ? "1" : "0"; + else + response= "???"; + + cout<<"Our reply: "< +#include +#include "misc.hh" +#include "pdnsexception.hh" + +extern bool g_singleThreaded; + +class Lock +{ + pthread_mutex_t *d_lock; +public: + Lock(const Lock& rhs) = delete; + Lock& operator=(const Lock& rhs) = delete; + + Lock(pthread_mutex_t *lock) : d_lock(lock) + { + if(g_singleThreaded) + return; + + int err; + if((err = pthread_mutex_lock(d_lock))) { + errno = err; + throw PDNSException("error acquiring lock: "+stringerror()); + } + } + ~Lock() + { + if(g_singleThreaded) + return; + + pthread_mutex_unlock(d_lock); + } +}; + +class WriteLock +{ + pthread_rwlock_t *d_lock; +public: + + WriteLock(pthread_rwlock_t *lock) : d_lock(lock) + { + if(g_singleThreaded) + return; + + int err; + if((err = pthread_rwlock_wrlock(d_lock))) { + errno = err; + throw PDNSException("error acquiring rwlock wrlock: "+stringerror()); + } + } + ~WriteLock() + { + if(g_singleThreaded) + return; + if(d_lock) // might have been moved + pthread_rwlock_unlock(d_lock); + } + + WriteLock(WriteLock&& rhs) + { + d_lock = rhs.d_lock; + rhs.d_lock=0; + } + WriteLock(const WriteLock& rhs) = delete; + WriteLock& operator=(const WriteLock& rhs) = delete; + + +}; + +class TryWriteLock +{ + pthread_rwlock_t *d_lock; + bool d_havelock; +public: + TryWriteLock(const TryWriteLock& rhs) = delete; + TryWriteLock& operator=(const TryWriteLock& rhs) = delete; + + TryWriteLock(pthread_rwlock_t *lock) : d_lock(lock) + { + if(g_singleThreaded) { + d_havelock=true; + return; + } + + d_havelock=false; + int err; + if((err = pthread_rwlock_trywrlock(d_lock)) && err!=EBUSY) { + errno = err; + throw PDNSException("error acquiring rwlock tryrwlock: "+stringerror()); + } + d_havelock=(err==0); + } + + TryWriteLock(TryWriteLock&& rhs) + { + d_lock = rhs.d_lock; + rhs.d_lock = nullptr; + d_havelock = rhs.d_havelock; + rhs.d_havelock = false; + } + + + ~TryWriteLock() + { + if(g_singleThreaded) + return; + + if(d_havelock && d_lock) // we might be moved + pthread_rwlock_unlock(d_lock); + } + bool gotIt() + { + if(g_singleThreaded) + return true; + + return d_havelock; + } +}; + +class TryReadLock +{ + pthread_rwlock_t *d_lock; + bool d_havelock; +public: + TryReadLock(const TryReadLock& rhs) = delete; + TryReadLock& operator=(const TryReadLock& rhs) = delete; + + TryReadLock(pthread_rwlock_t *lock) : d_lock(lock) + { + if(g_singleThreaded) { + d_havelock=true; + return; + } + + int err; + if((err = pthread_rwlock_tryrdlock(d_lock)) && err!=EBUSY) { + errno = err; + throw PDNSException("error acquiring rwlock tryrdlock: "+stringerror()); + } + d_havelock=(err==0); + } + TryReadLock(TryReadLock&& rhs) + { + d_lock = rhs.d_lock; + rhs.d_lock = nullptr; + d_havelock = rhs.d_havelock; + rhs.d_havelock = false; + } + + ~TryReadLock() + { + if(g_singleThreaded) + return; + + if(d_havelock && d_lock) + pthread_rwlock_unlock(d_lock); + } + bool gotIt() + { + if(g_singleThreaded) + return true; + + return d_havelock; + } +}; + + +class ReadLock +{ + pthread_rwlock_t *d_lock; +public: + + ReadLock(pthread_rwlock_t *lock) : d_lock(lock) + { + if(g_singleThreaded) + return; + + int err; + if((err = pthread_rwlock_rdlock(d_lock))) { + errno = err; + throw PDNSException("error acquiring rwlock readlock: "+stringerror()); + } + } + ~ReadLock() + { + if(g_singleThreaded) + return; + if(d_lock) // may have been moved + pthread_rwlock_unlock(d_lock); + } + + ReadLock(ReadLock&& rhs) + { + d_lock = rhs.d_lock; + rhs.d_lock=0; + } + ReadLock(const ReadLock& rhs) = delete; + ReadLock& operator=(const ReadLock& rhs) = delete; +}; +#endif diff --git a/pdns/logger.cc b/pdns/logger.cc new file mode 100644 index 0000000..dd89047 --- /dev/null +++ b/pdns/logger.cc @@ -0,0 +1,198 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "logger.hh" +#include "misc.hh" +#ifndef RECURSOR +#include "statbag.hh" +extern StatBag S; +#endif +#include "lock.hh" +#include "namespaces.hh" + +thread_local Logger::PerThread Logger::t_perThread; + +Logger& getLogger() +{ + /* Since the Logger can be called very early, we need to make sure + that the relevant parts are initialized no matter what, which is tricky + because we can't easily control the initialization order, especially with + built-in backends. + t_perThread is thread_local, so it will be initialized when first accessed, + but we need to make sure that the object itself is initialized, and making + it a function-level static variable achieves that, because it will be + initialized the first time we enter this function at the very last. + */ + static Logger log("", LOG_DAEMON); + return log; +} + +void Logger::log(const string &msg, Urgency u) +{ +#ifndef RECURSOR + bool mustAccount(false); +#endif + if(u<=consoleUrgency) { + char buffer[50] = ""; + if (d_timestamps) { + struct tm tm; + time_t t; + time(&t); + tm=*localtime(&t); + strftime(buffer,sizeof(buffer),"%b %d %H:%M:%S ", &tm); + } + + string prefix; + if (d_prefixed) { + switch(u) { + case All: + prefix = "[all] "; + break; + case Alert: + prefix = "[ALERT] "; + break; + case Critical: + prefix = "[CRITICAL] "; + break; + case Error: + prefix = "[ERROR] "; + break; + case Warning: + prefix = "[WARNING] "; + break; + case Notice: + prefix = "[NOTICE] "; + break; + case Info: + prefix = "[INFO] "; + break; + case Debug: + prefix = "[DEBUG] "; + break; + case None: + prefix = "[none] "; + break; + } + } + + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + Lock l(&m); // the C++-2011 spec says we need this, and OSX actually does + clog << string(buffer) + prefix + msg < +#include +#include +#include +#include + +#include "namespaces.hh" +#include "dnsname.hh" +#include "iputils.hh" + +//! The Logger class can be used to log messages in various ways. +class Logger +{ +public: + Logger(const string &, int facility=LOG_DAEMON); //!< pass the identification you wish to appear in the log + + //! The urgency of a log message + enum Urgency {All=32767,Alert=LOG_ALERT, Critical=LOG_CRIT, Error=LOG_ERR, Warning=LOG_WARNING, + Notice=LOG_NOTICE,Info=LOG_INFO, Debug=LOG_DEBUG, None=-1}; + + /** Log a message. + \param msg Message you wish to log + \param u Urgency of the message you wish to log + */ + void log(const string &msg, Urgency u=Notice); + + void setFacility(int f){d_facility=f;open();} //!< Choose logging facility + void setFlag(int f){flags|=f;open();} //!< set a syslog flag + void setName(const string &); + + //! set lower limit of urgency needed for console display. Messages of this urgency, and higher, will be displayed + void toConsole(Urgency); + void setLoglevel( Urgency ); + + void disableSyslog(bool d) { + d_disableSyslog = d; + } + + void setTimestamps(bool t) { + d_timestamps = t; + } + + void setPrefixed(bool p) { + d_prefixed = p; + } + + //! Log to a file. + void toFile( const string & filename ); + + void resetFlags(){flags=0;open();} //!< zero the flags + /** Use this to stream to your log, like this: + \code + g_log<<"This is an informational message"< Logger & operator<<(const T & i) { + ostringstream tmp; + tmp< +#include "logger.hh" +#include "dnsparser.hh" +#include "namespaces.hh" +#include "ednssubnet.hh" +#include +#include "sstuff.hh" +#include +#include + +#include "ueberbackend.hh" + +AuthLua4::AuthLua4() { prepareContext(); } + +#if !defined(HAVE_LUA) + +bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) { return false; } +bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector& out) { return false; } +LuaContext* AuthLua4::getLua() { return 0; } +DNSPacket *AuthLua4::prequery(DNSPacket *q) { return NULL; } + +AuthLua4::~AuthLua4() { } + +void AuthLua4::postPrepareContext() +{ +} + +void AuthLua4::postLoad() +{ +} + +#else + +LuaContext* AuthLua4::getLua() +{ + return d_lw.get(); +} + +void AuthLua4::postPrepareContext() { + d_lw->writeFunction("resolve", [](const std::string& qname, uint16_t qtype) { + std::vector ret; + std::unordered_map luaResult; + stubDoResolve(DNSName(qname), qtype, ret); + int i = 0; + for(const auto &row: ret) { + luaResult[++i] = DNSResourceRecord::fromWire(row.dr); + luaResult[i].auth = row.auth; + } + return luaResult; + }); + +/* DNSPacket */ + d_lw->writeFunction("newDNSPacket", [](bool isQuery) { return new DNSPacket(isQuery); }); + d_lw->writeFunction("dupDNSPacket", [](const DNSPacket &orig) { return new DNSPacket(orig); }); + d_lw->registerFunction("noparse", [](DNSPacket &p, const char *mesg, size_t len){ return p.noparse(mesg, len); }); + d_lw->registerFunction("parse", [](DNSPacket &p, const char *mesg, size_t len){ return p.parse(mesg, len); }); + d_lw->registerFunction("getString", [](DNSPacket &p) { return p.getString(); }); + d_lw->registerFunction("setRemote", [](DNSPacket &p, const ComboAddress &ca) { p.setRemote(&ca); }); + d_lw->registerFunction("getRemote", [](DNSPacket &p) { return p.getRemote(); }); + d_lw->registerFunction("getRealRemote", [](DNSPacket &p) { return p.getRealRemote(); }); + d_lw->registerFunction("getLocal", [](DNSPacket &p) { return p.getLocal(); }); + d_lw->registerFunction("getRemotePort", [](DNSPacket &p) { return p.getRemotePort(); }); + d_lw->registerFunction()>("getQuestion", [](DNSPacket &p) { return std::make_tuple(p.qdomain.toString(), static_cast(p.qtype.getCode())); }); + d_lw->registerFunction("setA", [](DNSPacket &p, bool a) { return p.setA(a); }); + d_lw->registerFunction("setID", [](DNSPacket &p, unsigned int id) { return p.setID(static_cast(id)); }); + d_lw->registerFunction("setRA", [](DNSPacket &p, bool ra) { return p.setRA(ra); }); + d_lw->registerFunction("setRD", [](DNSPacket &p, bool rd) { return p.setRD(rd); }); + d_lw->registerFunction("setAnswer", [](DNSPacket &p, bool answer) { return p.setAnswer(answer); }); + d_lw->registerFunction("setOpCode", [](DNSPacket &p, unsigned int opcode) { return p.setOpcode(static_cast(opcode)); }); + d_lw->registerFunction("setRcode", [](DNSPacket &p, int rcode) { return p.setRcode(rcode); }); + d_lw->registerFunction("clearRecords",[](DNSPacket &p){p.clearRecords();}); + d_lw->registerFunction("addRecord", [](DNSPacket &p, DNSRecord &dr, bool auth) { DNSZoneRecord dzr; dzr.dr = dr; dzr.auth = auth; p.addRecord(dzr); }); + d_lw->registerFunction >&)>("addRecords", [](DNSPacket &p, const vector >& records){ for(const auto &dr: records){ DNSZoneRecord dzr; dzr.dr = std::get<1>(dr); dzr.auth = true; p.addRecord(dzr); }}); + d_lw->registerFunction("setQuestion", [](DNSPacket &p, unsigned int opcode, const DNSName &name, const string &type){ QType qtype; qtype = type; p.setQuestion(static_cast(opcode), name, static_cast(qtype.getCode())); }); + d_lw->registerFunction("isEmpty", [](DNSPacket &p){return p.isEmpty();}); + d_lw->registerFunction("replyPacket",[](DNSPacket& p){ return p.replyPacket();}); + d_lw->registerFunction("hasEDNSSubnet", [](DNSPacket &p){return p.hasEDNSSubnet();}); + d_lw->registerFunction("hasEDNS",[](DNSPacket &p){return p.hasEDNS();}); + d_lw->registerFunction("getEDNSVersion",[](DNSPacket &p){return p.getEDNSVersion();}); + d_lw->registerFunction("setEDNSRcode",[](DNSPacket &p, unsigned int extRCode){p.setEDNSRcode(static_cast(extRCode));}); + d_lw->registerFunction("getEDNSRcode",[](DNSPacket &p){return p.getEDNSRCode();}); + d_lw->registerFunction("getTSIGKeyname",[](DNSPacket &p){ return p.getTSIGKeyname();}); + d_lw->registerFunction()>("getRRS", [](DNSPacket &p){ std::unordered_map ret; unsigned int i = 0; for(const auto &rec: p.getRRS()) { ret.insert({i++, rec.dr}); } return ret;}); + d_lw->registerMember("qdomain", [](const DNSPacket &p) -> DNSName { return p.qdomain; }, [](DNSPacket &p, const DNSName& name) { p.qdomain = name; }); + d_lw->registerMember("qdomainwild", [](const DNSPacket &p) -> DNSName { return p.qdomainwild; }, [](DNSPacket &p, const DNSName& name) { p.qdomainwild = name; }); + d_lw->registerMember("qdomainzone", [](const DNSPacket &p) -> DNSName { return p.qdomainzone; }, [](DNSPacket &p, const DNSName& name) { p.qdomainzone = name; }); + + d_lw->registerMember("d_peer_principal", [](const DNSPacket &p) -> std::string { return p.d_peer_principal; }, [](DNSPacket &p, const std::string &princ) { p.d_peer_principal = princ; }); + d_lw->registerMember("qtype", [](const DNSPacket &p) -> const std::string { return p.qtype.getName(); }, [](DNSPacket &p, const std::string &type) { p.qtype = type; }); +/* End of DNSPacket */ + + +/* update policy */ + d_lw->registerFunction("getQName", [](UpdatePolicyQuery& upq) { return upq.qname; }); + d_lw->registerFunction("getZoneName", [](UpdatePolicyQuery& upq) { return upq.zonename; }); + d_lw->registerFunction("getQType", [](UpdatePolicyQuery& upq) { return upq.qtype; }); + d_lw->registerFunction("getLocal", [](UpdatePolicyQuery& upq) { return upq.local; }); + d_lw->registerFunction("getRemote", [](UpdatePolicyQuery& upq) { return upq.remote; }); + d_lw->registerFunction("getRealRemote", [](UpdatePolicyQuery& upq) { return upq.realRemote; }); + d_lw->registerFunction("getTsigName", [](UpdatePolicyQuery& upq) { return upq.tsigName; }); + d_lw->registerFunction("getPeerPrincipal", [](UpdatePolicyQuery& upq) { return upq.peerPrincipal; }); +/* end of update policy */ +} + +void AuthLua4::postLoad() { + d_update_policy = d_lw->readVariable>("updatepolicy").get_value_or(0); + d_axfr_filter = d_lw->readVariable>("axfrfilter").get_value_or(0); + d_prequery = d_lw->readVariable>("prequery").get_value_or(0); +} + +bool AuthLua4::axfrfilter(const ComboAddress& remote, const DNSName& zone, const DNSResourceRecord& in, vector& out) { + luacall_axfr_filter_t::result_type ret; + int rcode; + + if (d_axfr_filter == NULL) return false; + + ret = d_axfr_filter(remote, zone, in); + rcode = std::get<0>(ret); + if (rcode < 0) { + // no modification, handle normally + return false; + } + else if (rcode == 0) { + // replace the matching record by the filtered record(s) + } + else if (rcode == 1) { + // append the filtered record(s) after the matching record + out.push_back(in); + } + else + throw PDNSException("Cannot understand return code "+std::to_string(rcode)+" in axfr filter response"); + + const auto& rows = std::get<1>(ret); + + for(const auto& row: rows) { + DNSResourceRecord rec; + for(const auto& col: row.second) { + if (col.first == "qtype") + rec.qtype = QType(boost::get(col.second)); + else if (col.first == "qname") + rec.qname = DNSName(boost::get(col.second)).makeLowerCase(); + else if (col.first == "ttl") + rec.ttl = boost::get(col.second); + else if (col.first == "content") + rec.setContent(boost::get(col.second)); + else + throw PDNSException("Cannot understand "+col.first+" in axfr filter response on row "+std::to_string(row.first)); + } + out.push_back(rec); + } + + return true; +} + + +bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet) { + // default decision is all goes + if (d_update_policy == NULL) return true; + + UpdatePolicyQuery upq; + upq.qname = qname; + upq.qtype = qtype.getCode(); + upq.zonename = zonename; + upq.local = packet->getLocal(); + upq.remote = packet->getRemote(); + upq.realRemote = packet->getRealRemote(); + upq.tsigName = packet->getTSIGKeyname(); + upq.peerPrincipal = packet->d_peer_principal; + + return d_update_policy(upq); +} + +DNSPacket *AuthLua4::prequery(DNSPacket *q) { + if (d_prequery == NULL) return NULL; + + DNSPacket *r = q->replyPacket(); + if (d_prequery(r)) + return r; + delete r; + return NULL; +} + +AuthLua4::~AuthLua4() { } + + +#endif diff --git a/pdns/lua-auth4.hh b/pdns/lua-auth4.hh new file mode 100644 index 0000000..4e7d7c0 --- /dev/null +++ b/pdns/lua-auth4.hh @@ -0,0 +1,46 @@ +#pragma once +#include "iputils.hh" +#include "dnsname.hh" +#include "dnspacket.hh" +#include "dnsparser.hh" +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "lua-base4.hh" + +class AuthLua4 : public BaseLua4 +{ +public: + AuthLua4(); + bool updatePolicy(const DNSName &qname, QType qtype, const DNSName &zonename, DNSPacket *packet); + bool axfrfilter(const ComboAddress&, const DNSName&, const DNSResourceRecord&, std::vector&); + LuaContext* getLua(); + + DNSPacket *prequery(DNSPacket *p); + + ~AuthLua4(); // this is so unique_ptr works with an incomplete type +protected: + virtual void postPrepareContext() override; + virtual void postLoad() override; +private: + struct UpdatePolicyQuery { + DNSName qname; + DNSName zonename; + uint16_t qtype; + ComboAddress local, remote; + Netmask realRemote; + DNSName tsigName; + std::string peerPrincipal; + }; + + typedef std::function luacall_update_policy_t; + typedef std::function > > >(const ComboAddress&, const DNSName&, const DNSResourceRecord&)> luacall_axfr_filter_t; + typedef std::function luacall_prequery_t; + + luacall_update_policy_t d_update_policy; + luacall_axfr_filter_t d_axfr_filter; + luacall_prequery_t d_prequery; +}; +std::vector> luaSynth(const std::string& code, const DNSName& qname, + const DNSName& zone, int zoneid, const DNSPacket& dnsp, uint16_t qtype); diff --git a/pdns/lua-base4.cc b/pdns/lua-base4.cc new file mode 100644 index 0000000..39dbb39 --- /dev/null +++ b/pdns/lua-base4.cc @@ -0,0 +1,253 @@ +#include +#include +#include +#include +#include "logger.hh" +#include "iputils.hh" +#include "dnsname.hh" +#include "dnsparser.hh" +#include "dnspacket.hh" +#include "namespaces.hh" +#include "ednssubnet.hh" +#include "lua-base4.hh" +#include "dns_random.hh" + +BaseLua4::BaseLua4() { +} + +void BaseLua4::loadFile(const std::string &fname) { + std::ifstream ifs(fname); + if(!ifs) { + g_log<(new LuaContext); + + // dnsheader + d_lw->registerFunction("getID", [](dnsheader& dh) { return ntohs(dh.id); }); + d_lw->registerFunction("getCD", [](dnsheader& dh) { return dh.cd; }); + d_lw->registerFunction("getTC", [](dnsheader& dh) { return dh.tc; }); + d_lw->registerFunction("getRA", [](dnsheader& dh) { return dh.ra; }); + d_lw->registerFunction("getAD", [](dnsheader& dh) { return dh.ad; }); + d_lw->registerFunction("getAA", [](dnsheader& dh) { return dh.aa; }); + d_lw->registerFunction("getRD", [](dnsheader& dh) { return dh.rd; }); + d_lw->registerFunction("getRCODE", [](dnsheader& dh) { return dh.rcode; }); + d_lw->registerFunction("getOPCODE", [](dnsheader& dh) { return dh.opcode; }); + d_lw->registerFunction("getQDCOUNT", [](dnsheader& dh) { return ntohs(dh.qdcount); }); + d_lw->registerFunction("getANCOUNT", [](dnsheader& dh) { return ntohs(dh.ancount); }); + d_lw->registerFunction("getNSCOUNT", [](dnsheader& dh) { return ntohs(dh.nscount); }); + d_lw->registerFunction("getARCOUNT", [](dnsheader& dh) { return ntohs(dh.arcount); }); + + // DNSName + d_lw->writeFunction("newDN", [](const std::string& dom){ return DNSName(dom); }); + d_lw->registerFunction("__lt", &DNSName::operator<); + d_lw->registerFunction("canonCompare", &DNSName::canonCompare); + d_lw->registerFunction("makeRelative", &DNSName::makeRelative); + d_lw->registerFunction("isPartOf", &DNSName::isPartOf); + d_lw->registerFunction("getRawLabels", &DNSName::getRawLabels); + d_lw->registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); + d_lw->registerFunction("wireLength", [](const DNSName& name) { return name.wirelength(); }); + d_lw->registerFunction("equal", [](const DNSName& lhs, const std::string& rhs) { return lhs==DNSName(rhs); }); + d_lw->registerEqFunction(&DNSName::operator==); + d_lw->registerToStringFunction([](const DNSName&dn ) { return dn.toString(); }); + d_lw->registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); + d_lw->registerFunction("toStringNoDot", [](const DNSName&dn ) { return dn.toStringNoDot(); }); + d_lw->registerFunction("chopOff", [](DNSName&dn ) { return dn.chopOff(); }); + + // DNSResourceRecord + d_lw->writeFunction("newDRR", [](const DNSName& qname, const string& qtype, const unsigned int ttl, const string& content, boost::optional domain_id, boost::optional auth){ + auto drr = DNSResourceRecord(); + drr.qname = qname; + drr.qtype = qtype; + drr.ttl = ttl; + drr.setContent(content); + if (domain_id) + drr.domain_id = *domain_id; + if (auth) + drr.auth = *auth; + return drr; + }); + d_lw->registerEqFunction(&DNSResourceRecord::operator==); + d_lw->registerFunction("__lt", &DNSResourceRecord::operator<); + d_lw->registerToStringFunction([](const DNSResourceRecord& rec) { return rec.getZoneRepresentation(); }); + d_lw->registerFunction("toString", [](const DNSResourceRecord& rec) { return rec.getZoneRepresentation();} ); + d_lw->registerFunction("qname", [](DNSResourceRecord& rec) { return rec.qname; }); + d_lw->registerFunction("wildcardName", [](DNSResourceRecord& rec) { return rec.wildcardname; }); + d_lw->registerFunction("content", [](DNSResourceRecord& rec) { return rec.content; }); + d_lw->registerFunction("lastModified", [](DNSResourceRecord& rec) { return rec.last_modified; }); + d_lw->registerFunction("ttl", [](DNSResourceRecord& rec) { return rec.ttl; }); + d_lw->registerFunction("signttl", [](DNSResourceRecord& rec) { return rec.signttl; }); + d_lw->registerFunction("domainId", [](DNSResourceRecord& rec) { return rec.domain_id; }); + d_lw->registerFunction("qtype", [](DNSResourceRecord& rec) { return rec.qtype.getCode(); }); + d_lw->registerFunction("qclass", [](DNSResourceRecord& rec) { return rec.qclass; }); + d_lw->registerFunction("scopeMask", [](DNSResourceRecord& rec) { return rec.scopeMask; }); + d_lw->registerFunction("auth", [](DNSResourceRecord& rec) { return rec.auth; }); + d_lw->registerFunction("disabled", [](DNSResourceRecord& rec) { return rec.disabled; }); + + // ComboAddress + d_lw->registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); + d_lw->registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); + d_lw->registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } ); + d_lw->registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); + d_lw->registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); + d_lw->registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); + d_lw->registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); + d_lw->registerToStringFunction([](const ComboAddress& ca) { return ca.toString(); }); + d_lw->registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + d_lw->registerFunction("getRaw", [](const ComboAddress& ca) { + if(ca.sin4.sin_family == AF_INET) { + auto t=ca.sin4.sin_addr.s_addr; return string((const char*)&t, 4); + } + else + return string((const char*)&ca.sin6.sin6_addr.s6_addr, 16); + } ); + + d_lw->writeFunction("newCA", [](const std::string& a) { return ComboAddress(a); }); + typedef std::unordered_set cas_t; + d_lw->registerFunction("equal", [](const ComboAddress& lhs, const ComboAddress& rhs) { return ComboAddress::addressOnlyEqual()(lhs, rhs); }); + + // cas_t + d_lw->writeFunction("newCAS", []{ return cas_t(); }); + d_lw->registerFunction > >)>("add", + [](cas_t& cas, const boost::variant > >& in) + { + try { + if(auto s = boost::get(&in)) { + cas.insert(ComboAddress(*s)); + } + else if(auto v = boost::get > >(&in)) { + for(const auto& str : *v) + cas.insert(ComboAddress(str.second)); + } + else + cas.insert(boost::get(in)); + } + catch(std::exception& e) { g_log <registerFunction("check",[](const cas_t& cas, const ComboAddress&ca) { return cas.count(ca)>0; }); + + // QType + d_lw->writeFunction("newQType", [](const string& s) { QType q; q = s; return q; }); + d_lw->registerFunction("getCode", &QType::getCode); + d_lw->registerFunction("getName", &QType::getName); + d_lw->registerEqFunction([](const QType& a, const QType& b){ return a == b;}); // operator overloading confuses LuaContext + d_lw->registerToStringFunction(&QType::getName); + + // Netmask + d_lw->writeFunction("newNetmask", [](const string& s) { return Netmask(s); }); + d_lw->registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary + d_lw->registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } ); + d_lw->registerFunction("isIpv4", &Netmask::isIpv4); + d_lw->registerFunction("isIpv6", &Netmask::isIpv6); + d_lw->registerFunction("getBits", &Netmask::getBits); + d_lw->registerFunction("toString", &Netmask::toString); + d_lw->registerFunction("empty", &Netmask::empty); + d_lw->registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match); + d_lw->registerEqFunction(&Netmask::operator==); + d_lw->registerToStringFunction(&Netmask::toString); + + // NetmaskGroup + d_lw->writeFunction("newNMG", []() { return NetmaskGroup(); }); + d_lw->registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) { nmg.addMask(mask); }); + d_lw->registerFunction>&)>("addMasks", [](NetmaskGroup&nmg, const vector>& masks) { for(const auto& mask: masks) { nmg.addMask(mask.second); } }); + d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); + + // DNSRecord + d_lw->writeFunction("newDR", [](const DNSName &name, const std::string &type, unsigned int ttl, const std::string &content, int place){ QType qtype; qtype = type; auto dr = DNSRecord(); dr.d_name = name; dr.d_type = qtype.getCode(); dr.d_ttl = ttl; dr.d_content = shared_ptr(DNSRecordContent::mastermake(dr.d_type, 1, content)); dr.d_place = static_cast(place); return dr; }); + d_lw->registerMember("name", &DNSRecord::d_name); + d_lw->registerMember("type", &DNSRecord::d_type); + d_lw->registerMember("ttl", &DNSRecord::d_ttl); + d_lw->registerMember("place", &DNSRecord::d_place); + d_lw->registerFunction("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); }); + d_lw->registerFunction(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) { + boost::optional ret; + + if(auto arec = std::dynamic_pointer_cast(dr.d_content)) + ret=arec->getCA(53); + else if(auto aaaarec = std::dynamic_pointer_cast(dr.d_content)) + ret=aaaarec->getCA(53); + return ret; + }); + d_lw->registerFunction("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = shared_ptr(DNSRecordContent::mastermake(dr.d_type, 1, newContent)); }); + + // pdnsload + d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional loglevel) { g_log << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<writeFunction("pdnsrandom", [](boost::optional maximum) { return dns_random(maximum.get_value_or(0xffffffff)); }); + + // certain constants + d_pd.push_back({"PASS", (int)PolicyDecision::PASS}); + d_pd.push_back({"DROP", (int)PolicyDecision::DROP}); + d_pd.push_back({"TRUNCATE", (int)PolicyDecision::TRUNCATE}); + + vector > rcodes = {{"NOERROR", RCode::NoError }, + {"FORMERR", RCode::FormErr }, + {"SERVFAIL", RCode::ServFail }, + {"NXDOMAIN", RCode::NXDomain }, + {"NOTIMP", RCode::NotImp }, + {"REFUSED", RCode::Refused }, + {"YXDOMAIN", RCode::YXDomain }, + {"YXRRSET", RCode::YXRRSet }, + {"NXRRSET", RCode::NXRRSet }, + {"NOTAUTH", RCode::NotAuth }, + {"NOTZONE", RCode::NotZone }}; + for(const auto& rcode : rcodes) + d_pd.push_back({rcode.first, rcode.second}); + + d_pd.push_back({"place", in_t{ + {"QUESTION", 0}, + {"ANSWER", 1}, + {"AUTHORITY", 2}, + {"ADDITIONAL", 3} + }}); + + d_pd.push_back({"loglevels", in_t{ + {"Alert", LOG_ALERT}, + {"Critical", LOG_CRIT}, + {"Debug", LOG_DEBUG}, + {"Emergency", LOG_EMERG}, + {"Info", LOG_INFO}, + {"Notice", LOG_NOTICE}, + {"Warning", LOG_WARNING}, + {"Error", LOG_ERR} + }}); + + for(const auto& n : QType::names) + d_pd.push_back({n.first, n.second}); + + d_lw->registerMember("tv_sec", &timeval::tv_sec); + d_lw->registerMember("tv_usec", &timeval::tv_usec); + + postPrepareContext(); + + // so we can let postprepare do changes to this + d_lw->writeVariable("pdns", d_pd); +} + +void BaseLua4::loadStream(std::istream &is) { + d_lw->executeCode(is); + + postLoad(); +} + +BaseLua4::~BaseLua4() { } + +#endif diff --git a/pdns/lua-base4.hh b/pdns/lua-base4.hh new file mode 100644 index 0000000..c166e3f --- /dev/null +++ b/pdns/lua-base4.hh @@ -0,0 +1,33 @@ +#pragma once +#include "namespaces.hh" +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +class LuaContext; + +#if defined(HAVE_LUA) +#include "ext/luawrapper/include/LuaContext.hpp" +#endif + +class BaseLua4 : public boost::noncopyable +{ +protected: +#ifdef HAVE_LUA + std::unique_ptr d_lw; // this is way on top because it must get destroyed _last_ +#endif + +public: + BaseLua4(); + void loadFile(const std::string &fname); + void loadString(const std::string &script); + void loadStream(std::istream &is); + virtual ~BaseLua4(); // this is so unique_ptr works with an incomplete type +protected: + void prepareContext(); + virtual void postPrepareContext() = 0; + virtual void postLoad() = 0; + typedef vector > in_t; + vector > > d_pd; +}; diff --git a/pdns/lua-record.cc b/pdns/lua-record.cc new file mode 100644 index 0000000..fa7a9a0 --- /dev/null +++ b/pdns/lua-record.cc @@ -0,0 +1,928 @@ +#include "version.hh" +#include "ext/luawrapper/include/LuaContext.hpp" +#include "lua-auth4.hh" +#include +#include "sstuff.hh" +#include +#include "minicurl.hh" +#include "ueberbackend.hh" +#include +#include "dnsrecords.hh" +#include "dns_random.hh" + +#include "../modules/geoipbackend/geoipinterface.hh" // only for the enum + +/* to do: + block AXFR unless TSIG, or override + + investigate IPv6 + + check the wildcard 'no cache' stuff, we may get it wrong + + ponder ECS scopemask setting + + ponder netmask tree from file for huge number of netmasks + + unify ifupurl/ifupport + add attribute for certificate check + add list of current monitors + expire them too? + + pool of UeberBackends? + + Pool checks ? + */ + +extern int g_luaRecordExecLimit; + +using iplist_t = vector >; +using wiplist_t = std::unordered_map; +using ipunitlist_t = vector >; +using opts_t = std::unordered_map; + +class IsUpOracle +{ +private: + struct CheckDesc + { + ComboAddress rem; + string url; + opts_t opts; + bool operator<(const CheckDesc& rhs) const + { + std::map oopts, rhsoopts; + for(const auto& m : opts) + oopts[m.first]=m.second; + for(const auto& m : rhs.opts) + rhsoopts[m.first]=m.second; + + return std::make_tuple(rem, url, oopts) < + std::make_tuple(rhs.rem, rhs.url, rhsoopts); + } + }; +public: + bool isUp(const ComboAddress& remote, const opts_t& opts); + bool isUp(const ComboAddress& remote, const std::string& url, const opts_t& opts); + bool isUp(const CheckDesc& cd); + +private: + void checkURLThread(ComboAddress rem, std::string url, const opts_t& opts); + void checkTCPThread(ComboAddress rem, const opts_t& opts); + + struct Checker + { + std::thread thr; + bool status; + }; + + typedef map statuses_t; + statuses_t d_statuses; + + std::mutex d_mutex; + + void setStatus(const CheckDesc& cd, bool status) + { + std::lock_guard l(d_mutex); + d_statuses[cd].status=status; + } + + void setDown(const ComboAddress& rem, const std::string& url=std::string(), const opts_t& opts = opts_t()) + { + CheckDesc cd{rem, url, opts}; + setStatus(cd, false); + } + + void setUp(const ComboAddress& rem, const std::string& url=std::string(), const opts_t& opts = opts_t()) + { + CheckDesc cd{rem, url, opts}; + + setStatus(cd, true); + } + + void setDown(const CheckDesc& cd) + { + setStatus(cd, false); + } + + void setUp(const CheckDesc& cd) + { + setStatus(cd, true); + } + + bool upStatus(const ComboAddress& rem, const std::string& url=std::string(), const opts_t& opts = opts_t()) + { + CheckDesc cd{rem, url, opts}; + std::lock_guard l(d_mutex); + return d_statuses[cd].status; + } +}; + +bool IsUpOracle::isUp(const CheckDesc& cd) +{ + std::lock_guard l(d_mutex); + auto iter = d_statuses.find(cd); + if(iter == d_statuses.end()) { + d_statuses[cd]=Checker{std::thread(&IsUpOracle::checkTCPThread, this, cd.rem, cd.opts), false}; + return false; + } + return iter->second.status; + +} + +bool IsUpOracle::isUp(const ComboAddress& remote, const opts_t& opts) +{ + CheckDesc cd{remote, "", opts}; + return isUp(cd); +} + +bool IsUpOracle::isUp(const ComboAddress& remote, const std::string& url, const opts_t& opts) +{ + CheckDesc cd{remote, url, opts}; + std::lock_guard l(d_mutex); + auto iter = d_statuses.find(cd); + if(iter == d_statuses.end()) { + // g_log<second.status; +} + +void IsUpOracle::checkTCPThread(ComboAddress rem, const opts_t& opts) +{ + CheckDesc cd{rem, "", opts}; + setDown(cd); + for(bool first=true;;first=false) { + try { + Socket s(rem.sin4.sin_family, SOCK_STREAM); + ComboAddress src; + s.setNonBlocking(); + if(opts.count("source")) { + src=ComboAddress(opts.at("source")); + s.bind(src); + } + s.connect(rem, 1); + if(!isUp(cd)) { + g_log< +bool doCompare(const T& var, const std::string& res, const C& cmp) +{ + if(auto country = boost::get(&var)) + return cmp(*country, res); + + auto countries=boost::get > >(&var); + for(const auto& country : *countries) { + if(cmp(country.second, res)) + return true; + } + return false; +} +} + + +std::string getGeo(const std::string& ip, GeoIPInterface::GeoIPQueryAttribute qa) +{ + static bool initialized; + extern std::function g_getGeo; + if(!g_getGeo) { + if(!initialized) { + g_log<& ips) +{ + if (ips.empty()) { + throw std::invalid_argument("The IP list cannot be empty"); + } + return ips[dns_random(ips.size())]; +} + +static ComboAddress hashed(const ComboAddress& who, const vector& ips) +{ + if (ips.empty()) { + throw std::invalid_argument("The IP list cannot be empty"); + } + ComboAddress::addressOnlyHash aoh; + return ips[aoh(who) % ips.size()]; +} + + +static ComboAddress pickwrandom(const vector >& wips) +{ + if (wips.empty()) { + throw std::invalid_argument("The IP list cannot be empty"); + } + int sum=0; + vector > pick; + for(auto& i : wips) { + sum += i.first; + pick.push_back({sum, i.second}); + } + int r = dns_random(sum); + auto p = upper_bound(pick.begin(), pick.end(),r, [](int r, const decltype(pick)::value_type& a) { return r < a.first;}); + return p->second; +} + +static ComboAddress pickwhashed(const ComboAddress& bestwho, vector >& wips) +{ + if (wips.empty()) { + return ComboAddress(); + } + int sum=0; + vector > pick; + for(auto& i : wips) { + sum += i.first; + pick.push_back({sum, i.second}); + } + ComboAddress::addressOnlyHash aoh; + int r = aoh(bestwho) % sum; + auto p = upper_bound(pick.begin(), pick.end(),r, [](int r, const decltype(pick)::value_type& a) { return r < a.first;}); + return p->second; +} + +static bool getLatLon(const std::string& ip, double& lat, double& lon) +{ + string inp = getGeo(ip, GeoIPInterface::Location); + if(inp.empty()) + return false; + lat=atof(inp.c_str()); + auto pos=inp.find(' '); + if(pos != string::npos) + lon=atof(inp.c_str() + pos); + return true; +} + +static bool getLatLon(const std::string& ip, string& loc) +{ + int latdeg, latmin, londeg, lonmin; + double latsec, lonsec; + char lathem='X', lonhem='X'; + + double lat, lon; + if(!getLatLon(ip, lat, lon)) + return false; + + if(lat > 0) { + lathem='N'; + } + else { + lat = -lat; + lathem='S'; + } + + if(lon > 0) { + lonhem='E'; + } + else { + lon = -lon; + lonhem='W'; + } + + /* + >>> deg = int(R) + >>> min = int((R - int(R)) * 60.0) + >>> sec = (((R - int(R)) * 60.0) - min) * 60.0 + >>> print("{}º {}' {}\"".format(deg, min, sec)) + */ + + + latdeg = lat; + latmin = (lat - latdeg)*60.0; + latsec = (((lat - latdeg)*60.0) - latmin)*60.0; + + londeg = lon; + lonmin = (lon - londeg)*60.0; + lonsec = (((lon - londeg)*60.0) - lonmin)*60.0; + + // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m + + boost::format fmt("%d %d %d %c %d %d %d %c 0.00m 1.00m 10000.00m 10.00m"); + + loc= (fmt % latdeg % latmin % latsec % lathem % londeg % lonmin % lonsec % lonhem ).str(); + return true; +} + +static ComboAddress pickclosest(const ComboAddress& bestwho, const vector& wips) +{ + if (wips.empty()) { + throw std::invalid_argument("The IP list cannot be empty"); + } + map > ranked; + double wlat=0, wlon=0; + getLatLon(bestwho.toString(), wlat, wlon); + // cout<<"bestwho "< ret; + for(const auto& c : wips) { + double lat=0, lon=0; + getLatLon(c.toString(), lat, lon); + // cout< 180) + londiff = 360 - londiff; + double dist2=latdiff*latdiff + londiff*londiff; + // cout<<" distance: "<second[dns_random(ranked.begin()->second.size())]; +} + +static std::vector lookup(const DNSName& name, uint16_t qtype, int zoneid) +{ + static UeberBackend ub; + static std::mutex mut; + std::lock_guard lock(mut); + ub.lookup(QType(qtype), name, nullptr, zoneid); + DNSZoneRecord dr; + vector ret; + while(ub.get(dr)) { + ret.push_back(dr); + } + return ret; +} + +static std::string getOptionValue(const boost::optional>& options, const std::string &name, const std::string &defaultValue) +{ + string selector=defaultValue; + if(options) { + if(options->count(name)) + selector=options->find(name)->second; + } + return selector; +} + +static vector useSelector(const std::string &selector, const ComboAddress& bestwho, const vector& candidates) +{ + vector ret; + + if(selector=="all") + return candidates; + else if(selector=="random") + ret.emplace_back(pickrandom(candidates)); + else if(selector=="pickclosest") + ret.emplace_back(pickclosest(bestwho, candidates)); + else if(selector=="hashed") + ret.emplace_back(hashed(bestwho, candidates)); + else { + g_log< convIpListToString(const vector &comboAddresses) +{ + vector ret; + + for (const auto& c : comboAddresses) { + ret.emplace_back(c.toString()); + } + + return ret; +} + +static vector convIplist(const iplist_t& src) +{ + vector ret; + + for(const auto& ip : src) { + ret.emplace_back(ip.second); + } + + return ret; +} + +static vector > convWIplist(std::unordered_map src) +{ + vector > ret; + + for(const auto& i : src) { + ret.emplace_back(atoi(i.second.at(1).c_str()), ComboAddress(i.second.at(2))); + } + + return ret; +} + +static thread_local unique_ptr s_LUA; +bool g_LuaRecordSharedState; + +std::vector> luaSynth(const std::string& code, const DNSName& query, const DNSName& zone, int zoneid, const DNSPacket& dnsp, uint16_t qtype) +{ + if(!s_LUA || // we don't have a Lua state yet + !g_LuaRecordSharedState) { // or we want a new one even if we had one + s_LUA = make_unique(); + } + + std::vector> ret; + + LuaContext& lua = *s_LUA->getLua(); + lua.writeVariable("qname", query); + lua.writeVariable("who", dnsp.getRemote()); + lua.writeVariable("dh", (dnsheader*)&dnsp.d); + lua.writeVariable("dnssecOK", dnsp.d_dnssecOk); + lua.writeVariable("tcp", dnsp.d_tcp); + lua.writeVariable("ednsPKTSize", dnsp.d_ednsRawPacketSizeLimit); + ComboAddress bestwho; + if(dnsp.hasEDNSSubnet()) { + lua.writeVariable("ecswho", dnsp.getRealRemote()); + bestwho=dnsp.getRealRemote().getNetwork(); + } + else { + lua.writeVariable("ecswho", nullptr); + bestwho=dnsp.getRemote(); + } + + lua.writeVariable("bestwho", bestwho); + + lua.writeFunction("latlon", [&bestwho]() { + double lat, lon; + getLatLon(bestwho.toString(), lat, lon); + return std::to_string(lat)+" "+std::to_string(lon); + }); + + lua.writeFunction("latlonloc", [&bestwho]() { + string loc; + getLatLon(bestwho.toString(), loc); + return loc; + }); + + + lua.writeFunction("closestMagic", [&bestwho,&query]() { + vector candidates; + // Getting something like 192-0-2-1.192-0-2-2.198-51-100-1.example.org + for(auto l : query.getRawLabels()) { + boost::replace_all(l, "-", "."); + try { + candidates.emplace_back(l); + } catch (const PDNSException& e) { + // no need to continue as we most likely reached the end of the ip list + break ; + } + } + return pickclosest(bestwho, candidates).toString(); + }); + + lua.writeFunction("latlonMagic", [&query](){ + auto labels= query.getRawLabels(); + if(labels.size()<4) + return std::string("unknown"); + double lat, lon; + getLatLon(labels[3]+"."+labels[2]+"."+labels[1]+"."+labels[0], lat, lon); + return std::to_string(lat)+" "+std::to_string(lon); + }); + + + lua.writeFunction("createReverse", [&query](string suffix, boost::optional> e){ + try { + auto labels= query.getRawLabels(); + if(labels.size()<4) + return std::string("unknown"); + + vector candidates; + + // exceptions are relative to zone + // so, query comes in for 4.3.2.1.in-addr.arpa, zone is called 2.1.in-addr.arpa + // e["1.2.3.4"]="bert.powerdns.com" - should match, easy enough to do + // the issue is with classless delegation.. + if(e) { + ComboAddress req(labels[3]+"."+labels[2]+"."+labels[1]+"."+labels[0], 0); + const auto& uom = *e; + for(const auto& c : uom) + if(ComboAddress(c.first, 0) == req) + return c.second; + } + + + boost::format fmt(suffix); + fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit ) ); + fmt % labels[3] % labels[2] % labels[1] % labels[0]; + + fmt % (labels[3]+"-"+labels[2]+"-"+labels[1]+"-"+labels[0]); + + boost::format fmt2("%02x%02x%02x%02x"); + for(int i=3; i>=0; --i) + fmt2 % atoi(labels[i].c_str()); + + fmt % (fmt2.str()); + + return fmt.str(); + } + catch(std::exception& e) { + g_log<> e){ + vector candidates; + + try { + auto labels= query.getRawLabels(); + if(labels.size()<32) + return std::string("unknown"); + boost::format fmt(suffix); + fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit ) ); + + + string together; + vector quads; + for(int i=0; i<8; ++i) { + if(i) + together+=":"; + string quad; + for(int j=0; j <4; ++j) { + quad.append(1, labels[31-i*4-j][0]); + together += labels[31-i*4-j][0]; + } + quads.push_back(quad); + } + ComboAddress ip6(together,0); + + if(e) { + auto& addrs=*e; + for(const auto& addr: addrs) { + // this makes sure we catch all forms of the address + if(ComboAddress(addr.first,0)==ip6) + return addr.second; + } + } + + string dashed=ip6.toString(); + boost::replace_all(dashed, ":", "-"); + + for(int i=31; i>=0; --i) + fmt % labels[i]; + fmt % dashed; + + for(const auto& quad : quads) + fmt % quad; + + return fmt.str(); + } + catch(std::exception& e) { + g_log< >& ips, const boost::optional> options) { + vector candidates, unavailables; + opts_t opts; + vector conv; + std::string selector; + + if(options) + opts = *options; + for(const auto& i : ips) { + ComboAddress rem(i.second, port); + if(g_up.isUp(rem, opts)) { + candidates.push_back(rem); + } + else { + unavailables.push_back(rem); + } + } + if(!candidates.empty()) { + // use regular selector + selector = getOptionValue(options, "selector", "random"); + } else { + // All units are down, apply backupSelector on all candidates + candidates = std::move(unavailables); + selector = getOptionValue(options, "backupSelector", "random"); + } + + vector res = useSelector(selector, bestwho, candidates); + return convIpListToString(res); + }); + + lua.writeFunction("ifurlup", [&bestwho](const std::string& url, + const boost::variant& ips, + boost::optional options) { + + vector > candidates; + opts_t opts; + if(options) + opts = *options; + if(auto simple = boost::get(&ips)) { + vector unit = convIplist(*simple); + candidates.push_back(unit); + } else { + auto units = boost::get(ips); + for(const auto& u : units) { + vector unit = convIplist(u.second); + candidates.push_back(unit); + } + } + + for(const auto& unit : candidates) { + vector available; + for(const auto& c : unit) { + if(g_up.isUp(c, url, opts)) { + available.push_back(c); + } + } + if(!available.empty()) { + vector res = useSelector(getOptionValue(options, "selector", "random"), bestwho, available); + return convIpListToString(res); + } + } + + // All units down, apply backupSelector on all candidates + vector ret{}; + for(const auto& unit : candidates) { + ret.insert(ret.end(), unit.begin(), unit.end()); + } + + vector res = useSelector(getOptionValue(options, "backupSelector", "random"), bestwho, ret); + return convIpListToString(res); + }); + + + /* idea: we have policies on vectors of ComboAddresses, like + random, pickwrandom, pickwhashed, pickclosest. In C++ this is ComboAddress in, + ComboAddress out. In Lua, vector string in, string out */ + + /* + * Returns a random IP address from the supplied list + * @example pickrandom({ '1.2.3.4', '5.4.3.2' })" + */ + lua.writeFunction("pickrandom", [](const iplist_t& ips) { + vector conv = convIplist(ips); + + return pickrandom(conv).toString(); + }); + + + /* + * Returns a random IP address from the supplied list, as weighted by the + * various ``weight`` parameters + * @example pickwrandom({ {100, '1.2.3.4'}, {50, '5.4.3.2'}, {1, '192.168.1.0'} }) + */ + lua.writeFunction("pickwrandom", [](std::unordered_map ips) { + vector > conv = convWIplist(ips); + + return pickwrandom(conv).toString(); + }); + + /* + * Based on the hash of `bestwho`, returns an IP address from the list + * supplied, as weighted by the various `weight` parameters + * @example pickwhashed({ {15, '1.2.3.4'}, {50, '5.4.3.2'} }) + */ + lua.writeFunction("pickwhashed", [&bestwho](std::unordered_map ips) { + vector > conv; + + for(auto& i : ips) + conv.emplace_back(atoi(i.second[1].c_str()), ComboAddress(i.second[2])); + + return pickwhashed(bestwho, conv).toString(); + }); + + + lua.writeFunction("pickclosest", [&bestwho](const iplist_t& ips) { + vector conv = convIplist(ips); + + return pickclosest(bestwho, conv).toString(); + + }); + + + lua.writeFunction("report", [](string event, boost::optional line){ + throw std::runtime_error("Script took too long"); + }); + if (g_luaRecordExecLimit > 0) { + lua.executeCode(boost::str(boost::format("debug.sethook(report, '', %d)") % g_luaRecordExecLimit)); + } + + // TODO: make this better. Accept netmask/CA objects; provide names for the attr constants + lua.writeFunction("geoiplookup", [](const string &ip, const GeoIPInterface::GeoIPQueryAttribute attr) { + return getGeo(ip, attr); + }); + + typedef const boost::variant > > combovar_t; + lua.writeFunction("continent", [&bestwho](const combovar_t& continent) { + string res=getGeo(bestwho.toString(), GeoIPInterface::Continent); + return doCompare(continent, res, [](const std::string& a, const std::string& b) { + return !strcasecmp(a.c_str(), b.c_str()); + }); + }); + + lua.writeFunction("asnum", [&bestwho](const combovar_t& asns) { + string res=getGeo(bestwho.toString(), GeoIPInterface::ASn); + return doCompare(asns, res, [](const std::string& a, const std::string& b) { + return !strcasecmp(a.c_str(), b.c_str()); + }); + }); + + lua.writeFunction("country", [&bestwho](const combovar_t& var) { + string res = getGeo(bestwho.toString(), GeoIPInterface::Country2); + return doCompare(var, res, [](const std::string& a, const std::string& b) { + return !strcasecmp(a.c_str(), b.c_str()); + }); + + }); + + lua.writeFunction("netmask", [bestwho](const iplist_t& ips) { + for(const auto& i :ips) { + Netmask nm(i.second); + if(nm.match(bestwho)) + return true; + } + return false; + }); + + /* { + { + {'192.168.0.0/16', '10.0.0.0/8'}, + {'192.168.20.20', '192.168.20.21'} + }, + { + {'0.0.0.0/0'}, {'192.0.2.1'} + } + } + */ + lua.writeFunction("view", [bestwho](const vector > > >& in) { + for(const auto& rule : in) { + const auto& netmasks=rule.second[0].second; + const auto& destinations=rule.second[1].second; + for(const auto& nmpair : netmasks) { + Netmask nm(nmpair.second); + if(nm.match(bestwho)) { + if (destinations.empty()) { + throw std::invalid_argument("The IP list cannot be empty (for netmask " + nm.toString() + ")"); + } + return destinations[dns_random(destinations.size())].second; + } + } + } + return std::string(); + } + ); + + + lua.writeFunction("include", [&lua,zone,zoneid](string record) { + try { + vector drs = lookup(DNSName(record) +zone, QType::LUA, zoneid); + for(const auto& dr : drs) { + auto lr = getRR(dr.dr); + lua.executeCode(lr->getCode()); + } + } + catch(std::exception& e) { + g_log< > > >(actual); + + vector contents; + if(auto str = boost::get(&content)) + contents.push_back(*str); + else + for(const auto& c : boost::get>>(content)) + contents.push_back(c.second); + + for(const auto& content: contents) { + if(qtype==QType::TXT) + ret.push_back(DNSRecordContent::mastermake(qtype, QClass::IN, '"'+content+'"' )); + else + ret.push_back(DNSRecordContent::mastermake(qtype, QClass::IN, content )); + } + } catch(std::exception &e) { + g_log< +#include "communicator.hh" +#include +#include + +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "packethandler.hh" +#include "nameserver.hh" +#include "resolver.hh" +#include "logger.hh" +#include "dns.hh" +#include "arguments.hh" +#include "packetcache.hh" +#include "base64.hh" +#include "namespaces.hh" + + +void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B) +{ + bool hasQueuedItem=false; + set nsset, ips; + DNSZoneRecord rr; + FindNS fns; + + + try { + if (d_onlyNotify.size()) { + B->lookup(QType(QType::NS), di.zone, nullptr, di.id); + while(B->get(rr)) + nsset.insert(getRR(rr.dr)->getNS().toString()); + + for(set::const_iterator j=nsset.begin();j!=nsset.end();++j) { + vector nsips=fns.lookup(DNSName(*j), B); + if(nsips.empty()) + g_log<::const_iterator k=nsips.begin();k!=nsips.end();++k) { + const ComboAddress caIp(*k, 53); + if(!d_preventSelfNotification || !AddressIsUs(caIp)) { + if(!d_onlyNotify.match(&caIp)) + g_log<::const_iterator j=ips.begin();j!=ips.end();++j) { + g_log< alsoNotify(d_alsoNotify); + B->alsoNotifies(di.zone, &alsoNotify); + + for(set::const_iterator j=alsoNotify.begin();j!=alsoNotify.end();++j) { + try { + const ComboAddress caIp(*j, 53); + g_log<getDomainInfo(domain, di)) { + g_log<setNotified(di.id, di.serial); + + return true; +} + +void NotificationQueue::dump() +{ + cerr<<"Waiting for notification responses: "<getBackend(); + vector cmdomains; + B->getUpdatedMasters(&cmdomains); + + if(cmdomains.empty()) { + if(d_masterschanged) + g_log<1 ? "s" : "")<<" for which we are master need"<< + (cmdomains.size()>1 ? "" : "s")<< + " notifications"<setNotified(di.id, di.serial); + } +} + +time_t CommunicatorClass::doNotifications(PacketHandler *P) +{ + UeberBackend *B=P->getBackend(); + ComboAddress from; + Utility::socklen_t fromlen; + char buffer[1500]; + int sock; + ssize_t size; + set fds = {d_nsock4, d_nsock6}; + + // receive incoming notifications on the nonblocking socket and take them off the list + while(waitForMultiData(fds, 0, 0, &sock) > 0) { + fromlen=sizeof(from); + size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen); + if(size < 0) + break; + DNSPacket p(true); + + p.setRemote(&from); + + if(p.parse(buffer,(size_t)size)<0) { + g_log< meta; + DNSName tsigkeyname; + DNSName tsigalgorithm; + string tsigsecret64; + string tsigsecret; + + if (::arg().mustDo("send-signed-notify") && B->getDomainMetadata(domain, "TSIG-ALLOW-AXFR", meta) && meta.size() > 0) { + tsigkeyname = DNSName(meta[0]); + } + + vector packet; + DNSPacketWriter pw(packet, domain, QType::SOA, 1, Opcode::Notify); + pw.getHeader()->id = id; + pw.getHeader()->aa = true; + + if (tsigkeyname.empty() == false) { + if (!B->getTSIGKey(tsigkeyname, &tsigalgorithm, &tsigsecret64)) { + g_log<time(0)-900) // recent hole + return true; + + // do we want to purge this? XXX FIXME + return false; +} + +void CommunicatorClass::makeNotifySockets() +{ + if(!::arg()["query-local-address"].empty()) { + d_nsock4 = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true, ::arg().mustDo("non-local-bind")); + } else { + d_nsock4 = -1; + } + if(!::arg()["query-local-address6"].empty()) { + d_nsock6 = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true, ::arg().mustDo("non-local-bind")); + } else { + d_nsock6 = -1; + } +} + +void CommunicatorClass::notify(const DNSName &domain, const string &ip) +{ + d_nq.add(domain, ip); + d_any_sem.post(); +} diff --git a/pdns/minicurl.cc b/pdns/minicurl.cc new file mode 100644 index 0000000..5c846d0 --- /dev/null +++ b/pdns/minicurl.cc @@ -0,0 +1,177 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 powerdns.com bv + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "minicurl.hh" +#include +#include + +void MiniCurl::init() +{ + static std::atomic_flag s_init = ATOMIC_FLAG_INIT; + + if (s_init.test_and_set()) + return; + + CURLcode code = curl_global_init(CURL_GLOBAL_ALL); + if (code != 0) { + throw std::runtime_error("Error initializing libcurl"); + } +} + +MiniCurl::MiniCurl(const string& useragent) +{ + d_curl = curl_easy_init(); + if (d_curl == nullptr) { + throw std::runtime_error("Error creating a MiniCurl session"); + } + curl_easy_setopt(d_curl, CURLOPT_USERAGENT, useragent.c_str()); +} + +MiniCurl::~MiniCurl() +{ + // NEEDS TO CLEAN HOSTLIST + curl_easy_cleanup(d_curl); +} + +size_t MiniCurl::write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) +{ + MiniCurl* us = (MiniCurl*)userdata; + us->d_data.append(ptr, size*nmemb); + return size*nmemb; +} + +static string extractHostFromURL(const std::string& url) +{ + auto pos = url.find("://"); + if(pos == string::npos) + throw runtime_error("Can't find host part of '"+url+"'"); + pos += 3; + auto endpos = url.find('/', pos); + if(endpos == string::npos) + return url.substr(pos); + + return url.substr(pos, endpos-pos); +} + +void MiniCurl::setupURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src) +{ + if(rem) { + struct curl_slist *hostlist = nullptr; // THIS SHOULD BE FREED + + // url = http://hostname.enzo/url + string host4=extractHostFromURL(str); + // doest the host contain port indication + std::size_t found = host4.find(':'); + vector ports{80, 443}; + if (found != std::string::npos) { + int port = std::stoi(host4.substr(found + 1)); + if (port <= 0 || port > 65535) + throw std::overflow_error("Invalid port number"); + ports = {(uint16_t)port}; + host4 = host4.substr(0, found); + } + + for (const auto& port : ports) { + string hcode = boost::str(boost::format("%s:%u:%s") % host4 % port % rem->toString()); + hostlist = curl_slist_append(hostlist, hcode.c_str()); + } + + curl_easy_setopt(d_curl, CURLOPT_RESOLVE, hostlist); + } + if(src) { + curl_easy_setopt(d_curl, CURLOPT_INTERFACE, src->toString().c_str()); + } + curl_easy_setopt(d_curl, CURLOPT_FOLLOWLOCATION, true); + /* only allow HTTP and HTTPS */ + curl_easy_setopt(d_curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_easy_setopt(d_curl, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(d_curl, CURLOPT_SSL_VERIFYHOST, false); + curl_easy_setopt(d_curl, CURLOPT_FAILONERROR, true); + curl_easy_setopt(d_curl, CURLOPT_URL, str.c_str()); + curl_easy_setopt(d_curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(d_curl, CURLOPT_WRITEDATA, this); + curl_easy_setopt(d_curl, CURLOPT_TIMEOUT, 2L); + + clearHeaders(); + d_data.clear(); +} + +std::string MiniCurl::getURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src) +{ + setupURL(str, rem, src); + auto res = curl_easy_perform(d_curl); + long http_code = 0; + curl_easy_getinfo(d_curl, CURLINFO_RESPONSE_CODE, &http_code); + + if(res != CURLE_OK || http_code != 200) { + throw std::runtime_error("Unable to retrieve URL ("+std::to_string(http_code)+"): "+string(curl_easy_strerror(res))); + } + std::string ret=d_data; + d_data.clear(); + return ret; +} + +std::string MiniCurl::postURL(const std::string& str, const std::string& postdata, MiniCurlHeaders& headers) +{ + setupURL(str); + setHeaders(headers); + curl_easy_setopt(d_curl, CURLOPT_POSTFIELDSIZE, postdata.size()); + curl_easy_setopt(d_curl, CURLOPT_POSTFIELDS, postdata.c_str()); + + auto res = curl_easy_perform(d_curl); + + long http_code = 0; + curl_easy_getinfo(d_curl, CURLINFO_RESPONSE_CODE, &http_code); + + if(res != CURLE_OK) + throw std::runtime_error("Unable to post URL ("+std::to_string(http_code)+"): "+string(curl_easy_strerror(res))); + + std::string ret=d_data; + + d_data.clear(); + return ret; +} + +void MiniCurl::clearHeaders() +{ + if (d_curl) { + curl_easy_setopt(d_curl, CURLOPT_HTTPHEADER, NULL); + if (d_header_list != nullptr) { + curl_slist_free_all(d_header_list); + d_header_list = nullptr; + } + } +} + +void MiniCurl::setHeaders(const MiniCurlHeaders& headers) +{ + if (d_curl) { + for (auto& header : headers) { + std::stringstream header_ss; + header_ss << header.first << ": " << header.second; + d_header_list = curl_slist_append(d_header_list, header_ss.str().c_str()); + } + curl_easy_setopt(d_curl, CURLOPT_HTTPHEADER, d_header_list); + } +} diff --git a/pdns/minicurl.hh b/pdns/minicurl.hh new file mode 100644 index 0000000..a4a3663 --- /dev/null +++ b/pdns/minicurl.hh @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 powerdns.com bv + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once +#include +#include +#include "iputils.hh" +// turns out 'CURL' is currently typedef for void which means we can't easily forward declare it + +class MiniCurl +{ +public: + using MiniCurlHeaders = std::map; + + static void init(); + + MiniCurl(const string& useragent="MiniCurl/0.0"); + ~MiniCurl(); + MiniCurl& operator=(const MiniCurl&) = delete; + std::string getURL(const std::string& str, const ComboAddress* rem=0, const ComboAddress* src=0); + std::string postURL(const std::string& str, const std::string& postdata, MiniCurlHeaders& headers); +private: + CURL *d_curl; + static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata); + std::string d_data; + struct curl_slist* d_header_list = nullptr; + void setupURL(const std::string& str, const ComboAddress* rem=0, const ComboAddress* src=0); + void setHeaders(const MiniCurlHeaders& headers); + void clearHeaders(); +}; diff --git a/pdns/misc.cc b/pdns/misc.cc new file mode 100644 index 0000000..a051b7e --- /dev/null +++ b/pdns/misc.cc @@ -0,0 +1,1524 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "misc.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pdnsexception.hh" +#include +#include +#include "iputils.hh" +#include "dnsparser.hh" +#include +#include +#include +#ifdef __FreeBSD__ +# include +#endif +#ifdef __NetBSD__ +# include +# include +#endif + +bool g_singleThreaded; + +size_t writen2(int fd, const void *buf, size_t count) +{ + const char *ptr = (char*)buf; + const char *eptr = ptr + count; + + ssize_t res; + while(ptr != eptr) { + res = ::write(fd, ptr, eptr - ptr); + if(res < 0) { + if (errno == EAGAIN) + throw std::runtime_error("used writen2 on non-blocking socket, got EAGAIN"); + else + unixDie("failed in writen2"); + } + else if (res == 0) + throw std::runtime_error("could not write all bytes, got eof in writen2"); + + ptr += (size_t) res; + } + + return count; +} + +size_t readn2(int fd, void* buffer, size_t len) +{ + size_t pos=0; + ssize_t res; + for(;;) { + res = read(fd, (char*)buffer + pos, len - pos); + if(res == 0) + throw runtime_error("EOF while reading message"); + if(res < 0) { + if (errno == EAGAIN) + throw std::runtime_error("used readn2 on non-blocking socket, got EAGAIN"); + else + unixDie("failed in readn2"); + } + + pos+=(size_t)res; + if(pos == len) + break; + } + return len; +} + +size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout) +{ + size_t pos = 0; + time_t start = 0; + int remainingTime = totalTimeout; + if (totalTimeout) { + start = time(NULL); + } + + do { + ssize_t got = read(fd, (char *)buffer + pos, len - pos); + if (got > 0) { + pos += (size_t) got; + } + else if (got == 0) { + throw runtime_error("EOF while reading message"); + } + else { + if (errno == EAGAIN) { + int res = waitForData(fd, (totalTimeout == 0 || idleTimeout <= remainingTime) ? idleTimeout : remainingTime); + if (res > 0) { + /* there is data available */ + } + else if (res == 0) { + throw runtime_error("Timeout while waiting for data to read"); + } else { + throw runtime_error("Error while waiting for data to read"); + } + } + else { + unixDie("failed in readn2WithTimeout"); + } + } + + if (totalTimeout) { + time_t now = time(NULL); + int elapsed = now - start; + if (elapsed >= remainingTime) { + throw runtime_error("Timeout while reading data"); + } + start = now; + remainingTime -= elapsed; + } + } + while (pos < len); + + return len; +} + +size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout) +{ + size_t pos = 0; + do { + ssize_t written = write(fd, (char *)buffer + pos, len - pos); + + if (written > 0) { + pos += (size_t) written; + } + else if (written == 0) + throw runtime_error("EOF while writing message"); + else { + if (errno == EAGAIN) { + int res = waitForRWData(fd, false, timeout, 0); + if (res > 0) { + /* there is room available */ + } + else if (res == 0) { + throw runtime_error("Timeout while waiting to write data"); + } else { + throw runtime_error("Error while waiting for room to write data"); + } + } + else { + unixDie("failed in write2WithTimeout"); + } + } + } + while (pos < len); + + return len; +} + +string nowTime() +{ + time_t now = time(nullptr); + struct tm* tm = localtime(&now); + char buffer[30]; + // YYYY-mm-dd HH:MM:SS TZOFF + strftime(buffer, sizeof(buffer), "%F %T %z", tm); + buffer[sizeof(buffer)-1] = '\0'; + return string(buffer); +} + +uint16_t getShort(const unsigned char *p) +{ + return p[0] * 256 + p[1]; +} + + +uint16_t getShort(const char *p) +{ + return getShort((const unsigned char *)p); +} + +uint32_t getLong(const unsigned char* p) +{ + return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; +} + +uint32_t getLong(const char* p) +{ + return getLong((unsigned char *)p); +} + +static bool ciEqual(const string& a, const string& b) +{ + if(a.size()!=b.size()) + return false; + + string::size_type pos=0, epos=a.size(); + for(;pos < epos; ++pos) + if(dns_tolower(a[pos])!=dns_tolower(b[pos])) + return false; + return true; +} + +/** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */ +static bool endsOn(const string &domain, const string &suffix) +{ + if( suffix.empty() || ciEqual(domain, suffix) ) + return true; + + if(domain.size()<=suffix.size()) + return false; + + string::size_type dpos=domain.size()-suffix.size()-1, spos=0; + + if(domain[dpos++]!='.') + return false; + + for(; dpos < domain.size(); ++dpos, ++spos) + if(dns_tolower(domain[dpos]) != dns_tolower(suffix[spos])) + return false; + + return true; +} + +/** strips a domain suffix from a domain, returns true if it stripped */ +bool stripDomainSuffix(string *qname, const string &domain) +{ + if(!endsOn(*qname, domain)) + return false; + + if(toLower(*qname)==toLower(domain)) + *qname="@"; + else { + if((*qname)[qname->size()-domain.size()-1]!='.') + return false; + + qname->resize(qname->size()-domain.size()-1); + } + return true; +} + +static void parseService4(const string &descr, ServiceTuple &st) +{ + vectorparts; + stringtok(parts,descr,":"); + if(parts.empty()) + throw PDNSException("Unable to parse '"+descr+"' as a service"); + st.host=parts[0]; + if(parts.size()>1) + st.port=pdns_stou(parts[1]); +} + +static void parseService6(const string &descr, ServiceTuple &st) +{ + string::size_type pos=descr.find(']'); + if(pos == string::npos) + throw PDNSException("Unable to parse '"+descr+"' as an IPv6 service"); + + st.host=descr.substr(1, pos-1); + if(pos + 2 < descr.length()) + st.port=pdns_stou(descr.substr(pos+2)); +} + + +void parseService(const string &descr, ServiceTuple &st) +{ + if(descr.empty()) + throw PDNSException("Unable to parse '"+descr+"' as a service"); + + vector parts; + stringtok(parts, descr, ":"); + + if(descr[0]=='[') { + parseService6(descr, st); + } + else if(descr[0]==':' || parts.size() > 2 || descr.find("::") != string::npos) { + st.host=descr; + } + else { + parseService4(descr, st); + } +} + +// returns -1 in case if error, 0 if no data is available, 1 if there is. In the first two cases, errno is set +int waitForData(int fd, int seconds, int useconds) +{ + return waitForRWData(fd, true, seconds, useconds); +} + +int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error, bool* disconnected) +{ + int ret; + + struct pollfd pfd; + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = fd; + + if(waitForRead) + pfd.events=POLLIN; + else + pfd.events=POLLOUT; + + ret = poll(&pfd, 1, seconds * 1000 + useconds/1000); + if (ret > 0) { + if (error && (pfd.revents & POLLERR)) { + *error = true; + } + if (disconnected && (pfd.revents & POLLHUP)) { + *disconnected = true; + } + } + + return ret; +} + +// returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set +int waitForMultiData(const set& fds, const int seconds, const int useconds, int* fdOut) { + set realFDs; + for (const auto& fd : fds) { + if (fd >= 0 && realFDs.count(fd) == 0) { + realFDs.insert(fd); + } + } + + std::vector pfds(realFDs.size()); + memset(pfds.data(), 0, realFDs.size()*sizeof(struct pollfd)); + int ctr = 0; + for (const auto& fd : realFDs) { + pfds[ctr].fd = fd; + pfds[ctr].events = POLLIN; + ctr++; + } + + int ret; + if(seconds >= 0) + ret = poll(pfds.data(), realFDs.size(), seconds * 1000 + useconds/1000); + else + ret = poll(pfds.data(), realFDs.size(), -1); + if(ret <= 0) + return ret; + + set pollinFDs; + for (const auto& pfd : pfds) { + if (pfd.revents & POLLIN) { + pollinFDs.insert(pfd.fd); + } + } + set::const_iterator it(pollinFDs.begin()); + advance(it, random() % pollinFDs.size()); + *fdOut = *it; + return 1; +} + +// returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set +int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd) +{ + int ret; + + struct pollfd pfds[2]; + memset(&pfds[0], 0, 2*sizeof(struct pollfd)); + pfds[0].fd = fd1; + pfds[1].fd = fd2; + + pfds[0].events= pfds[1].events = POLLIN; + + int nsocks = 1 + (fd2 >= 0); // fd2 can optionally be -1 + + if(seconds >= 0) + ret = poll(pfds, nsocks, seconds * 1000 + useconds/1000); + else + ret = poll(pfds, nsocks, -1); + if(!ret || ret < 0) + return ret; + + if((pfds[0].revents & POLLIN) && !(pfds[1].revents & POLLIN)) + *fd = pfds[0].fd; + else if((pfds[1].revents & POLLIN) && !(pfds[0].revents & POLLIN)) + *fd = pfds[1].fd; + else if(ret == 2) { + *fd = pfds[random()%2].fd; + } + else + *fd = -1; // should never happen + + return 1; +} + + +string humanDuration(time_t passed) +{ + ostringstream ret; + if(passed<60) + ret<> 24)&0xff, + (val >> 16)&0xff, + (val >> 8)&0xff, + (val )&0xff); + return string(tmp); +} + + +string makeHexDump(const string& str) +{ + char tmp[5]; + string ret; + ret.reserve((int)(str.size()*2.2)); + + for(string::size_type n=0;n& rrs) +{ + vector::iterator first, second; + for(first=rrs.begin();first!=rrs.end();++first) + if(first->dr.d_place==DNSResourceRecord::ANSWER && first->dr.d_type != QType::CNAME) // CNAME must come first + break; + for(second=first;second!=rrs.end();++second) + if(second->dr.d_place!=DNSResourceRecord::ANSWER) + break; + + if(second-first > 1) + random_shuffle(first,second); + + // now shuffle the additional records + for(first=second;first!=rrs.end();++first) + if(first->dr.d_place==DNSResourceRecord::ADDITIONAL && first->dr.d_type != QType::CNAME) // CNAME must come first + break; + for(second=first;second!=rrs.end();++second) + if(second->dr.d_place!=DNSResourceRecord::ADDITIONAL) + break; + + if(second-first>1) + random_shuffle(first,second); + + // we don't shuffle the rest +} + + +// shuffle, maintaining some semblance of order +void shuffle(vector& rrs) +{ + vector::iterator first, second; + for(first=rrs.begin();first!=rrs.end();++first) + if(first->d_place==DNSResourceRecord::ANSWER && first->d_type != QType::CNAME) // CNAME must come first + break; + for(second=first;second!=rrs.end();++second) + if(second->d_place!=DNSResourceRecord::ANSWER || second->d_type == QType::RRSIG) // leave RRSIGs at the end + break; + + if(second-first>1) + random_shuffle(first,second); + + // now shuffle the additional records + for(first=second;first!=rrs.end();++first) + if(first->d_place==DNSResourceRecord::ADDITIONAL && first->d_type != QType::CNAME) // CNAME must come first + break; + for(second=first; second!=rrs.end(); ++second) + if(second->d_place!=DNSResourceRecord::ADDITIONAL) + break; + + if(second-first>1) + random_shuffle(first,second); + + // we don't shuffle the rest +} + +static uint16_t mapTypesToOrder(uint16_t type) +{ + if(type == QType::CNAME) + return 0; + if(type == QType::RRSIG) + return 65535; + else + return 1; +} + +// make sure rrs is sorted in d_place order to avoid surprises later +// then shuffle the parts that desire shuffling +void orderAndShuffle(vector& rrs) +{ + std::stable_sort(rrs.begin(), rrs.end(), [](const DNSRecord&a, const DNSRecord& b) { + return std::make_tuple(a.d_place, mapTypesToOrder(a.d_type)) < std::make_tuple(b.d_place, mapTypesToOrder(b.d_type)); + }); + shuffle(rrs); +} + +void normalizeTV(struct timeval& tv) +{ + if(tv.tv_usec > 1000000) { + ++tv.tv_sec; + tv.tv_usec-=1000000; + } + else if(tv.tv_usec < 0) { + --tv.tv_sec; + tv.tv_usec+=1000000; + } +} + +const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs) +{ + struct timeval ret; + ret.tv_sec=lhs.tv_sec + rhs.tv_sec; + ret.tv_usec=lhs.tv_usec + rhs.tv_usec; + normalizeTV(ret); + return ret; +} + +const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs) +{ + struct timeval ret; + ret.tv_sec=lhs.tv_sec - rhs.tv_sec; + ret.tv_usec=lhs.tv_usec - rhs.tv_usec; + normalizeTV(ret); + return ret; +} + +pair splitField(const string& inp, char sepa) +{ + pair ret; + string::size_type cpos=inp.find(sepa); + if(cpos==string::npos) + ret.first=inp; + else { + ret.first=inp.substr(0, cpos); + ret.second=inp.substr(cpos+1); + } + return ret; +} + +int logFacilityToLOG(unsigned int facility) +{ + switch(facility) { + case 0: + return LOG_LOCAL0; + case 1: + return(LOG_LOCAL1); + case 2: + return(LOG_LOCAL2); + case 3: + return(LOG_LOCAL3); + case 4: + return(LOG_LOCAL4); + case 5: + return(LOG_LOCAL5); + case 6: + return(LOG_LOCAL6); + case 7: + return(LOG_LOCAL7); + default: + return -1; + } +} + +string stripDot(const string& dom) +{ + if(dom.empty()) + return dom; + + if(dom[dom.size()-1]!='.') + return dom; + + return dom.substr(0,dom.size()-1); +} + + + +int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret) +{ + if(addr.empty()) + return -1; + string ourAddr(addr); + bool portSet = false; + unsigned int port; + if(addr[0]=='[') { // [::]:53 style address + string::size_type pos = addr.find(']'); + if(pos == string::npos) + return -1; + ourAddr.assign(addr.c_str() + 1, pos-1); + if (pos + 1 != addr.size()) { // complete after ], no port specified + if (pos + 2 > addr.size() || addr[pos+1]!=':') + return -1; + try { + port = pdns_stou(addr.substr(pos+2)); + portSet = true; + } + catch(const std::out_of_range&) { + return -1; + } + } + } + ret->sin6_scope_id=0; + ret->sin6_family=AF_INET6; + + if(inet_pton(AF_INET6, ourAddr.c_str(), (void*)&ret->sin6_addr) != 1) { + struct addrinfo* res; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + + int error; + // getaddrinfo has anomalous return codes, anything nonzero is an error, positive or negative + if((error=getaddrinfo(ourAddr.c_str(), 0, &hints, &res))) { + return -1; + } + + memcpy(ret, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + } + + if(portSet) { + if(port > 65535) + return -1; + + ret->sin6_port = htons(port); + } + + return 0; +} + +int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret) +{ + if(str.empty()) { + return -1; + } + struct in_addr inp; + + string::size_type pos = str.find(':'); + if(pos == string::npos) { // no port specified, not touching the port + if(inet_aton(str.c_str(), &inp)) { + ret->sin_addr.s_addr=inp.s_addr; + return 0; + } + return -1; + } + if(!*(str.c_str() + pos + 1)) // trailing : + return -1; + + char *eptr = (char*)str.c_str() + str.size(); + int port = strtol(str.c_str() + pos + 1, &eptr, 10); + if (port < 0 || port > 65535) + return -1; + + if(*eptr) + return -1; + + ret->sin_port = htons(port); + if(inet_aton(str.substr(0, pos).c_str(), &inp)) { + ret->sin_addr.s_addr=inp.s_addr; + return 0; + } + return -1; +} + +int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret) +{ + if (path.empty()) + return -1; + + memset(ret, 0, sizeof(struct sockaddr_un)); + ret->sun_family = AF_UNIX; + if (path.length() >= sizeof(ret->sun_path)) + return -1; + + path.copy(ret->sun_path, sizeof(ret->sun_path), 0); + return 0; +} + +//! read a line of text from a FILE* to a std::string, returns false on 'no data' +bool stringfgets(FILE* fp, std::string& line) +{ + char buffer[1024]; + line.clear(); + + do { + if(!fgets(buffer, sizeof(buffer), fp)) + return !line.empty(); + + line.append(buffer); + } while(!strchr(buffer, '\n')); + return true; +} + +bool readFileIfThere(const char* fname, std::string* line) +{ + line->clear(); + auto fp = std::unique_ptr(fopen(fname, "r"), fclose); + if(!fp) + return false; + stringfgets(fp.get(), *line); + fp.reset(); + + return true; +} + +Regex::Regex(const string &expr) +{ + if(regcomp(&d_preg, expr.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED)) + throw PDNSException("Regular expression did not compile"); +} + +// if you end up here because valgrind told you were are doing something wrong +// with msgh->msg_controllen, please refer to https://github.com/PowerDNS/pdns/pull/3962 +// first. +void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex) +{ + struct cmsghdr *cmsg = NULL; + + if(source->sin4.sin_family == AF_INET6) { + struct in6_pktinfo *pkt; + + msgh->msg_control = cmsgbuf; + msgh->msg_controllen = CMSG_SPACE(sizeof(*pkt)); + + cmsg = CMSG_FIRSTHDR(msgh); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt)); + + pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg); + // Include the padding to stop valgrind complaining about passing uninitialized data + memset(pkt, 0, CMSG_SPACE(sizeof(*pkt))); + pkt->ipi6_addr = source->sin6.sin6_addr; + pkt->ipi6_ifindex = itfIndex; + } + else { +#if defined(IP_PKTINFO) + struct in_pktinfo *pkt; + + msgh->msg_control = cmsgbuf; + msgh->msg_controllen = CMSG_SPACE(sizeof(*pkt)); + + cmsg = CMSG_FIRSTHDR(msgh); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt)); + + pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); + // Include the padding to stop valgrind complaining about passing uninitialized data + memset(pkt, 0, CMSG_SPACE(sizeof(*pkt))); + pkt->ipi_spec_dst = source->sin4.sin_addr; + pkt->ipi_ifindex = itfIndex; +#elif defined(IP_SENDSRCADDR) + struct in_addr *in; + + msgh->msg_control = cmsgbuf; + msgh->msg_controllen = CMSG_SPACE(sizeof(*in)); + + cmsg = CMSG_FIRSTHDR(msgh); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(*in)); + + // Include the padding to stop valgrind complaining about passing uninitialized data + in = (struct in_addr *) CMSG_DATA(cmsg); + memset(in, 0, CMSG_SPACE(sizeof(*in))); + *in = source->sin4.sin_addr; +#endif + } +} + +unsigned int getFilenumLimit(bool hardOrSoft) +{ + struct rlimit rlim; + if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Requesting number of available file descriptors"); + return hardOrSoft ? rlim.rlim_max : rlim.rlim_cur; +} + +void setFilenumLimit(unsigned int lim) +{ + struct rlimit rlim; + + if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Requesting number of available file descriptors"); + rlim.rlim_cur=lim; + if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) + unixDie("Setting number of available file descriptors"); +} + +#define burtlemix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t initval) +{ + uint32_t a,b,c,len; + + /* Set up the internal state */ + len = length; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = initval; /* the previous hash value */ + + /*---------------------------------------- handle most of the key */ + while (len >= 12) { + a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24)); + b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24)); + c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24)); + burtlemix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) { /* all the case statements fall through */ + case 11: c+=((uint32_t)k[10]<<24); + case 10: c+=((uint32_t)k[9]<<16); + case 9 : c+=((uint32_t)k[8]<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((uint32_t)k[7]<<24); + case 7 : b+=((uint32_t)k[6]<<16); + case 6 : b+=((uint32_t)k[5]<<8); + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3]<<24); + case 3 : a+=((uint32_t)k[2]<<16); + case 2 : a+=((uint32_t)k[1]<<8); + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + burtlemix(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} + +uint32_t burtleCI(const unsigned char* k, uint32_t length, uint32_t initval) +{ + uint32_t a,b,c,len; + + /* Set up the internal state */ + len = length; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = initval; /* the previous hash value */ + + /*---------------------------------------- handle most of the key */ + while (len >= 12) { + a += (dns_tolower(k[0]) +((uint32_t)dns_tolower(k[1])<<8) +((uint32_t)dns_tolower(k[2])<<16) +((uint32_t)dns_tolower(k[3])<<24)); + b += (dns_tolower(k[4]) +((uint32_t)dns_tolower(k[5])<<8) +((uint32_t)dns_tolower(k[6])<<16) +((uint32_t)dns_tolower(k[7])<<24)); + c += (dns_tolower(k[8]) +((uint32_t)dns_tolower(k[9])<<8) +((uint32_t)dns_tolower(k[10])<<16)+((uint32_t)dns_tolower(k[11])<<24)); + burtlemix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) { /* all the case statements fall through */ + case 11: c+=((uint32_t)dns_tolower(k[10])<<24); + case 10: c+=((uint32_t)dns_tolower(k[9])<<16); + case 9 : c+=((uint32_t)dns_tolower(k[8])<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((uint32_t)dns_tolower(k[7])<<24); + case 7 : b+=((uint32_t)dns_tolower(k[6])<<16); + case 6 : b+=((uint32_t)dns_tolower(k[5])<<8); + case 5 : b+=dns_tolower(k[4]); + case 4 : a+=((uint32_t)dns_tolower(k[3])<<24); + case 3 : a+=((uint32_t)dns_tolower(k[2])<<16); + case 2 : a+=((uint32_t)dns_tolower(k[1])<<8); + case 1 : a+=dns_tolower(k[0]); + /* case 0: nothing left to add */ + } + burtlemix(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} + + +bool setSocketTimestamps(int fd) +{ +#ifdef SO_TIMESTAMP + int on=1; + return setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, (char*)&on, sizeof(on)) == 0; +#else + return true; // we pretend this happened. +#endif +} + +bool setTCPNoDelay(int sock) +{ + int flag = 1; + return setsockopt(sock, /* socket affected */ + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (char *) &flag, /* the cast is historical cruft */ + sizeof(flag)) == 0; /* length of option value */ +} + + +bool setNonBlocking(int sock) +{ + int flags=fcntl(sock,F_GETFL,0); + if(flags<0 || fcntl(sock, F_SETFL,flags|O_NONBLOCK) <0) + return false; + return true; +} + +bool setBlocking(int sock) +{ + int flags=fcntl(sock,F_GETFL,0); + if(flags<0 || fcntl(sock, F_SETFL,flags&(~O_NONBLOCK)) <0) + return false; + return true; +} + +bool setReuseAddr(int sock) +{ + int tmp = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, static_cast(sizeof tmp))<0) + throw PDNSException(string("Setsockopt failed: ")+strerror(errno)); + return true; +} + +bool isNonBlocking(int sock) +{ + int flags=fcntl(sock,F_GETFL,0); + return flags & O_NONBLOCK; +} + +bool setReceiveSocketErrors(int sock, int af) +{ +#ifdef __linux__ + int tmp = 1, ret; + if (af == AF_INET) { + ret = setsockopt(sock, IPPROTO_IP, IP_RECVERR, &tmp, sizeof(tmp)); + } else { + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVERR, &tmp, sizeof(tmp)); + } + if (ret < 0) { + throw PDNSException(string("Setsockopt failed: ") + strerror(errno)); + } +#endif + return true; +} + +// Closes a socket. +int closesocket( int socket ) +{ + int ret=::close(socket); + if(ret < 0 && errno == ECONNRESET) // see ticket 192, odd BSD behaviour + return 0; + if(ret < 0) + throw PDNSException("Error closing socket: "+stringerror()); + return ret; +} + +bool setCloseOnExec(int sock) +{ + int flags=fcntl(sock,F_GETFD,0); + if(flags<0 || fcntl(sock, F_SETFD,flags|FD_CLOEXEC) <0) + return false; + return true; +} + +string getMACAddress(const ComboAddress& ca) +{ + string ret; +#ifdef __linux__ + ifstream ifs("/proc/net/arp"); + if(!ifs) + return ret; + string line; + string match=ca.toString()+' '; + while(getline(ifs, line)) { + if(boost::starts_with(line, match)) { + vector parts; + stringtok(parts, line, " \n\t\r"); + if(parts.size() < 4) + return ret; + unsigned int tmp[6]; + sscanf(parts[3].c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5); + for(int i = 0 ; i< 6 ; ++i) + ret.append(1, (char)tmp[i]); + return ret; + } + } +#endif + return ret; +} + +uint64_t udpErrorStats(const std::string& str) +{ +#ifdef __linux__ + ifstream ifs("/proc/net/snmp"); + if(!ifs) + return 0; + string line; + vector parts; + while(getline(ifs,line)) { + if(boost::starts_with(line, "Udp: ") && isdigit(line[5])) { + stringtok(parts, line, " \n\t\r"); + if(parts.size() < 7) + break; + if(str=="udp-rcvbuf-errors") + return std::stoull(parts[5]); + else if(str=="udp-sndbuf-errors") + return std::stoull(parts[6]); + else if(str=="udp-noport-errors") + return std::stoull(parts[2]); + else if(str=="udp-in-errors") + return std::stoull(parts[3]); + else + return 0; + } + } +#endif + return 0; +} + +bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum) +{ + if (algoName == DNSName("hmac-md5.sig-alg.reg.int") || algoName == DNSName("hmac-md5")) + algoEnum = TSIG_MD5; + else if (algoName == DNSName("hmac-sha1")) + algoEnum = TSIG_SHA1; + else if (algoName == DNSName("hmac-sha224")) + algoEnum = TSIG_SHA224; + else if (algoName == DNSName("hmac-sha256")) + algoEnum = TSIG_SHA256; + else if (algoName == DNSName("hmac-sha384")) + algoEnum = TSIG_SHA384; + else if (algoName == DNSName("hmac-sha512")) + algoEnum = TSIG_SHA512; + else if (algoName == DNSName("gss-tsig")) + algoEnum = TSIG_GSS; + else { + return false; + } + return true; +} + +DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum) +{ + switch(algoEnum) { + case TSIG_MD5: return DNSName("hmac-md5.sig-alg.reg.int."); + case TSIG_SHA1: return DNSName("hmac-sha1."); + case TSIG_SHA224: return DNSName("hmac-sha224."); + case TSIG_SHA256: return DNSName("hmac-sha256."); + case TSIG_SHA384: return DNSName("hmac-sha384."); + case TSIG_SHA512: return DNSName("hmac-sha512."); + case TSIG_GSS: return DNSName("gss-tsig."); + } + throw PDNSException("getTSIGAlgoName does not understand given algorithm, please fix!"); +} + +uint64_t getOpenFileDescriptors(const std::string&) +{ +#ifdef __linux__ + DIR* dirhdl=opendir(("/proc/"+std::to_string(getpid())+"/fd/").c_str()); + if(!dirhdl) + return 0; + + struct dirent *entry; + int ret=0; + while((entry = readdir(dirhdl))) { + uint32_t num; + try { + num = pdns_stou(entry->d_name); + } catch (...) { + continue; // was not a number. + } + if(std::to_string(num) == entry->d_name) + ret++; + } + closedir(dirhdl); + return ret; + +#else + return 0; +#endif +} + +uint64_t getRealMemoryUsage(const std::string&) +{ +#ifdef __linux__ + ifstream ifs("/proc/self/statm"); + if(!ifs) + return 0; + + uint64_t size, resident, shared, text, lib, data; + ifs >> size >> resident >> shared >> text >> lib >> data; + + return data * getpagesize(); +#else + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) != 0) + return 0; + return ru.ru_maxrss * 1024; +#endif +} + + +uint64_t getSpecialMemoryUsage(const std::string&) +{ +#ifdef __linux__ + ifstream ifs("/proc/self/smaps"); + if(!ifs) + return 0; + string line; + uint64_t bytes=0; + string header("Private_Dirty:"); + while(getline(ifs, line)) { + if(boost::starts_with(line, header)) { + bytes += std::stoull(line.substr(header.length() + 1))*1024; + } + } + return bytes; +#else + return 0; +#endif +} + +uint64_t getCPUTimeUser(const std::string&) +{ + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000); +} + +uint64_t getCPUTimeSystem(const std::string&) +{ + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000); +} + +double DiffTime(const struct timespec& first, const struct timespec& second) +{ + int seconds=second.tv_sec - first.tv_sec; + int nseconds=second.tv_nsec - first.tv_nsec; + + if(nseconds < 0) { + seconds-=1; + nseconds+=1000000000; + } + return seconds + nseconds/1000000000.0; +} + +double DiffTime(const struct timeval& first, const struct timeval& second) +{ + int seconds=second.tv_sec - first.tv_sec; + int useconds=second.tv_usec - first.tv_usec; + + if(useconds < 0) { + seconds-=1; + useconds+=1000000; + } + return seconds + useconds/1000000.0; +} + +uid_t strToUID(const string &str) +{ + uid_t result = 0; + const char * cstr = str.c_str(); + struct passwd * pwd = getpwnam(cstr); + + if (pwd == NULL) { + long long val; + + try { + val = stoll(str); + } + catch(std::exception& e) { + throw runtime_error((boost::format("Error: Unable to parse user ID %s") % cstr).str() ); + } + + if (val < std::numeric_limits::min() || val > std::numeric_limits::max()) { + throw runtime_error((boost::format("Error: Unable to parse user ID %s") % cstr).str() ); + } + + result = static_cast(val); + } + else { + result = pwd->pw_uid; + } + + return result; +} + +gid_t strToGID(const string &str) +{ + gid_t result = 0; + const char * cstr = str.c_str(); + struct group * grp = getgrnam(cstr); + + if (grp == NULL) { + long long val; + + try { + val = stoll(str); + } + catch(std::exception& e) { + throw runtime_error((boost::format("Error: Unable to parse group ID %s") % cstr).str() ); + } + + if (val < std::numeric_limits::min() || val > std::numeric_limits::max()) { + throw runtime_error((boost::format("Error: Unable to parse group ID %s") % cstr).str() ); + } + + result = static_cast(val); + } + else { + result = grp->gr_gid; + } + + return result; +} + +unsigned int pdns_stou(const std::string& str, size_t * idx, int base) +{ + if (str.empty()) return 0; // compatibility + unsigned long result; + try { + result = std::stoul(str, idx, base); + } + catch(std::invalid_argument& e) { + throw std::invalid_argument(string(e.what()) + "; (invalid argument during std::stoul); data was \""+str+"\""); + } + catch(std::out_of_range& e) { + throw std::out_of_range(string(e.what()) + "; (out of range during std::stoul); data was \""+str+"\""); + } + if (result > std::numeric_limits::max()) { + throw std::out_of_range("stoul returned result out of unsigned int range; data was \""+str+"\""); + } + return static_cast(result); +} + +bool isSettingThreadCPUAffinitySupported() +{ +#ifdef HAVE_PTHREAD_SETAFFINITY_NP + return true; +#else + return false; +#endif +} + +int mapThreadToCPUList(pthread_t tid, const std::set& cpus) +{ +#ifdef HAVE_PTHREAD_SETAFFINITY_NP +# ifdef __NetBSD__ + cpuset_t *cpuset; + cpuset = cpuset_create(); + for (const auto cpuID : cpus) { + cpuset_set(cpuID, cpuset); + } + + return pthread_setaffinity_np(tid, + cpuset_size(cpuset), + cpuset); +# else +# ifdef __FreeBSD__ +# define cpu_set_t cpuset_t +# endif + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + for (const auto cpuID : cpus) { + CPU_SET(cpuID, &cpuset); + } + + return pthread_setaffinity_np(tid, + sizeof(cpuset), + &cpuset); +# endif +#else + return ENOSYS; +#endif /* HAVE_PTHREAD_SETAFFINITY_NP */ +} + +std::vector getResolvers(const std::string& resolvConfPath) +{ + std::vector results; + + ifstream ifs(resolvConfPath); + if (!ifs) { + return results; + } + + string line; + while(std::getline(ifs, line)) { + boost::trim_right_if(line, is_any_of(" \r\n\x1a")); + boost::trim_left(line); // leading spaces, let's be nice + + string::size_type tpos = line.find_first_of(";#"); + if (tpos != string::npos) { + line.resize(tpos); + } + + if (boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { + vector parts; + stringtok(parts, line, " \t,"); // be REALLY nice + for(vector::const_iterator iter = parts.begin() + 1; iter != parts.end(); ++iter) { + try { + results.emplace_back(*iter, 53); + } + catch(...) + { + } + } + } + } + + return results; +} + +size_t getPipeBufferSize(int fd) +{ +#ifdef F_GETPIPE_SZ + int res = fcntl(fd, F_GETPIPE_SZ); + if (res == -1) { + return 0; + } + return res; +#else + errno = ENOSYS; + return 0; +#endif /* F_GETPIPE_SZ */ +} + +bool setPipeBufferSize(int fd, size_t size) +{ +#ifdef F_SETPIPE_SZ + if (size > std::numeric_limits::max()) { + errno = EINVAL; + return false; + } + int newSize = static_cast(size); + int res = fcntl(fd, F_SETPIPE_SZ, newSize); + if (res == -1) { + return false; + } + return true; +#else + errno = ENOSYS; + return false; +#endif /* F_SETPIPE_SZ */ +} diff --git a/pdns/misc.hh b/pdns/misc.hh new file mode 100644 index 0000000..ee255e9 --- /dev/null +++ b/pdns/misc.hh @@ -0,0 +1,605 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::boost::multi_index; + +#include "dns.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" +#include "dnsname.hh" + +typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum; + +string nowTime(); +const string unquotify(const string &item); +string humanDuration(time_t passed); +bool stripDomainSuffix(string *qname, const string &domain); +void stripLine(string &line); +string getHostname(); +string urlEncode(const string &text); +int waitForData(int fd, int seconds, int useconds=0); +int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd); +int waitForMultiData(const set& fds, const int seconds, const int useconds, int* fd); +int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr); +uint16_t getShort(const unsigned char *p); +uint16_t getShort(const char *p); +uint32_t getLong(const unsigned char *p); +uint32_t getLong(const char *p); +bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum); +DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum); + +int logFacilityToLOG(unsigned int facility); + +struct ServiceTuple +{ + string host; + uint16_t port; +}; +void parseService(const string &descr, ServiceTuple &st); + +template +void +stringtok (Container &container, string const &in, + const char * const delimiters = " \t\n") +{ + const string::size_type len = in.length(); + string::size_type i = 0; + + while (i bool rfc1982LessThan(T a, T b) +{ + return ((signed)(a - b)) < 0; +} + +// fills container with ranges, so {posbegin,posend} +template +void +vstringtok (Container &container, string const &in, + const char * const delimiters = " \t\n") +{ + const string::size_type len = in.length(); + string::size_type i = 0; + + while (i& rrs); +void shuffle(vector& rrs); + +void orderAndShuffle(vector& rrs); + +void normalizeTV(struct timeval& tv); +const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs); +const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs); +inline float makeFloat(const struct timeval& tv) +{ + return tv.tv_sec + tv.tv_usec/1000000.0f; +} + +inline bool operator<(const struct timeval& lhs, const struct timeval& rhs) +{ + return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec); +} + +inline bool operator<(const struct timespec& lhs, const struct timespec& rhs) +{ + return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec); +} + + +inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure)); +inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) +{ + const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str(); + const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length(); + while(aPtr != aEptr && bPtr != bEptr) { + if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr))) + return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0; + aPtr++; + bPtr++; + } + if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length) + return false; + return aPtr == aEptr; // true if first string was shorter +} + +inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure)); +inline bool pdns_iequals(const std::string& a, const std::string& b) +{ + if (a.length() != b.length()) + return false; + + const char *aPtr = a.c_str(), *bPtr = b.c_str(); + const char *aEptr = aPtr + a.length(); + while(aPtr != aEptr) { + if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr))) + return false; + aPtr++; + bPtr++; + } + return true; +} + +inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure)); +inline bool pdns_iequals_ch(const char a, const char b) +{ + if ((a != b) && (dns_tolower(a) != dns_tolower(b))) + return false; + + return true; +} + + +typedef unsigned long AtomicCounterInner; +typedef std::atomic AtomicCounter ; + +// FIXME400 this should probably go? +struct CIStringCompare: public std::binary_function +{ + bool operator()(const string& a, const string& b) const + { + return pdns_ilexicographical_compare(a, b); + } +}; + +struct CIStringComparePOSIX +{ + bool operator() (const std::string& lhs, const std::string& rhs) + { + std::string::const_iterator a,b; + const std::locale &loc = std::locale("POSIX"); + a=lhs.begin();b=rhs.begin(); + while(a!=lhs.end()) { + if (b==rhs.end() || std::tolower(*b,loc), pair, bool> +{ + bool operator()(const pair& a, const pair& b) const + { + if(pdns_ilexicographical_compare(a.first, b.first)) + return true; + if(pdns_ilexicographical_compare(b.first, a.first)) + return false; + return a.second < b.second; + } +}; + +inline size_t pdns_ci_find(const string& haystack, const string& needle) +{ + string::const_iterator it = std::search(haystack.begin(), haystack.end(), + needle.begin(), needle.end(), pdns_iequals_ch); + if (it == haystack.end()) { + // not found + return string::npos; + } else { + return it - haystack.begin(); + } +} + +pair splitField(const string& inp, char sepa); + +inline bool isCanonical(const string& qname) +{ + if(qname.empty()) + return false; + return qname[qname.size()-1]=='.'; +} + +inline DNSName toCanonic(const DNSName& zone, const string& qname) +{ + if(qname.size()==1 && qname[0]=='@') + return zone; + if(isCanonical(qname)) + return DNSName(qname); + return DNSName(qname) += zone; +} + +string stripDot(const string& dom); + +int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret); +int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret); +int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret); +bool stringfgets(FILE* fp, std::string& line); + +template +std::pair +replacing_insert(Index& i,const typename Index::value_type& x) +{ + std::pair res=i.insert(x); + if(!res.second)res.second=i.replace(res.first,x); + return res; +} + +/** very small regex wrapper */ +class Regex +{ +public: + /** constructor that accepts the expression to regex */ + Regex(const string &expr); + + ~Regex() + { + regfree(&d_preg); + } + /** call this to find out if 'line' matches your expression */ + bool match(const string &line) const + { + return regexec(&d_preg,line.c_str(),0,0,0)==0; + } + bool match(const DNSName& name) const + { + return match(name.toStringNoDot()); + } + +private: + regex_t d_preg; +}; + +class SimpleMatch +{ +public: + SimpleMatch(const string &mask, bool caseFold = false): d_mask(mask), d_fold(caseFold) + { + } + + bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend) + { + for(;;++mi) { + if (mi == mend) { + return vi == vend; + } else if (*mi == '?') { + if (vi == vend) return false; + ++vi; + } else if (*mi == '*') { + while(*mi == '*') ++mi; + if (mi == d_mask.end()) return true; + while(vi != vend) { + if (match(mi,mend,vi,vend)) return true; + ++vi; + } + return false; + } else { + if ((mi == mend && vi != vend)|| + (mi != mend && vi == vend)) return false; + if (d_fold) { + if (dns_tolower(*mi) != dns_tolower(*vi)) return false; + } else { + if (*mi != *vi) return false; + } + ++vi; + } + } + } + + bool match(const string& value) { + return match(d_mask.begin(), d_mask.end(), value.begin(), value.end()); + } + + bool match(const DNSName& name) { + return match(name.toStringNoDot()); + } + +private: + string d_mask; + bool d_fold; +}; + +union ComboAddress; +/* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */ +void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex); + +unsigned int getFilenumLimit(bool hardOrSoft=0); +void setFilenumLimit(unsigned int lim); +bool readFileIfThere(const char* fname, std::string* line); +uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t init); +bool setSocketTimestamps(int fd); + +//! Sets the socket into blocking mode. +bool setBlocking( int sock ); + +//! Sets the socket into non-blocking mode. +bool setNonBlocking( int sock ); +bool setTCPNoDelay(int sock); +bool setReuseAddr(int sock); +bool isNonBlocking(int sock); +bool setReceiveSocketErrors(int sock, int af); +int closesocket(int fd); +bool setCloseOnExec(int sock); + +size_t getPipeBufferSize(int fd); +bool setPipeBufferSize(int fd, size_t size); + +uint64_t udpErrorStats(const std::string& str); +uint64_t getRealMemoryUsage(const std::string&); +uint64_t getSpecialMemoryUsage(const std::string&); +uint64_t getOpenFileDescriptors(const std::string&); +uint64_t getCPUTimeUser(const std::string&); +uint64_t getCPUTimeSystem(const std::string&); +std::string getMACAddress(const ComboAddress& ca); +template +std::unique_ptr make_unique(Args&&... args) +{ + return std::unique_ptr(new T(std::forward(args)...)); +} + + +template +const T& defTer(const T& a, const T& b) +{ + return a ? a : b; +} + +template +T valueOrEmpty(const P val) { + if (!val) return T{}; + return T(val); +} + + +// I'm not very OCD, but I appreciate loglines like "processing 1 delta", "processing 2 deltas" :-) +template +const char* addS(Integer siz, typename std::enable_if::value>::type*P=0) +{ + if(!siz || siz > 1) + return "s"; + else return ""; +} + +template +const char* addS(const C& c, typename std::enable_if::value>::type*P=0) +{ + return addS(c.size()); +} + +template +const typename C::value_type::second_type* rplookup(const C& c, const typename C::value_type::first_type& key) +{ + auto fnd = c.find(key); + if(fnd == c.end()) + return 0; + return &fnd->second; +} + +double DiffTime(const struct timespec& first, const struct timespec& second); +double DiffTime(const struct timeval& first, const struct timeval& second); +uid_t strToUID(const string &str); +gid_t strToGID(const string &str); + +unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10); + +bool isSettingThreadCPUAffinitySupported(); +int mapThreadToCPUList(pthread_t tid, const std::set& cpus); + +std::vector getResolvers(const std::string& resolvConfPath); diff --git a/pdns/mplexer.hh b/pdns/mplexer.hh new file mode 100644 index 0000000..927651c --- /dev/null +++ b/pdns/mplexer.hh @@ -0,0 +1,241 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_MPLEXER_HH +#define PDNS_MPLEXER_HH +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::boost::multi_index; + +class FDMultiplexerException : public std::runtime_error +{ +public: + FDMultiplexerException(const std::string& str) : std::runtime_error(str) + {} +}; + + +/** Very simple FD multiplexer, based on callbacks and boost::any parameters + As a special service, this parameter is kept around and can be modified, + allowing for state to be stored inside the multiplexer. + + It has some "interesting" semantics +*/ + +class FDMultiplexer +{ +public: + typedef boost::any funcparam_t; + typedef boost::function< void(int, funcparam_t&) > callbackfunc_t; +protected: + + struct Callback + { + callbackfunc_t d_callback; + mutable funcparam_t d_parameter; + struct timeval d_ttd; + int d_fd; + }; + +public: + FDMultiplexer() : d_inrun(false) + {} + virtual ~FDMultiplexer() + {} + + static FDMultiplexer* getMultiplexerSilent(); + + /* tv will be updated to 'now' before run returns */ + /* timeout is in ms */ + virtual int run(struct timeval* tv, int timeout=500) = 0; + + /* timeout is in ms, 0 will return immediatly, -1 will block until at least one FD is ready */ + virtual void getAvailableFDs(std::vector& fds, int timeout) = 0; + + //! Add an fd to the read watch list - currently an fd can only be on one list at a time! + virtual void addReadFD(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t(), const struct timeval* ttd=nullptr) + { + this->addFD(d_readCallbacks, fd, toDo, parameter, ttd); + } + + //! Add an fd to the write watch list - currently an fd can only be on one list at a time! + virtual void addWriteFD(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t(), const struct timeval* ttd=nullptr) + { + this->addFD(d_writeCallbacks, fd, toDo, parameter, ttd); + } + + //! Remove an fd from the read watch list. You can't call this function on an fd that is closed already! + /** WARNING: references to 'parameter' become invalid after this function! */ + virtual void removeReadFD(int fd) + { + this->removeFD(d_readCallbacks, fd); + } + + //! Remove an fd from the write watch list. You can't call this function on an fd that is closed already! + /** WARNING: references to 'parameter' become invalid after this function! */ + virtual void removeWriteFD(int fd) + { + this->removeFD(d_writeCallbacks, fd); + } + + virtual void setReadTTD(int fd, struct timeval tv, int timeout) + { + const auto& it = d_readCallbacks.find(fd); + if (it == d_readCallbacks.end()) { + throw FDMultiplexerException("attempt to timestamp fd not in the multiplexer"); + } + + auto newEntry = *it; + tv.tv_sec += timeout; + newEntry.d_ttd = tv; + d_readCallbacks.replace(it, newEntry); + } + + virtual void setWriteTTD(int fd, struct timeval tv, int timeout) + { + const auto& it = d_writeCallbacks.find(fd); + if (it == d_writeCallbacks.end()) { + throw FDMultiplexerException("attempt to timestamp fd not in the multiplexer"); + } + + auto newEntry = *it; + tv.tv_sec += timeout; + newEntry.d_ttd = tv; + d_writeCallbacks.replace(it, newEntry); + } + + virtual std::vector > getTimeouts(const struct timeval& tv, bool writes=false) + { + std::vector > ret; + const auto tied = boost::tie(tv.tv_sec, tv.tv_usec); + auto& idx = writes ? d_writeCallbacks.get() : d_readCallbacks.get(); + + for (auto it = idx.begin(); it != idx.end(); ++it) { + if (it->d_ttd.tv_sec == 0 || tied <= boost::tie(it->d_ttd.tv_sec, it->d_ttd.tv_usec)) { + break; + } + ret.push_back(std::make_pair(it->d_fd, it->d_parameter)); + } + + return ret; + } + + typedef FDMultiplexer* getMultiplexer_t(); + typedef std::multimap FDMultiplexermap_t; + + static FDMultiplexermap_t& getMultiplexerMap() + { + static FDMultiplexermap_t theMap; + return theMap; + } + + virtual std::string getName() const = 0; + + size_t getWatchedFDCount(bool writeFDs) const + { + return writeFDs ? d_writeCallbacks.size() : d_readCallbacks.size(); + } + +protected: + struct FDBasedTag {}; + struct TTDOrderedTag {}; + struct ttd_compare + { + /* we want a 0 TTD (no timeout) to come _after_ everything else */ + bool operator() (const struct timeval& lhs, const struct timeval& rhs) const + { + /* special treatment if at least one of the TTD is 0, + normal comparison otherwise */ + if (lhs.tv_sec == 0 && rhs.tv_sec == 0) { + return false; + } + if (lhs.tv_sec == 0 && rhs.tv_sec != 0) { + return false; + } + if (lhs.tv_sec != 0 && rhs.tv_sec == 0) { + return true; + } + + return std::tie(lhs.tv_sec, lhs.tv_usec) < std::tie(rhs.tv_sec, rhs.tv_usec); + } + }; + + typedef multi_index_container< + Callback, + indexed_by < + hashed_unique, + member + >, + ordered_non_unique, + member, + ttd_compare + > + > + > callbackmap_t; + + callbackmap_t d_readCallbacks, d_writeCallbacks; + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr)=0; + virtual void removeFD(callbackmap_t& cbmap, int fd)=0; + bool d_inrun; + callbackmap_t::iterator d_iter; + + void accountingAddFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) + { + Callback cb; + cb.d_fd = fd; + cb.d_callback=toDo; + cb.d_parameter=parameter; + memset(&cb.d_ttd, 0, sizeof(cb.d_ttd)); + if (ttd) { + cb.d_ttd = *ttd; + } + + auto pair = cbmap.insert(cb); + if (!pair.second) { + throw FDMultiplexerException("Tried to add fd "+std::to_string(fd)+ " to multiplexer twice"); + } + } + + void accountingRemoveFD(callbackmap_t& cbmap, int fd) + { + if(!cbmap.erase(fd)) { + throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); + } + } +}; + + +#endif + diff --git a/pdns/mtasker.cc b/pdns/mtasker.cc new file mode 100644 index 0000000..2d01f12 --- /dev/null +++ b/pdns/mtasker.cc @@ -0,0 +1,412 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "mtasker.hh" +#include "misc.hh" +#include +#include + +#ifdef PDNS_USE_VALGRIND +#include +#endif /* PDNS_USE_VALGRIND */ + +/** \page MTasker + Simple system for implementing cooperative multitasking of functions, with + support for waiting on events which can return values. + + \section copyright Copyright and License + MTasker is (c) 2002 - 2009 by bert hubert. It is licensed to you under the terms of the GPL version 2. + + \section overview High level overview + MTasker is designed to support very simple cooperative multitasking to facilitate writing + code that would ordinarily require a statemachine, for which the author does not consider + himself smart enough. + + This class does not perform any magic it only makes calls to makecontext() and swapcontext(). + Getting the details right however is complicated and MTasker does that for you. + + If preemptive multitasking or more advanced concepts such as semaphores, locks or mutexes + are required, the use of POSIX threads is advised. + + MTasker is designed to offer the performance of statemachines while maintaining simple thread semantics. It is not + a replacement for a full threading system. + + \section compatibility Compatibility + MTasker is only guaranteed to work on Linux with glibc 2.2.5 and higher. It does not work on FreeBSD and notably, + not on Red Hat 6.0. It may work on Solaris, please test. + + \section concepts Concepts + + There are two important concepts, the 'kernel' and the 'thread'. Each thread starts out as a function, + which is passed to MTasker::makeThread(), together with a possible argument. + + This function is now free to do whatever it wants, but realise that MTasker implements cooperative + multitasking, which means that the coder has the responsibility of not taking the CPU overly long. + Other threads can only get the CPU if MTasker::yield() is called or if a thread sleeps to wait for an event, + using the MTasker::waitEvent() method. + + \section kernel The Kernel + The Kernel consists of functions that do housekeeping, but also of code that the client coder + can call to report events. A minimal kernel loop looks like this: + \code + for(;;) { + MT.schedule(); + if(MT.noProcesses()) // exit if no processes are left + break; + } + \endcode + + The kernel typically starts from the main() function of your program. New threads are also + created from the kernel. This can also happen before entering the main loop. To start a thread, + the method MTasker::makeThread is provided. + + \section events Events + By default, Events are recognized by an int and their value is also an int. + This can be overridden by specifying the EventKey and EventVal template parameters. + + An event can be a keypress, but also a UDP packet, or a bit of data from a TCP socket. The + sample code provided works with keypresses, but that is just a not very useful example. + + A thread can also wait for an event only for a limited time, and receive a timeout of that + event did not occur within the specified timeframe. + + \section example A simple menu system + \code +MTasker<> MT; + +void menuHandler(void *p) +{ + int num=(int)p; + cout<<"Key handler for key "<int MTasker::waitEvent(EventKey &key, EventVal *val, unsigned int timeoutMsec, struct timeval* now) +{ + if(d_waiters.count(key)) { // there was already an exact same waiter + return -1; + } + + Waiter w; + w.context=std::make_shared(); + w.ttd.tv_sec = 0; w.ttd.tv_usec = 0; + if(timeoutMsec) { + struct timeval increment; + increment.tv_sec = timeoutMsec / 1000; + increment.tv_usec = 1000 * (timeoutMsec % 1000); + if(now) + w.ttd = increment + *now; + else { + struct timeval realnow; + gettimeofday(&realnow, 0); + w.ttd = increment + realnow; + } + } + + w.tid=d_tid; + w.key=key; + + d_waiters.insert(w); +#ifdef MTASKERTIMING + unsigned int diff=d_threads[d_tid].dt.ndiff()/1000; + d_threads[d_tid].totTime+=diff; +#endif + notifyStackSwitchToKernel(); + pdns_swapcontext(*d_waiters.find(key)->context,d_kernel); // 'A' will return here when 'key' has arrived, hands over control to kernel first + notifyStackSwitchDone(); +#ifdef MTASKERTIMING + d_threads[d_tid].dt.start(); +#endif + if(val && d_waitstatus==Answer) + *val=d_waitval; + d_tid=w.tid; + if((char*)&w < d_threads[d_tid].highestStackSeen) { + d_threads[d_tid].highestStackSeen = (char*)&w; + } + key=d_eventkey; + return d_waitstatus; +} + +//! yields control to the kernel or other threads +/** Hands over control to the kernel, allowing other processes to run, or events to arrive */ + +templatevoid MTasker::yield() +{ + d_runQueue.push(d_tid); + notifyStackSwitchToKernel(); + pdns_swapcontext(*d_threads[d_tid].context ,d_kernel); // give control to the kernel + notifyStackSwitchDone(); +} + +//! reports that an event took place for which threads may be waiting +/** From the kernel loop, sendEvent can be called to report that something occurred for which there may be waiters. + \param key Key of the event for which threads may be waiting + \param val If non-zero, pointer to the content of the event + \return Returns -1 in case of error, 0 if there were no waiters, 1 if a thread was woken up. + + WARNING: when passing val as zero, d_waitval is undefined, and hence waitEvent will return undefined! +*/ +templateint MTasker::sendEvent(const EventKey& key, const EventVal* val) +{ + typename waiters_t::iterator waiter=d_waiters.find(key); + + if(waiter == d_waiters.end()) { + // cout<<"Event sent nobody was waiting for!"<tid; // set tid + d_eventkey=waiter->key; // pass waitEvent the exact key it was woken for + auto userspace=std::move(waiter->context); + d_waiters.erase(waiter); // removes the waitpoint + notifyStackSwitch(d_threads[d_tid].startOfStack, d_stacksize); + pdns_swapcontext(d_kernel,*userspace); // swaps back to the above point 'A' + notifyStackSwitchDone(); + return 1; +} + +//! launches a new thread +/** The kernel can call this to make a new thread, which starts at the function start and gets passed the val void pointer. + \param start Pointer to the function which will form the start of the thread + \param val A void pointer that can be used to pass data to the thread +*/ +templatevoid MTasker::makeThread(tfunc_t *start, void* val) +{ + auto uc=std::make_shared(); + + uc->uc_link = &d_kernel; // come back to kernel after dying + uc->uc_stack.resize (d_stacksize+1); +#ifdef PDNS_USE_VALGRIND + uc->valgrind_id = VALGRIND_STACK_REGISTER(&uc->uc_stack[0], + &uc->uc_stack[uc->uc_stack.size()-1]); +#endif /* PDNS_USE_VALGRIND */ + + ++d_threadsCount; + auto& thread = d_threads[d_maxtid]; + auto mt = this; + thread.start = [start, val, mt]() { + char dummy; + mt->d_threads[mt->d_tid].startOfStack = mt->d_threads[mt->d_tid].highestStackSeen = &dummy; + auto const tid = mt->d_tid; + start (val); + mt->d_zombiesQueue.push(tid); + }; + pdns_makecontext (*uc, thread.start); + + thread.context = std::move(uc); + d_runQueue.push(d_maxtid++); // will run at next schedule invocation +} + + +//! needs to be called periodically so threads can run and housekeeping can be performed +/** The kernel should call this function every once in a while. It makes sense + to call this function if you: + - reported an event + - called makeThread + - want to have threads running waitEvent() to get a timeout if enough time passed + + \return Returns if there is more work scheduled and recalling schedule now would be useful + +*/ +templatebool MTasker::schedule(struct timeval* now) +{ + if(!d_runQueue.empty()) { + d_tid=d_runQueue.front(); +#ifdef MTASKERTIMING + d_threads[d_tid].dt.start(); +#endif + notifyStackSwitch(d_threads[d_tid].startOfStack, d_stacksize); + pdns_swapcontext(d_kernel, *d_threads[d_tid].context); + notifyStackSwitchDone(); + + d_runQueue.pop(); + return true; + } + if(!d_zombiesQueue.empty()) { + d_threads.erase(d_zombiesQueue.front()); + --d_threadsCount; + d_zombiesQueue.pop(); + return true; + } + if(!d_waiters.empty()) { + struct timeval rnow; + if(!now) + gettimeofday(&rnow, 0); + else + rnow = *now; + + typedef typename waiters_t::template index::type waiters_by_ttd_index_t; + // waiters_by_ttd_index_t& ttdindex=d_waiters.template get(); + waiters_by_ttd_index_t& ttdindex=boost::multi_index::get(d_waiters); + + for(typename waiters_by_ttd_index_t::iterator i=ttdindex.begin(); i != ttdindex.end(); ) { + if(i->ttd.tv_sec && i->ttd < rnow) { + d_waitstatus=TimeOut; + d_eventkey=i->key; // pass waitEvent the exact key it was woken for + auto uc = i->context; + d_tid = i->tid; + ttdindex.erase(i++); // removes the waitpoint + + notifyStackSwitch(d_threads[d_tid].startOfStack, d_stacksize); + pdns_swapcontext(d_kernel, *uc); // swaps back to the above point 'A' + notifyStackSwitchDone(); + } + else if(i->ttd.tv_sec) + break; + else + ++i; + } + } + return false; +} + +//! returns true if there are no processes +/** Call this to check if no processes are running anymore + \return true if no processes are left + */ +templatebool MTasker::noProcesses() const +{ + return d_threadsCount == 0; +} + +//! returns the number of processes running +/** Call this to perhaps limit activities if too many threads are running + \return number of processes running + */ +templateunsigned int MTasker::numProcesses() const +{ + return d_threadsCount; +} + +//! gives access to the list of Events threads are waiting for +/** The kernel can call this to get a list of Events threads are waiting for. This is very useful + to setup 'select' or 'poll' or 'aio' events needed to satisfy these requests. + getEvents clears the events parameter before filling it. + + \param events Vector which is to be filled with keys threads are waiting for +*/ +templatevoid MTasker::getEvents(std::vector& events) +{ + events.clear(); + for(typename waiters_t::const_iterator i=d_waiters.begin();i!=d_waiters.end();++i) { + events.push_back(i->first); + } +} + +//! Returns the current Thread ID (tid) +/** Processes can call this to get a numerical representation of their current thread ID. + This can be useful for logging purposes. +*/ +templateint MTasker::getTid() const +{ + return d_tid; +} + +//! Returns the maximum stack usage so far of this MThread +templateunsigned int MTasker::getMaxStackUsage() +{ + return d_threads[d_tid].startOfStack - d_threads[d_tid].highestStackSeen; +} + +//! Returns the maximum stack usage so far of this MThread +templateunsigned int MTasker::getUsec() +{ +#ifdef MTASKERTIMING + return d_threads[d_tid].totTime + d_threads[d_tid].dt.ndiff()/1000; +#else + return 0; +#endif +} diff --git a/pdns/named.conf.parsertest b/pdns/named.conf.parsertest new file mode 100644 index 0000000..4d38d22 --- /dev/null +++ b/pdns/named.conf.parsertest @@ -0,0 +1,70 @@ +# this file is used by ../pdns/test-bindparser_cc.cc +# if you change it, please make check! + +options { + directory "./zones/"; + recursion no; + listen-on port 5300 { + 127.0.0.1; + }; + version "Meow!Meow!"; + minimal-responses yes; +}; +zone "example.com"{ + type master; + file "example.com"; +}; + +zone "test.com"{ + type slave; + file "test.com"; + masters { 1.2.3.4:5678; }; +}; + +zone "test.dyndns" { + type garblewarble; + file "test.dyndns"; + allow-update { + 127.0.0.0/8; + }; +}; + +zone "wtest.com"{ + type master; + file "wtest.com"; +}; + +zone "nztest.com"{ + type master; + file "nztest.com"; +}; + +zone "dnssec-parent.com"{ + type master; + file "dnssec-parent.com"; +}; + +zone "delegated.dnssec-parent.com"{ + type master; + file "delegated.dnssec-parent.com"; +}; + +zone "secure-delegated.dnssec-parent.com"{ + type master; + file "secure-delegated.dnssec-parent.com"; +}; + +zone "minimal.com"{ + type master; + file "minimal.com"; +}; + +zone "tsig.com"{ + type master; + file "tsig.com"; +}; + +zone "stest.com"{ + type master; + file "stest.com"; +}; diff --git a/pdns/nameserver.cc b/pdns/nameserver.cc new file mode 100644 index 0000000..5581239 --- /dev/null +++ b/pdns/nameserver.cc @@ -0,0 +1,398 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include +#include +#include +#include +#include +#include +#include +#include "responsestats.hh" + +#include "dns.hh" +#include "dnsbackend.hh" +#include "dnspacket.hh" +#include "nameserver.hh" +#include "distributor.hh" +#include "logger.hh" +#include "arguments.hh" +#include "statbag.hh" + +#include "namespaces.hh" + +extern StatBag S; + +/** \mainpage + PowerDNS is a very versatile nameserver that can answer questions from different backends. To implement your + own backend, see the documentation for the DNSBackend class. + + \section copyright Copyright and License + PowerDNS is (C) 2001-2008 PowerDNS.COM BV. It is distributed according to the terms of the General Public License version 2. + + \section overview High level overview + + The Distributor contains a configurable number of PacketHandler instances, each in its own thread, for connection pooling. + PacketHandler instances are recycled of they let escape an PDNSException. + + The PacketHandler implements the RFC1034 algorithm and converts question packets into DNSBackend queries. + + A DNSBackend is an entity that returns DNSResourceRecord objects in return to explicit questions for domains with a specified QType + + PowerDNS uses the UeberBackend, which hosts DNSBackends. By default it has no DNSBackends within itself, those are loaded + by setting --load=. This way DNSBackend implementations can be kept completely separate, but most aren't. + + If one or more DNSBackends are loaded, the UeberBackend fields the queries to all of them until one answers. + + \section TCP TCP Operations + + The TCP operation runs within a single thread called tcpreceiver(), that also queries the PacketHandler. + + \section Cache Caching + + On its own, this setup is not suitable for high performance operations. A single DNS query can turn into many DNSBackend questions, + each taking many milliseconds to complete. This is why the qthread() first checks the PacketCache to see if an answer is known to a packet + asking this question. If so, the entire Distributor is shunted, and the answer is sent back *directly*, within a few microseconds. + + \section misc Miscellaneous + Configuration details are available via the ArgvMap instance arg. Statistics are created by making calls to the StatBag object called S. + These statistics are made available via the UeberBackend on the same socket that is used for dynamic module commands. + + \section Main Main + The main() of PowerDNS can be found in receiver.cc - start reading there for further insights into the operation of the nameserver +*/ + +vector g_localaddresses; // not static, our unit tests need to poke this + +void UDPNameserver::bindIPv4() +{ + vectorlocals; + stringtok(locals,::arg()["local-address"]," ,"); + int one = 1; + + if(locals.empty()) + throw PDNSException("No local address specified"); + + int s; + for(vector::const_iterator i=locals.begin();i!=locals.end();++i) { + string localname(*i); + ComboAddress locala; + + s=socket(AF_INET,SOCK_DGRAM,0); + + if(s<0) { + g_log< locals; + stringtok(locals,::arg()["local-ipv6"]," ,"); + int one=1; + + if(locals.empty()) + return; + + int s; + for(vector::const_iterator i=locals.begin();i!=locals.end();++i) { + string localname(*i); + + s=socket(AF_INET6,SOCK_DGRAM,0); + if(s<0) { + if( errno == EAFNOSUPPORT ) { + g_log<getString(); + g_rs.submitResponse(*p, true); + + struct msghdr msgh; + struct iovec iov; + char cbuf[256]; + + fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)buffer.c_str(), buffer.length(), &p->d_remote); + + msgh.msg_control=NULL; + if(p->d_anyLocal) { + addCMsgSrcAddr(&msgh, cbuf, p->d_anyLocal.get_ptr(), 0); + } + DLOG(g_log<getRemote() <<" ("<< buffer.length()<<" octets)"< p->getMaxReplyLen()) { + g_log< "<getMaxReplyLen()<<". Question was for "<qdomain<<"|"<qtype.getName()<getSocket(), &msgh, 0) < 0) + g_log< rfds= d_rfds; + + for(auto &pfd : rfds) { + pfd.events = POLLIN; + pfd.revents = 0; + } + + retry:; + + err = poll(&rfds[0], rfds.size(), -1); + if(err < 0) { + if(errno==EINTR) + goto retry; + unixDie("Unable to poll for new UDP events"); + } + + for(auto &pfd : rfds) { + if(pfd.revents & POLLIN) { + sock=pfd.fd; + if((len=recvmsg(sock, &msgh, 0)) < 0 ) { + if(errno != EAGAIN) + g_log<setSocket(sock); + packet->setRemote(&remote); + + ComboAddress dest; + if(HarvestDestinationAddress(&msgh, &dest)) { +// cerr<<"Setting d_anyLocal to '"<d_anyLocal = dest; + } + + struct timeval recvtv; + if(HarvestTimestamp(&msgh, &recvtv)) { + packet->d_dt.setTimeval(recvtv); + } + else + packet->d_dt.set(); // timing + + if(packet->parse(&buffer.at(0), (size_t) len)<0) { + S.inc("corrupt-packets"); + S.ringAccount("remotes-corrupt", packet->d_remote); + + if(!prefilled) + delete packet; + return 0; // unable to parse + } + + return packet; +} diff --git a/pdns/nameserver.hh b/pdns/nameserver.hh new file mode 100644 index 0000000..d9d0419 --- /dev/null +++ b/pdns/nameserver.hh @@ -0,0 +1,109 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef NAMESERVER_HH +#define NAMESERVER_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "statbag.hh" +#include "namespaces.hh" +#include "dnspacket.hh" +#include "responsestats.hh" + +/** This is the main class. It opens a socket on udp port 53 and waits for packets. Those packets can + be retrieved with the receive() member function, which returns a DNSPacket. + + Some sample code in main(): + \code + typedef Distributor DNSDistributor; + DNSDistributor D(6); // the big dispatcher! + + pthread_t qtid, atid; + N=new UDPNameserver; + + pthread_create(&qtid,0,qthread,static_cast(&D)); // receives packets + pthread_create(&atid,0,athread,static_cast(&D)); // sends packets + \endcode + + Code for qthread: + \code + void *qthread(void *p) + { + DNSDistributor *D=static_cast(p); + + DNSPacket *P; + + while((P=N->receive())) // receive a packet + { + D->question(P); // and give to the distributor, they will delete it + } + return 0; + } + + \endcode + +*/ + +#ifdef __linux__ +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif +#endif + +class UDPNameserver +{ +public: + UDPNameserver( bool additional_socket = false ); //!< Opens the socket + DNSPacket *receive(DNSPacket *prefilled, std::string& buffer); //!< call this in a while or for(;;) loop to get packets + void send(DNSPacket *); //!< send a DNSPacket. Will call DNSPacket::truncate() if over 512 bytes + inline bool canReusePort() { +#ifdef SO_REUSEPORT + return d_can_reuseport; +#else + return false; +#endif + }; + +private: + bool d_additional_socket; +#ifdef SO_REUSEPORT + bool d_can_reuseport; +#endif + vector d_sockets; + void bindIPv4(); + void bindIPv6(); + vector d_rfds; +}; + +bool AddressIsUs(const ComboAddress& remote); + +extern ResponseStats g_rs; + +#endif diff --git a/pdns/namespaces.hh b/pdns/namespaces.hh new file mode 100644 index 0000000..565b67d --- /dev/null +++ b/pdns/namespaces.hh @@ -0,0 +1,81 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_NAMESPACES_HH +#define PDNS_NAMESPACES_HH +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; +using std::map; +using std::pair; +using std::make_pair; +using std::runtime_error; +using std::ostringstream; +using std::set; +using std::deque; +using std::cerr; +using std::cout; +using std::clog; +using std::endl; +using std::ifstream; +using std::ofstream; +using std::ostream; +using std::min; // these are a bit scary, everybody uses 'min' +using std::max; +using std::string; + +using boost::tie; +using std::shared_ptr; +using std::unique_ptr; +using boost::shared_array; +using boost::scoped_array; +using boost::tuple; +using boost::format; +using boost::make_tuple; +using boost::optional; +using boost::any_cast; +using boost::any; +using boost::function; +using boost::trim; +using boost::trim_copy; +using boost::trim_left; +using boost::trim_right; +using boost::is_any_of; +using boost::trim_right_copy_if; +using boost::equals; +using boost::ends_with; +using boost::iends_with; + +#endif diff --git a/pdns/notify.cc b/pdns/notify.cc new file mode 100644 index 0000000..1ec0c11 --- /dev/null +++ b/pdns/notify.cc @@ -0,0 +1,171 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "dnsparser.hh" +#include "dns_random.hh" +#include "iputils.hh" +#include + +#include +#include +#include +#include +#include + +#include "mplexer.hh" +#include "statbag.hh" +#include "arguments.hh" +#include "version.hh" +#include "namespaces.hh" +using namespace ::boost::multi_index; +#include "namespaces.hh" + +namespace po = boost::program_options; +po::variables_map g_vm; + +StatBag S; +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +} + +void usage() { + cerr<<"Syntax: pdns_notify IP_ADDRESS/HOSTNAME[:PORT] DOMAIN"< addrs; + ::arg().set("rng")="auto"; + ::arg().set("entropy-source")="/dev/urandom"; + + for(int n=1 ; n < argc; ++n) { + if ((string) argv[n] == "--help") { + usage(); + return EXIT_SUCCESS; + } + + if ((string) argv[n] == "--version") { + cerr<<"notify "< parts; + boost::split(parts, argv[1], [](char c){return c == ':';}); + if (parts.size() == 1) + parts.push_back("domain"); + else if (parts.size() != 2) + throw runtime_error("Invalid hostname:port syntax"); + if (getaddrinfo(parts[0].c_str(), parts[1].c_str(), NULL, &info) < 0) + throw runtime_error("Cannot resolve '" + string(argv[1]) +"'"); + for(auto ptr = info; ptr != NULL; ptr = ptr->ai_next) + addrs.emplace(ComboAddress{ptr->ai_addr, ptr->ai_addrlen}); + } + + for(const auto &addr: addrs) { + if (sock > -1) + (void)close(sock); + sock = socket(addr.sin4.sin_family, SOCK_DGRAM, 0); + if(sock < 0) + throw runtime_error("Creating socket for incoming packets: "+stringerror()); + if(connect(sock, (struct sockaddr*)&addr, addr.getSocklen()) < 0) { + cerr<<"Failed to connect to address "+addr.toStringWithPort()+": "+stringerror()< outpacket; + DNSPacketWriter pw(outpacket, DNSName(argv[2]), QType::SOA, 1, Opcode::Notify); + pw.getHeader()->id = dns_random(UINT16_MAX); + + if(send(sock, &outpacket[0], outpacket.size(), 0) < 0) { + cerr<<"Unable to send notify to "< 0) { + len = recv(sock, buffer, sizeof(buffer), 0); + timeout = false; + break; + } + } + + if(len < 0) { + cerr<<"Unable to receive notification response from "< +#include "dnsparser.hh" +#include "iputils.hh" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dnsrecords.hh" +#include "mplexer.hh" +#include "statbag.hh" + +#include "namespaces.hh" +using namespace ::boost::multi_index; +#include "namespaces.hh" + +namespace po = boost::program_options; +po::variables_map g_vm; + +StatBag S; + +FDMultiplexer* g_fdm; +int g_pdnssocket; +bool g_verbose; + +struct NotificationInFlight +{ + ComboAddress source; + time_t resentTime; + DNSName domain; + uint16_t origID, resentID; + int origSocket; +}; + +typedef map nifs_t; +nifs_t g_nifs; + +void syslogFmt(const boost::format& fmt) +{ + cerr<<"nproxy: "< packet; + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + + pw.startRecord(mdp.d_qname, mdp.d_qtype); + if(mdp.d_qtype == QType::TXT) { + TXTRecordContent trc("\"OK\""); + trc.toPacket(pw); + } + else if(mdp.d_qtype == QType::A) { + ARecordContent arc("1.2.3.4"); + arc.toPacket(pw); + } + pw.commit(); + + if(sendto(fd, &packet[0], packet.size(), 0, (struct sockaddr*)&nif.source, socklen) < 0) { + syslogFmt(boost::format("Unable to send health check response to external nameserver %s - %s") % nif.source.toStringWithPort() % stringerror()); + } + return; + } + + if(mdp.d_header.opcode != Opcode::Notify || mdp.d_qtype != QType::SOA) { + syslogFmt(boost::format("Received non-notification packet for domain '%s' from external nameserver %s") % nif.domain.toString() % nif.source.toStringWithPort()); + return; + } + syslogFmt(boost::format("External notification received for domain '%s' from %s") % nif.domain.toString() % nif.source.toStringWithPort()); + vector outpacket; + DNSPacketWriter pw(outpacket, mdp.d_qname, mdp.d_qtype, 1, Opcode::Notify); + + static uint16_t s_idpool; + pw.getHeader()->id = nif.resentID = s_idpool++; + + if(send(g_pdnssocket, &outpacket[0], outpacket.size(), 0) < 0) { + throw runtime_error("Unable to send notify to PowerDNS: "+stringerror()); + } + nif.resentTime=time(0); + g_nifs[nif.resentID] = nif; + +} +catch(std::exception &e) +{ + syslogFmt(boost::format("Error parsing packet from external nameserver: %s") % e.what()); +} + + +void handleInsideUDPPacket(int fd, boost::any&) +try +{ + char buffer[1500]; + struct NotificationInFlight nif; + /* make sure we report enough room for IPv6 */ + nif.source.sin4.sin_family = AF_INET6; + + socklen_t socklen=nif.source.getSocklen(); + + int len=recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&nif.source, &socklen); + if(!len) + return; + + if(len < 0) + throw runtime_error("reading packet from remote: "+stringerror()); + + string packet(buffer, len); + MOADNSParser mdp(false, packet); + + // cerr<<"Inside notification response for: "<second.resentTime < limit) { + syslogFmt(boost::format("Notification for domain '%s' was sent to inner nameserver, but no response within 10 seconds") % iter->second.domain.toString()); + g_nifs.erase(iter++); + } + else + ++iter; + } +} + +void daemonize(int null_fd); + +void usage(po::options_description &desc) { + cerr<<"nproxy"<(), "IP address of PowerDNS server") + ("chroot", po::value(), "chroot to this directory for additional security") + ("setuid", po::value(), "setuid to this numerical user id") + ("setgid", po::value(), "setgid to this numerical user id") + ("origin-address", po::value()->default_value("::"), "Source address for notifications to PowerDNS") + ("listen-address", po::value >(), "IP addresses to listen on") + ("listen-port", po::value()->default_value(53), "Source port to listen on") + ("daemon,d", po::value()->default_value(true), "operate in the background") + ("verbose,v", "be verbose"); + + po::store(po::command_line_parser(argc, argv).options(desc).run(), g_vm); + po::notify(g_vm); + + if (g_vm.count("help")) { + usage(desc); + return EXIT_SUCCESS; + } + + if (g_vm.count("version")) { + cerr << "nproxy " << VERSION << endl; + return EXIT_SUCCESS; + } + + if(!g_vm.count("powerdns-address")) { + cerr<<"Mandatory setting 'powerdns-address' unset:\n"< addresses; + if(g_vm.count("listen-address")) + addresses=g_vm["listen-address"].as >(); + else + addresses.push_back("::"); + + // create sockets to listen on + + syslogFmt(boost::format("Starting up")); + for(vector::const_iterator address = addresses.begin(); address != addresses.end(); ++address) { + ComboAddress local(*address, g_vm["listen-port"].as()); + int sock = socket(local.sin4.sin_family, SOCK_DGRAM, 0); + if(sock < 0) + throw runtime_error("Creating socket for incoming packets: "+stringerror()); + + if(::bind(sock,(sockaddr*) &local, local.getSocklen()) < 0) + throw runtime_error("Binding socket for incoming packets to '"+ local.toStringWithPort()+"': "+stringerror()); + + g_fdm->addReadFD(sock, handleOutsideUDPPacket); // add to fdmultiplexer for each socket + syslogFmt(boost::format("Listening for external notifications on address %s") % local.toStringWithPort()); + } + + // create socket that talks to inner PowerDNS + ComboAddress originAddress(g_vm["origin-address"].as(), 0); + g_pdnssocket=socket(originAddress.sin4.sin_family, SOCK_DGRAM, 0); + if(g_pdnssocket < 0) + throw runtime_error("Creating socket for packets to PowerDNS: "+stringerror()); + + + if(::bind(g_pdnssocket,(sockaddr*) &originAddress, originAddress.getSocklen()) < 0) + throw runtime_error("Binding local address of inward socket to '"+ originAddress.toStringWithPort()+"': "+stringerror()); + + + ComboAddress pdns(g_vm["powerdns-address"].as(), 53); + if(connect(g_pdnssocket, (struct sockaddr*) &pdns, pdns.getSocklen()) < 0) + throw runtime_error("Failed to connect PowerDNS socket to address "+pdns.toStringWithPort()+": "+stringerror()); + + syslogFmt(boost::format("Sending notifications from %s to internal address %s") % originAddress.toString() % pdns.toStringWithPort()); + + g_fdm->addReadFD(g_pdnssocket, handleInsideUDPPacket); + + int null_fd=open("/dev/null",O_RDWR); /* open stdin */ + if(null_fd < 0) + throw runtime_error("Unable to open /dev/null: "+stringerror()); + + if(g_vm.count("chroot")) { + if(chroot(g_vm["chroot"].as().c_str()) < 0 || chdir("/") < 0) + throw runtime_error("while chrooting to "+g_vm["chroot"].as()); + syslogFmt(boost::format("Changed root to directory '%s'") % g_vm["chroot"].as()); + } + + if(g_vm.count("setgid")) { + if(setgid(g_vm["setgid"].as()) < 0) + throw runtime_error("while changing gid to "+std::to_string(g_vm["setgid"].as())); + syslogFmt(boost::format("Changed gid to %d") % g_vm["setgid"].as()); + if(setgroups(0, NULL) < 0) + throw runtime_error("while dropping supplementary groups"); + } + + if(g_vm.count("setuid")) { + if(setuid(g_vm["setuid"].as()) < 0) + throw runtime_error("while changing uid to "+std::to_string(g_vm["setuid"].as())); + syslogFmt(boost::format("Changed uid to %d") % g_vm["setuid"].as()); + } + + if(g_vm["daemon"].as()) { + syslogFmt(boost::format("Daemonizing")); + daemonize(null_fd); + } + close(null_fd); + syslogFmt(boost::format("Program operational")); + + + // start loop + struct timeval now; + for(;;) { + gettimeofday(&now, 0); + g_fdm->run(&now); + // check for notifications that have been outstanding for more than 10 seconds + expireOldNotifications(); + } +} +catch(boost::program_options::error& e) +{ + syslogFmt(boost::format("Error parsing command line options: %s") % e.what()); +} +catch(std::exception& e) +{ + syslogFmt(boost::format("Fatal: %s") % e.what()); +} +catch(PDNSException& e) +{ + syslogFmt(boost::format("Fatal: %s") % e.reason); +} + +void daemonize(int null_fd) +{ + if(fork()) + exit(0); // bye bye + + setsid(); + + dup2(null_fd,0); /* stdin */ + dup2(null_fd,1); /* stderr */ + dup2(null_fd,2); /* stderr */ +} diff --git a/pdns/nsec3dig.cc b/pdns/nsec3dig.cc new file mode 100644 index 0000000..eb64304 --- /dev/null +++ b/pdns/nsec3dig.cc @@ -0,0 +1,291 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "base32.hh" +#include "dnssecinfra.hh" + + +StatBag S; + +typedef std::pair nsec3; +typedef set nsec3set; + +string nsec3Hash(const DNSName &qname, const string &salt, unsigned int iters) +{ + NSEC3PARAMRecordContent ns3prc; + ns3prc.d_iterations = iters; + ns3prc.d_salt = salt; + return toBase32Hex(hashQNameWithSalt(ns3prc, qname)); +} + +void proveOrDeny(const nsec3set &nsec3s, const DNSName &qname, const string &salt, unsigned int iters, set &proven, set &denied) +{ + string hashed = nsec3Hash(qname, salt, iters); + + // cerr<<"proveOrDeny(.., '"< base && hashed < next) || + (next < base && (hashed < next || hashed > base))) + { + denied.insert(qname); + cout< 5 && strcmp(argv[5], "recurse")==0) + { + recurse=true; + } + + vector packet; + DNSName qname(argv[3]); + DNSPacketWriter pw(packet, qname, DNSRecordContent::TypeToNumber(argv[4])); + + if(recurse) + { + pw.getHeader()->rd=true; + pw.getHeader()->cd=true; + } + + pw.addOpt(2800, 0, EDNSOpts::DNSSECOK); + pw.commit(); + + + ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2])); + Socket sock(dest.sin4.sin_family, SOCK_STREAM); + sock.connect(dest); + uint16_t len; + len = htons(packet.size()); + if(sock.write((char *) &len, 2) != 2) + throw PDNSException("tcp write failed"); + + sock.writen(string(packet.begin(), packet.end())); + + if(sock.read((char *) &len, 2) != 2) + throw PDNSException("tcp read failed"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(n names; + set namesseen; + set namestocheck; + nsec3set nsec3s; + string nsec3salt; + int nsec3iters = 0; + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_type == QType::NSEC3) + { + // cerr<<"got nsec3 ["<first.d_name<<"]"<first.d_content->getZoneRepresentation()<(i->first.d_content); + if (!r) { + continue; + } + // nsec3.insert(new nsec3() + // cerr< parts; + string sname=i->first.d_name.toString(); + boost::split(parts, sname /* FIXME400 */, boost::is_any_of(".")); + nsec3s.insert(make_pair(toLower(parts[0]), toBase32Hex(r->d_nexthash))); + nsec3salt = r->d_salt; + nsec3iters = r->d_iterations; + } + else + { + // cerr<<"namesseen.insert('"<first.d_name<<"')"<first.d_name); + namesseen.insert(i->first.d_name); + } + + if(i->first.d_type == QType::CNAME) + { + namesseen.insert(DNSName(i->first.d_content->getZoneRepresentation())); + } + + cout<first.d_place-1<<"\t"<first.d_name.toString()<<"\tIN\t"<first.d_type); + cout<<"\t"<first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n"; + } + +#if 0 + cerr<<"got "<::const_iterator pos=names.begin(); pos != names.end(); ++pos) { + cerr<<"name: "<<*pos< proven; + set denied; + namesseen.insert(qname); + for(const auto &name: namesseen) + { + DNSName shorter(name); + do { + namestocheck.insert(shorter); + } while(shorter.chopOff()); + } + for(const auto &name: namestocheck) + { + proveOrDeny(nsec3s, name, nsec3salt, nsec3iters, proven, denied); + proveOrDeny(nsec3s, g_wildcarddnsname+name, nsec3salt, nsec3iters, proven, denied); + } + + if(names.count(qname)) + { + cout<<"== qname found in names, investigating NSEC3s in case it's a wildcard"<(type / 256); + + if (window != oldWindow) { + if (oldWindow > -1) { + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); + } + memset(res, 0, sizeof(res)); + oldWindow = window; + } + res[2+bit/8] |= 1 << (7-(bit%8)); + len=1+bit/8; + } + + void finish() + { + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + if (len) { + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); + } + } + +private: + DNSPacketWriter& pw; + /* one byte for the window, + one for the length, + then the maximum of 32 bytes */ + uint8_t res[34]; + int oldWindow{-1}; + int len{0}; + string tmp; +}; + +void NSECBitmap::toPacket(DNSPacketWriter& pw) +{ + NSECBitmapGenerator nbg(pw); + if (d_bitset) { + size_t count = d_bitset->count(); + size_t found = 0; + for(size_t idx = 0; idx < nbTypes && found < count; ++idx){ + if (!d_bitset->test(idx)) { + continue; + } + found++; + nbg.set(idx); + } + } + else { + for (const auto& type : d_set) { + nbg.set(type); + } + } + + nbg.finish(); +} + +void NSECBitmap::fromPacket(PacketReader& pr) +{ + string bitmap; + pr.xfrBlob(bitmap); + + // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left + if(bitmap.empty()) { + return; + } + + if(bitmap.size() < 2) { + throw MOADNSException("NSEC record with impossibly small bitmap"); + } + + for(unsigned int n = 0; n+1 < bitmap.size();) { + unsigned int window=static_cast(bitmap[n++]); + unsigned int blen=static_cast(bitmap[n++]); + + // end if zero padding and ensure packet length + if(window == 0 && blen == 0) { + break; + } + + if(n + blen > bitmap.size()) { + throw MOADNSException("NSEC record with bitmap length > packet length"); + } + + for(unsigned int k=0; k < blen; k++) { + uint8_t val=bitmap[n++]; + for(int bit = 0; bit < 8 ; ++bit , val>>=1) { + if(val & 1) { + set((7-bit) + 8*(k) + 256*window); + } + } + } + } +} + +string NSECBitmap::getZoneRepresentation() const +{ + string ret; + + if (d_bitset) { + size_t count = d_bitset->count(); + size_t found = 0; + for(size_t idx = 0; idx < nbTypes && found < count; ++idx) { + if (!d_bitset->test(idx)) { + continue; + } + found++; + + ret+=" "; + ret+=DNSRecordContent::NumberToType(idx); + } + } + else { + for(const auto& type : d_set) { + ret+=" "; + ret+=DNSRecordContent::NumberToType(type); + } + } + + return ret; +} + +void NSECRecordContent::report(void) +{ + regist(1, 47, &make, &make, "NSEC"); +} + +std::shared_ptr NSECRecordContent::make(const string& content) +{ + return std::make_shared(content); +} + +NSECRecordContent::NSECRecordContent(const string& content, const string& zone) +{ + RecordTextReader rtr(content, DNSName(zone)); + rtr.xfrName(d_next); + + while(!rtr.eof()) { + uint16_t type; + rtr.xfrType(type); + set(type); + } +} + +void NSECRecordContent::toPacket(DNSPacketWriter& pw) +{ + pw.xfrName(d_next); + d_bitmap.toPacket(pw); +} + +std::shared_ptr NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + auto ret=std::make_shared(); + pr.xfrName(ret->d_next); + + ret->d_bitmap.fromPacket(pr); + + return ret; +} + +string NSECRecordContent::getZoneRepresentation(bool noDot) const +{ + string ret; + RecordTextWriter rtw(ret); + rtw.xfrName(d_next); + + return ret + d_bitmap.getZoneRepresentation(); +} + +////// begin of NSEC3 + +void NSEC3RecordContent::report(void) +{ + regist(1, 50, &make, &make, "NSEC3"); +} + +std::shared_ptr NSEC3RecordContent::make(const string& content) +{ + return std::make_shared(content); +} + +NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone) +{ + RecordTextReader rtr(content, DNSName(zone)); + rtr.xfr8BitInt(d_algorithm); + rtr.xfr8BitInt(d_flags); + rtr.xfr16BitInt(d_iterations); + + rtr.xfrHexBlob(d_salt); + rtr.xfrBase32HexBlob(d_nexthash); + + while(!rtr.eof()) { + uint16_t type; + rtr.xfrType(type); + set(type); + } +} + +void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) +{ + pw.xfr8BitInt(d_algorithm); + pw.xfr8BitInt(d_flags); + pw.xfr16BitInt(d_iterations); + pw.xfr8BitInt(d_salt.length()); + pw.xfrBlob(d_salt); + + pw.xfr8BitInt(d_nexthash.length()); + pw.xfrBlob(d_nexthash); + + d_bitmap.toPacket(pw); +} + +std::shared_ptr NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + auto ret=std::make_shared(); + pr.xfr8BitInt(ret->d_algorithm); + pr.xfr8BitInt(ret->d_flags); + pr.xfr16BitInt(ret->d_iterations); + uint8_t len; + pr.xfr8BitInt(len); + pr.xfrBlob(ret->d_salt, len); + + pr.xfr8BitInt(len); + pr.xfrBlob(ret->d_nexthash, len); + + ret->d_bitmap.fromPacket(pr); + return ret; +} + +string NSEC3RecordContent::getZoneRepresentation(bool noDot) const +{ + string ret; + RecordTextWriter rtw(ret); + rtw.xfr8BitInt(d_algorithm); + rtw.xfr8BitInt(d_flags); + rtw.xfr16BitInt(d_iterations); + + rtw.xfrHexBlob(d_salt); + rtw.xfrBase32HexBlob(d_nexthash); + + return ret + d_bitmap.getZoneRepresentation(); +} + + +void NSEC3PARAMRecordContent::report(void) +{ + regist(1, 51, &make, &make, "NSEC3PARAM"); + regist(254, 51, &make, &make, "NSEC3PARAM"); +} + +std::shared_ptr NSEC3PARAMRecordContent::make(const string& content) +{ + return std::make_shared(content); +} + +NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone) +{ + RecordTextReader rtr(content, DNSName(zone)); + rtr.xfr8BitInt(d_algorithm); + rtr.xfr8BitInt(d_flags); + rtr.xfr16BitInt(d_iterations); + rtr.xfrHexBlob(d_salt); +} + +void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw) +{ + pw.xfr8BitInt(d_algorithm); + pw.xfr8BitInt(d_flags); + pw.xfr16BitInt(d_iterations); + pw.xfr8BitInt(d_salt.length()); + // cerr<<"salt: '"< NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + auto ret=std::make_shared(); + pr.xfr8BitInt(ret->d_algorithm); + pr.xfr8BitInt(ret->d_flags); + pr.xfr16BitInt(ret->d_iterations); + uint8_t len; + pr.xfr8BitInt(len); + pr.xfrHexBlob(ret->d_salt, len); + return ret; +} + +string NSEC3PARAMRecordContent::getZoneRepresentation(bool noDot) const +{ + string ret; + RecordTextWriter rtw(ret); + rtw.xfr8BitInt(d_algorithm); + rtw.xfr8BitInt(d_flags); + rtw.xfr16BitInt(d_iterations); + rtw.xfrHexBlob(d_salt); + return ret; +} + diff --git a/pdns/opensslsigners.cc b/pdns/opensslsigners.cc new file mode 100644 index 0000000..694264e --- /dev/null +++ b/pdns/opensslsigners.cc @@ -0,0 +1,1111 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#ifdef HAVE_LIBCRYPTO_ECDSA +#include +#endif +#if defined(HAVE_LIBCRYPTO_ED25519) || defined(HAVE_LIBCRYPTO_ED448) +#include +#endif +#include +#include +#include +#include +#include +#include "opensslsigners.hh" +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" + +#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || defined LIBRESSL_VERSION_NUMBER) +/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */ +static pthread_mutex_t *openssllocks; + +extern "C" { +void openssl_pthreads_locking_callback(int mode, int type, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&(openssllocks[type])); + + }else { + pthread_mutex_unlock(&(openssllocks[type])); + } +} + +unsigned long openssl_pthreads_id_callback() +{ + return (unsigned long)pthread_self(); +} +} + +void openssl_thread_setup() +{ + openssllocks = (pthread_mutex_t*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + + for (int i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_init(&(openssllocks[i]), NULL); + + CRYPTO_set_id_callback(openssl_pthreads_id_callback); + CRYPTO_set_locking_callback(openssl_pthreads_locking_callback); +} + +void openssl_thread_cleanup() +{ + CRYPTO_set_locking_callback(NULL); + + for (int i=0; in; + *e = rsakey->e; + *d = rsakey->d; +} + +static inline int RSA_set0_key(RSA* rsakey, BIGNUM* n, BIGNUM* e, BIGNUM* d) { + if (n) { + BN_clear_free(rsakey->n); + rsakey->n = n; + } + if (e) { + BN_clear_free(rsakey->e); + rsakey->e = e; + } + if (d) { + BN_clear_free(rsakey->d); + rsakey->d = d; + } + return 1; +} + +static inline void RSA_get0_factors(const RSA* rsakey, const BIGNUM** p, const BIGNUM** q) { + *p = rsakey->p; + *q = rsakey->q; +} + +static inline int RSA_set0_factors(RSA* rsakey, BIGNUM* p, BIGNUM* q) { + BN_clear_free(rsakey->p); + rsakey->p = p; + BN_clear_free(rsakey->q); + rsakey->q = q; + return 1; +} + +static inline void RSA_get0_crt_params(const RSA* rsakey, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp) { + *dmp1 = rsakey->dmp1; + *dmq1 = rsakey->dmq1; + *iqmp = rsakey->iqmp; +} + +static inline int RSA_set0_crt_params(RSA* rsakey, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp) { + BN_clear_free(rsakey->dmp1); + rsakey->dmp1 = dmp1; + BN_clear_free(rsakey->dmq1); + rsakey->dmq1 = dmq1; + BN_clear_free(rsakey->iqmp); + rsakey->iqmp = iqmp; + return 1; +} + +#ifdef HAVE_LIBCRYPTO_ECDSA +static inline void ECDSA_SIG_get0(const ECDSA_SIG* signature, const BIGNUM** pr, const BIGNUM** ps) { + *pr = signature->r; + *ps = signature->s; +} + +static inline int ECDSA_SIG_set0(ECDSA_SIG* signature, BIGNUM* pr, BIGNUM* ps) { + BN_clear_free(signature->r); + BN_clear_free(signature->s); + signature->r = pr; + signature->s = ps; + return 1; +} +#endif /* HAVE_LIBCRYPTO_ECDSA */ + +#endif /* !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL */ + +#else +void openssl_thread_setup() {} +void openssl_thread_cleanup() {} +#endif + + +/* seeding PRNG */ + +void openssl_seed() +{ + std::string entropy; + entropy.reserve(1024); + + unsigned int r; + for(int i=0; i<1024; i+=4) { + r=dns_random(0xffffffff); + entropy.append((const char*)&r, 4); + } + + RAND_seed((const unsigned char*)entropy.c_str(), 1024); +} + + +class OpenSSLRSADNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit OpenSSLRSADNSCryptoKeyEngine(unsigned int algo): DNSCryptoKeyEngine(algo), d_key(std::unique_ptr(nullptr, RSA_free)) + { + int ret = RAND_status(); + if (ret != 1) { + throw runtime_error(getName()+" insufficient entropy"); + } + } + + ~OpenSSLRSADNSCryptoKeyEngine() + { + } + + string getName() const override { return "OpenSSL RSA"; } + int getBits() const override { return RSA_size(d_key.get()) << 3; } + + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string hash(const std::string& hash) const override; + std::string sign(const std::string& hash) const override; + bool verify(const std::string& hash, const std::string& signature) const override; + std::string getPubKeyHash() const override; + std::string getPublicKeyString() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + bool checkKey(vector *errorMessages) const override; + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + static int hashSizeToKind(size_t hashSize); + + std::unique_ptr d_key; +}; + + +void OpenSSLRSADNSCryptoKeyEngine::create(unsigned int bits) +{ + // When changing the bitsizes, also edit them in ::checkKey + if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) && (bits < 512 || bits > 4096)) { + /* RFC3110 */ + throw runtime_error(getName()+" RSASHA1 key generation failed for invalid bits size " + std::to_string(bits)); + } + if (d_algorithm == DNSSECKeeper::RSASHA256 && (bits < 512 || bits > 4096)) { + /* RFC5702 */ + throw runtime_error(getName()+" RSASHA256 key generation failed for invalid bits size " + std::to_string(bits)); + } + if (d_algorithm == DNSSECKeeper::RSASHA512 && (bits < 1024 || bits > 4096)) { + /* RFC5702 */ + throw runtime_error(getName()+" RSASHA512 key generation failed for invalid bits size " + std::to_string(bits)); + } + + auto e = std::unique_ptr(BN_new(), BN_clear_free); + if (!e) { + throw runtime_error(getName()+" key generation failed, unable to allocate e"); + } + + /* RSA_F4 is a public exponent value of 65537 */ + int res = BN_set_word(e.get(), RSA_F4); + + if (res == 0) { + throw runtime_error(getName()+" key generation failed while setting e"); + } + + auto key = std::unique_ptr(RSA_new(), RSA_free); + if (!key) { + throw runtime_error(getName()+" allocation of key structure failed"); + } + + res = RSA_generate_key_ex(key.get(), bits, e.get(), nullptr); + if (res == 0) { + throw runtime_error(getName()+" key generation failed"); + } + + d_key = std::move(key); +} + + +DNSCryptoKeyEngine::storvector_t OpenSSLRSADNSCryptoKeyEngine::convertToISCVector() const +{ + storvector_t storvect; + typedef vector > outputs_t; + outputs_t outputs; + const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; + RSA_get0_key(d_key.get(), &n, &e, &d); + RSA_get0_factors(d_key.get(), &p, &q); + RSA_get0_crt_params(d_key.get(), &dmp1, &dmq1, &iqmp); + outputs.push_back(make_pair("Modulus", n)); + outputs.push_back(make_pair("PublicExponent", e)); + outputs.push_back(make_pair("PrivateExponent", d)); + outputs.push_back(make_pair("Prime1", p)); + outputs.push_back(make_pair("Prime2", q)); + outputs.push_back(make_pair("Exponent1", dmp1)); + outputs.push_back(make_pair("Exponent2", dmq1)); + outputs.push_back(make_pair("Coefficient", iqmp)); + + string algorithm=std::to_string(d_algorithm); + switch(d_algorithm) { + case DNSSECKeeper::RSASHA1: + case DNSSECKeeper::RSASHA1NSEC3SHA1: + algorithm += " (RSASHA1)"; + break; + case DNSSECKeeper::RSASHA256: + algorithm += " (RSASHA256)"; + break; + case DNSSECKeeper::RSASHA512: + algorithm += " (RSASHA512)"; + break; + default: + algorithm += " (?)"; + } + storvect.push_back(make_pair("Algorithm", algorithm)); + + for(outputs_t::value_type value : outputs) { + std::string tmp; + tmp.resize(BN_num_bytes(value.second)); + int len = BN_bn2bin(value.second, reinterpret_cast(&tmp.at(0))); + if (len >= 0) { + tmp.resize(len); + storvect.push_back(make_pair(value.first, tmp)); + } + } + + return storvect; +} + + +std::string OpenSSLRSADNSCryptoKeyEngine::hash(const std::string& orig) const +{ + if (d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) { + unsigned char hash[SHA_DIGEST_LENGTH]; + SHA1((unsigned char*) orig.c_str(), orig.length(), hash); + return string((char*) hash, sizeof(hash)); + } + else if (d_algorithm == DNSSECKeeper::RSASHA256) { + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256((unsigned char*) orig.c_str(), orig.length(), hash); + return string((char*) hash, sizeof(hash)); + } + else if (d_algorithm == DNSSECKeeper::RSASHA512) { + unsigned char hash[SHA512_DIGEST_LENGTH]; + SHA512((unsigned char*) orig.c_str(), orig.length(), hash); + return string((char*) hash, sizeof(hash)); + } + + throw runtime_error(getName()+" does not support hash operation for algorithm "+std::to_string(d_algorithm)); +} + +int OpenSSLRSADNSCryptoKeyEngine::hashSizeToKind(const size_t hashSize) +{ + switch(hashSize) { + case SHA_DIGEST_LENGTH: + return NID_sha1; + case SHA256_DIGEST_LENGTH: + return NID_sha256; + case SHA384_DIGEST_LENGTH: + return NID_sha384; + case SHA512_DIGEST_LENGTH: + return NID_sha512; + default: + throw runtime_error("OpenSSL RSA does not handle hash of size " + std::to_string(hashSize)); + } +} + +std::string OpenSSLRSADNSCryptoKeyEngine::sign(const std::string& msg) const +{ + string hash = this->hash(msg); + int hashKind = hashSizeToKind(hash.size()); + std::string signature; + signature.resize(RSA_size(d_key.get())); + unsigned int signatureLen = 0; + + int res = RSA_sign(hashKind, reinterpret_cast(&hash.at(0)), hash.length(), reinterpret_cast(&signature.at(0)), &signatureLen, d_key.get()); + if (res != 1) { + throw runtime_error(getName()+" failed to generate signature"); + } + + signature.resize(signatureLen); + return signature; +} + + +bool OpenSSLRSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + string hash = this->hash(msg); + int hashKind = hashSizeToKind(hash.size()); + + int ret = RSA_verify(hashKind, (const unsigned char*) hash.c_str(), hash.length(), (unsigned char*) signature.c_str(), signature.length(), d_key.get()); + + return (ret == 1); +} + + +std::string OpenSSLRSADNSCryptoKeyEngine::getPubKeyHash() const +{ + const BIGNUM *n, *e, *d; + RSA_get0_key(d_key.get(), &n, &e, &d); + std::vector tmp; + tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n))); + unsigned char hash[SHA_DIGEST_LENGTH]; + SHA_CTX ctx; + + int res = SHA1_Init(&ctx); + + if (res != 1) { + throw runtime_error(getName()+" failed to init hash context for generating the public key hash"); + } + + int len = BN_bn2bin(e, tmp.data()); + res = SHA1_Update(&ctx, tmp.data(), len); + if (res != 1) { + throw runtime_error(getName()+" failed to update hash context for generating the public key hash"); + } + + len = BN_bn2bin(n, tmp.data()); + res = SHA1_Update(&ctx, tmp.data(), len); + if (res != 1) { + throw runtime_error(getName()+" failed to update hash context for generating the public key hash"); + } + + res = SHA1_Final(hash, &ctx); + if (res != 1) { + throw runtime_error(getName()+" failed to finish hash context for generating the public key hash"); + } + + return string((char*) hash, sizeof(hash)); +} + + +std::string OpenSSLRSADNSCryptoKeyEngine::getPublicKeyString() const +{ + const BIGNUM *n, *e, *d; + RSA_get0_key(d_key.get(), &n, &e, &d); + string keystring; + std::string tmp; + tmp.resize(std::max(BN_num_bytes(e), BN_num_bytes(n))); + + int len = BN_bn2bin(e, reinterpret_cast(&tmp.at(0))); + if (len < 255) { + keystring.assign(1, (char) (unsigned int) len); + } else { + keystring.assign(1, 0); + uint16_t tempLen = len; + tempLen = htons(tempLen); + keystring.append((char*)&tempLen, 2); + } + keystring.append(&tmp.at(0), len); + + len = BN_bn2bin(n, reinterpret_cast(&tmp.at(0))); + keystring.append(&tmp.at(0), len); + + return keystring; +} + + +void OpenSSLRSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) +{ + typedef map places_t; + places_t places; + auto key = std::unique_ptr(RSA_new(), RSA_free); + if (!key) { + throw runtime_error(getName()+" allocation of key structure failed"); + } + + BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; + n = BN_new(); + if (n == nullptr) { + throw runtime_error(getName()+" allocation of BIGNUM n failed"); + } + e = BN_new(); + if (e == nullptr) { + BN_clear_free(n); + throw runtime_error(getName()+" allocation of BIGNUM e failed"); + } + d = BN_new(); + if (d == nullptr) { + BN_clear_free(n); + BN_clear_free(e); + throw runtime_error(getName()+" allocation of BIGNUM d failed"); + } + RSA_set0_key(key.get(), n, e, d); + + p = BN_new(); + if (p == nullptr) { + throw runtime_error(getName()+" allocation of BIGNUM p failed"); + } + q = BN_new(); + if (q == nullptr) { + BN_clear_free(p); + throw runtime_error(getName()+" allocation of BIGNUM q failed"); + } + RSA_set0_factors(key.get(), p, q); + + dmp1 = BN_new(); + if (dmp1 == nullptr) { + throw runtime_error(getName()+" allocation of BIGNUM dmp1 failed"); + } + dmq1 = BN_new(); + if (dmq1 == nullptr) { + BN_clear_free(dmp1); + throw runtime_error(getName()+" allocation of BIGNUM dmq1 failed"); + } + iqmp = BN_new(); + if (iqmp == nullptr) { + BN_clear_free(dmq1); + BN_clear_free(dmp1); + throw runtime_error(getName()+" allocation of BIGNUM iqmp failed"); + } + RSA_set0_crt_params(key.get(), dmp1, dmq1, iqmp); + + places["Modulus"]=&n; + places["PublicExponent"]=&e; + places["PrivateExponent"]=&d; + places["Prime1"]=&p; + places["Prime2"]=&q; + places["Exponent1"]=&dmp1; + places["Exponent2"]=&dmq1; + places["Coefficient"]=&iqmp; + + drc.d_algorithm = pdns_stou(stormap["algorithm"]); + + string raw; + for(const places_t::value_type& val : places) { + raw=stormap[toLower(val.first)]; + + if (!val.second) + continue; + + *val.second = BN_bin2bn((unsigned char*) raw.c_str(), raw.length(), *val.second); + if (!*val.second) { + throw runtime_error(getName()+" error loading " + val.first); + } + } + + if (drc.d_algorithm != d_algorithm) { + throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key"); + } + + d_key = std::move(key); +} + +bool OpenSSLRSADNSCryptoKeyEngine::checkKey(vector *errorMessages) const +{ + bool retval = true; + // When changing the bitsizes, also edit them in ::create + if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1 || d_algorithm == DNSSECKeeper::RSASHA256) && (getBits() < 512 || getBits()> 4096)) { + retval = false; + if (errorMessages != nullptr) { + errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 512 and 4096"); + } + } + if (d_algorithm == DNSSECKeeper::RSASHA512 && (getBits() < 1024 || getBits() > 4096)) { + retval = false; + if (errorMessages != nullptr) { + errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 1024 and 4096"); + } + } + if (RSA_check_key(d_key.get()) != 1) { + retval = false; + if (errorMessages != nullptr) { + errorMessages->push_back(ERR_reason_error_string(ERR_get_error())); + } + } + return retval; +} + +void OpenSSLRSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + string exponent, modulus; + const size_t inputLen = input.length(); + const unsigned char* raw = (const unsigned char*)input.c_str(); + + if (inputLen < 1) { + throw runtime_error(getName()+" invalid input size for the public key"); + } + + if (raw[0] != 0) { + const size_t exponentSize = raw[0]; + if (inputLen < (exponentSize + 2)) { + throw runtime_error(getName()+" invalid input size for the public key"); + } + exponent = input.substr(1, exponentSize); + modulus = input.substr(exponentSize + 1); + } else { + if (inputLen < 3) { + throw runtime_error(getName()+" invalid input size for the public key"); + } + const size_t exponentSize = raw[1]*0xff + raw[2]; + if (inputLen < (exponentSize + 4)) { + throw runtime_error(getName()+" invalid input size for the public key"); + } + exponent = input.substr(3, exponentSize); + modulus = input.substr(exponentSize + 3); + } + + auto key = std::unique_ptr(RSA_new(), RSA_free); + if (!key) { + throw runtime_error(getName()+" allocation of key structure failed"); + } + + auto e = std::unique_ptr(BN_bin2bn((unsigned char*)exponent.c_str(), exponent.length(), nullptr), BN_clear_free); + if (!e) { + throw runtime_error(getName()+" error loading e value of public key"); + } + auto n = std::unique_ptr(BN_bin2bn((unsigned char*)modulus.c_str(), modulus.length(), nullptr), BN_clear_free); + if (!n) { + throw runtime_error(getName()+" error loading n value of public key"); + } + + RSA_set0_key(key.get(), n.release(), e.release(), nullptr); + d_key = std::move(key); +} + +#ifdef HAVE_LIBCRYPTO_ECDSA +class OpenSSLECDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit OpenSSLECDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_eckey(std::unique_ptr(EC_KEY_new(), EC_KEY_free)), d_ecgroup(std::unique_ptr(nullptr, EC_GROUP_clear_free)) + { + + int ret = RAND_status(); + if (ret != 1) { + throw runtime_error(getName()+" insufficient entropy"); + } + + if (!d_eckey) { + throw runtime_error(getName()+" allocation of key structure failed"); + } + + if(d_algorithm == 13) { + d_ecgroup = std::unique_ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1), EC_GROUP_clear_free); + d_len = 32; + } else if (d_algorithm == 14) { + d_ecgroup = std::unique_ptr(EC_GROUP_new_by_curve_name(NID_secp384r1), EC_GROUP_clear_free); + d_len = 48; + } else { + throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm)); + } + + if (!d_ecgroup) { + throw runtime_error(getName()+" allocation of group structure failed"); + } + + ret = EC_KEY_set_group(d_eckey.get(), d_ecgroup.get()); + if (ret != 1) { + throw runtime_error(getName()+" setting key group failed"); + } + } + + ~OpenSSLECDSADNSCryptoKeyEngine() + { + } + + string getName() const override { return "OpenSSL ECDSA"; } + int getBits() const override { return d_len << 3; } + + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string hash(const std::string& hash) const override; + std::string sign(const std::string& hash) const override; + bool verify(const std::string& hash, const std::string& signature) const override; + std::string getPubKeyHash() const override; + std::string getPublicKeyString() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + bool checkKey(vector *errorMessages) const override; + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + unsigned int d_len; + + std::unique_ptr d_eckey; + std::unique_ptr d_ecgroup; +}; + + +void OpenSSLECDSADNSCryptoKeyEngine::create(unsigned int bits) +{ + if (bits >> 3 != d_len) { + throw runtime_error(getName()+" unknown key length of "+std::to_string(bits)+" bits requested"); + } + + int res = EC_KEY_generate_key(d_eckey.get()); + if (res == 0) { + throw runtime_error(getName()+" key generation failed"); + } +} + + +DNSCryptoKeyEngine::storvector_t OpenSSLECDSADNSCryptoKeyEngine::convertToISCVector() const +{ + storvector_t storvect; + string algorithm; + + if(d_algorithm == 13) + algorithm = "13 (ECDSAP256SHA256)"; + else if(d_algorithm == 14) + algorithm = "14 (ECDSAP384SHA384)"; + else + algorithm = " ? (?)"; + + storvect.push_back(make_pair("Algorithm", algorithm)); + + const BIGNUM *key = EC_KEY_get0_private_key(d_eckey.get()); + if (key == nullptr) { + throw runtime_error(getName()+" private key not set"); + } + + std::string tmp; + tmp.resize(BN_num_bytes(key)); + int len = BN_bn2bin(key, reinterpret_cast(&tmp.at(0))); + + string prefix; + if (d_len - len) + prefix.append(d_len - len, 0x00); + + storvect.push_back(make_pair("PrivateKey", prefix + tmp)); + + return storvect; +} + + +std::string OpenSSLECDSADNSCryptoKeyEngine::hash(const std::string& orig) const +{ + if(getBits() == 256) { + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256((unsigned char*) orig.c_str(), orig.length(), hash); + return string((char*) hash, sizeof(hash)); + } + else if(getBits() == 384) { + unsigned char hash[SHA384_DIGEST_LENGTH]; + SHA384((unsigned char*) orig.c_str(), orig.length(), hash); + return string((char*) hash, sizeof(hash)); + } + + throw runtime_error(getName()+" does not support a hash size of "+std::to_string(getBits())+" bits"); +} + + +std::string OpenSSLECDSADNSCryptoKeyEngine::sign(const std::string& msg) const +{ + string hash = this->hash(msg); + + auto signature = std::unique_ptr(ECDSA_do_sign((unsigned char*) hash.c_str(), hash.length(), d_eckey.get()), ECDSA_SIG_free); + if (!signature) { + throw runtime_error(getName()+" failed to generate signature"); + } + + string ret; + std::string tmp; + tmp.resize(d_len); + + const BIGNUM *pr, *ps; + ECDSA_SIG_get0(signature.get(), &pr, &ps); + int len = BN_bn2bin(pr, reinterpret_cast(&tmp.at(0))); + if (d_len - len) + ret.append(d_len - len, 0x00); + ret.append(&tmp.at(0), len); + + len = BN_bn2bin(ps, reinterpret_cast(&tmp.at(0))); + if (d_len - len) + ret.append(d_len - len, 0x00); + ret.append(&tmp.at(0), len); + + return ret; +} + + +bool OpenSSLECDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + if (signature.length() != (d_len * 2)) { + throw runtime_error(getName()+" invalid signature size "+std::to_string(signature.length())); + } + + string hash = this->hash(msg); + + auto sig = std::unique_ptr(ECDSA_SIG_new(), ECDSA_SIG_free); + if (!sig) { + throw runtime_error(getName()+" allocation of signature structure failed"); + } + + auto r = std::unique_ptr(BN_bin2bn((unsigned char*) signature.c_str(), d_len, nullptr), BN_clear_free); + auto s = std::unique_ptr(BN_bin2bn((unsigned char*) signature.c_str() + d_len, d_len, nullptr), BN_clear_free); + if (!r || !s) { + throw runtime_error(getName()+" invalid signature"); + } + + ECDSA_SIG_set0(sig.get(), r.release(), s.release()); + int ret = ECDSA_do_verify((unsigned char*) hash.c_str(), hash.length(), sig.get(), d_eckey.get()); + + if (ret == -1){ + throw runtime_error(getName()+" verify error"); + } + + return (ret == 1); +} + + +std::string OpenSSLECDSADNSCryptoKeyEngine::getPubKeyHash() const +{ + string pubKey = getPublicKeyString(); + unsigned char hash[SHA_DIGEST_LENGTH]; + SHA1((unsigned char*) pubKey.c_str(), pubKey.length(), hash); + return string((char*) hash, sizeof(hash)); +} + + +std::string OpenSSLECDSADNSCryptoKeyEngine::getPublicKeyString() const +{ + std::string binaryPoint; + binaryPoint.resize((d_len * 2) + 1); + + int ret = EC_POINT_point2oct(d_ecgroup.get(), EC_KEY_get0_public_key(d_eckey.get()), POINT_CONVERSION_UNCOMPRESSED, reinterpret_cast(&binaryPoint.at(0)), binaryPoint.size(), nullptr); + if (ret == 0) { + throw runtime_error(getName()+" exporting point to binary failed"); + } + + /* we skip the first byte as the other backends use + raw field elements, as opposed to the format described in + SEC1: "2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion" */ + binaryPoint.erase(0, 1); + return binaryPoint; +} + + +void OpenSSLECDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) +{ + drc.d_algorithm = atoi(stormap["algorithm"].c_str()); + + if (drc.d_algorithm != d_algorithm) { + throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key"); + } + + string privateKey = stormap["privatekey"]; + + auto prv_key = std::unique_ptr(BN_bin2bn((unsigned char*) privateKey.c_str(), privateKey.length(), nullptr), BN_clear_free); + if (!prv_key) { + throw runtime_error(getName()+" reading private key from binary failed"); + } + + int ret = EC_KEY_set_private_key(d_eckey.get(), prv_key.get()); + if (ret != 1) { + throw runtime_error(getName()+" setting private key failed"); + } + + auto pub_key = std::unique_ptr(EC_POINT_new(d_ecgroup.get()), EC_POINT_free); + if (!pub_key) { + throw runtime_error(getName()+" allocation of public key point failed"); + } + + ret = EC_POINT_mul(d_ecgroup.get(), pub_key.get(), prv_key.get(), nullptr, nullptr, nullptr); + if (ret != 1) { + throw runtime_error(getName()+" computing public key from private failed"); + } + + ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get()); + if (ret != 1) { + throw runtime_error(getName()+" setting public key failed"); + } +} + +bool OpenSSLECDSADNSCryptoKeyEngine::checkKey(vector *errorMessages) const +{ + bool retval = true; + if (EC_KEY_check_key(d_eckey.get()) != 1) { + retval = false; + if (errorMessages != nullptr) { + errorMessages->push_back(ERR_reason_error_string(ERR_get_error())); + } + } + return retval; +} + +void OpenSSLECDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + /* uncompressed point, from SEC1: + "2.3.4 Octet-String-to-Elliptic-Curve-Point Conversion" */ + string ecdsaPoint= "\x04"; + ecdsaPoint.append(input); + + auto pub_key = std::unique_ptr(EC_POINT_new(d_ecgroup.get()), EC_POINT_free); + if (!pub_key) { + throw runtime_error(getName()+" allocation of point structure failed"); + } + + int ret = EC_POINT_oct2point(d_ecgroup.get(), pub_key.get(), (unsigned char*) ecdsaPoint.c_str(), ecdsaPoint.length(), nullptr); + if (ret != 1) { + throw runtime_error(getName()+" reading ECP point from binary failed"); + } + + ret = EC_KEY_set_private_key(d_eckey.get(), nullptr); + if (ret == 1) { + throw runtime_error(getName()+" setting private key failed"); + } + + ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get()); + if (ret != 1) { + throw runtime_error(getName()+" setting public key failed"); + } +} +#endif + +#ifdef HAVE_LIBCRYPTO_EDDSA +class OpenSSLEDDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit OpenSSLEDDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_edkey(std::unique_ptr(nullptr, EVP_PKEY_free)) + { + + int ret = RAND_status(); + if (ret != 1) { + throw runtime_error(getName()+" insufficient entropy"); + } + +#ifdef HAVE_LIBCRYPTO_ED25519 + if(d_algorithm == 15) { + d_len = 32; + d_id = NID_ED25519; + } +#endif +#ifdef HAVE_LIBCRYPTO_ED448 + if (d_algorithm == 16) { + d_len = 57; + d_id = NID_ED448; + } +#endif + if (d_len == 0) { + throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm)); + } + } + + ~OpenSSLEDDSADNSCryptoKeyEngine() + { + } + + string getName() const override { return "OpenSSL EDDSA"; } + int getBits() const override { return d_len; } + + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string sign(const std::string& hash) const override; + bool verify(const std::string& msg, const std::string& signature) const override; + std::string getPubKeyHash() const override; + std::string getPublicKeyString() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + bool checkKey(vector *errorMessages) const override; + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + size_t d_len{0}; + int d_id{0}; + + std::unique_ptr d_edkey; +}; + +bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey(vector *errorMessages) const +{ + return (d_edkey ? true : false); +} + +void OpenSSLEDDSADNSCryptoKeyEngine::create(unsigned int bits) +{ + auto pctx = std::unique_ptr(EVP_PKEY_CTX_new_id(d_id, nullptr), EVP_PKEY_CTX_free); + if (!pctx) { + throw runtime_error(getName()+" context initialization failed"); + } + if (EVP_PKEY_keygen_init(pctx.get()) < 1) { + throw runtime_error(getName()+" keygen initialization failed"); + } + EVP_PKEY* newKey = nullptr; + if (EVP_PKEY_keygen(pctx.get(), &newKey) < 1) { + throw runtime_error(getName()+" key generation failed"); + } + d_edkey = std::unique_ptr(newKey, EVP_PKEY_free); +} + +DNSCryptoKeyEngine::storvector_t OpenSSLEDDSADNSCryptoKeyEngine::convertToISCVector() const +{ + storvector_t storvect; + string algorithm; + +#ifdef HAVE_LIBCRYPTO_ED25519 + if(d_algorithm == 15) { + algorithm = "15 (ED25519)"; + } +#endif +#ifdef HAVE_LIBCRYPTO_ED448 + if(d_algorithm == 16) { + algorithm = "16 (ED448)"; + } +#endif + if (algorithm.empty()) { + algorithm = " ? (?)"; + } + + storvect.push_back(make_pair("Algorithm", algorithm)); + + string buf; + size_t len = d_len; + buf.resize(len); + if (EVP_PKEY_get_raw_private_key(d_edkey.get(), reinterpret_cast(&buf.at(0)), &len) < 1) { + throw runtime_error(getName() + " Could not get private key from d_edkey"); + } + storvect.push_back(make_pair("PrivateKey", buf)); + return storvect; +} + +std::string OpenSSLEDDSADNSCryptoKeyEngine::sign(const std::string& msg) const +{ + auto mdctx = std::unique_ptr(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (!mdctx) { + throw runtime_error(getName()+" MD context initialization failed"); + } + if(EVP_DigestSignInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) { + throw runtime_error(getName()+" unable to initialize signer"); + } + + string msgToSign = msg; + + size_t siglen = d_len * 2; + string signature; + signature.resize(siglen); + + if (EVP_DigestSign(mdctx.get(), + reinterpret_cast(&signature.at(0)), &siglen, + reinterpret_cast(&msgToSign.at(0)), msgToSign.length()) < 1) { + throw runtime_error(getName()+" signing error"); + } + + return signature; +} + +bool OpenSSLEDDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + auto mdctx = std::unique_ptr(EVP_MD_CTX_new(), EVP_MD_CTX_free); + if (!mdctx) { + throw runtime_error(getName()+" MD context initialization failed"); + } + if(EVP_DigestVerifyInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) { + throw runtime_error(getName()+" unable to initialize signer"); + } + + string checkSignature = signature; + string checkMsg = msg; + + auto r = EVP_DigestVerify(mdctx.get(), + reinterpret_cast(&checkSignature.at(0)), checkSignature.length(), + reinterpret_cast(&checkMsg.at(0)), checkMsg.length()); + if (r < 0) { + throw runtime_error(getName()+" verification failure"); + } + + return (r == 1); +} + +std::string OpenSSLEDDSADNSCryptoKeyEngine::getPubKeyHash() const +{ + return this->getPublicKeyString(); +} + +std::string OpenSSLEDDSADNSCryptoKeyEngine::getPublicKeyString() const +{ + string buf; + size_t len = d_len; + buf.resize(len); + if (EVP_PKEY_get_raw_public_key(d_edkey.get(), reinterpret_cast(&buf.at(0)), &len) < 1) { + throw std::runtime_error(getName() + " unable to get public key from key struct"); + } + return buf; +} + +void OpenSSLEDDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) { + drc.d_algorithm = atoi(stormap["algorithm"].c_str()); + if (drc.d_algorithm != d_algorithm) { + throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key"); + } + + d_edkey = std::unique_ptr(EVP_PKEY_new_raw_private_key(d_id, nullptr, reinterpret_cast(&stormap["privatekey"].at(0)), stormap["privatekey"].length()), EVP_PKEY_free); + if (!d_edkey) { + throw std::runtime_error(getName() + " could not create key structure from private key"); + } +} + +void OpenSSLEDDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& content) +{ + if (content.length() != d_len) { + throw runtime_error(getName() + " wrong public key length for algorithm " + std::to_string(d_algorithm)); + } + + const unsigned char* raw = reinterpret_cast(content.c_str()); + + d_edkey = std::unique_ptr(EVP_PKEY_new_raw_public_key(d_id, nullptr, raw, d_len), EVP_PKEY_free); + if (!d_edkey) { + throw runtime_error(getName()+" allocation of public key structure failed"); + } +} +#endif // HAVE_LIBCRYPTO_EDDSA + +namespace { + struct LoaderStruct + { + LoaderStruct() + { + DNSCryptoKeyEngine::report(5, &OpenSSLRSADNSCryptoKeyEngine::maker); + DNSCryptoKeyEngine::report(7, &OpenSSLRSADNSCryptoKeyEngine::maker); + DNSCryptoKeyEngine::report(8, &OpenSSLRSADNSCryptoKeyEngine::maker); + DNSCryptoKeyEngine::report(10, &OpenSSLRSADNSCryptoKeyEngine::maker); +#ifdef HAVE_LIBCRYPTO_ECDSA + DNSCryptoKeyEngine::report(13, &OpenSSLECDSADNSCryptoKeyEngine::maker); + DNSCryptoKeyEngine::report(14, &OpenSSLECDSADNSCryptoKeyEngine::maker); +#endif +#ifdef HAVE_LIBCRYPTO_ED25519 + DNSCryptoKeyEngine::report(15, &OpenSSLEDDSADNSCryptoKeyEngine::maker); +#endif +#ifdef HAVE_LIBCRYPTO_ED448 + DNSCryptoKeyEngine::report(16, &OpenSSLEDDSADNSCryptoKeyEngine::maker); +#endif + } + } loaderOpenSSL; +} diff --git a/pdns/opensslsigners.hh b/pdns/opensslsigners.hh new file mode 100644 index 0000000..cf7982c --- /dev/null +++ b/pdns/opensslsigners.hh @@ -0,0 +1,35 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +#include + +#include "dns_random.hh" + +/* pthread locking */ +void openssl_thread_setup(); +void openssl_thread_cleanup(); + +/* seeding PRNG */ +void openssl_seed(); diff --git a/pdns/packetcache.hh b/pdns/packetcache.hh new file mode 100644 index 0000000..7b2f1a8 --- /dev/null +++ b/pdns/packetcache.hh @@ -0,0 +1,152 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PACKETCACHE_HH +#define PACKETCACHE_HH + +#include "ednsoptions.hh" +#include "misc.hh" +#include "iputils.hh" + +class PacketCache : public boost::noncopyable +{ +public: + static uint32_t canHashPacket(const std::string& packet, uint16_t* ecsBegin, uint16_t* ecsEnd) + { + uint32_t ret = 0; + ret = burtle(reinterpret_cast(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id + size_t packetSize = packet.size(); + size_t pos = sizeof(dnsheader); + const char* end = packet.c_str() + packetSize; + const char* p = packet.c_str() + pos; + + for(; p < end && *p; ++p, ++pos) { // XXX if you embed a 0 in your qname we'll stop lowercasing there + const unsigned char l = dns_tolower(*p); // label lengths can safely be lower cased + ret=burtle(&l, 1, ret); + } // XXX the embedded 0 in the qname will break the subnet stripping + + const struct dnsheader* dh = reinterpret_cast(packet.c_str()); + const char* skipBegin = p; + const char* skipEnd = p; + if (ecsBegin != nullptr && ecsEnd != nullptr) { + *ecsBegin = 0; + *ecsEnd = 0; + } + /* we need at least 1 (final empty label) + 2 (QTYPE) + 2 (QCLASS) + + OPT root label (1), type (2), class (2) and ttl (4) + + the OPT RR rdlen (2) + = 16 + */ + if(ntohs(dh->arcount)==1 && (pos+16) < packetSize) { + char* optionBegin = nullptr; + size_t optionLen = 0; + /* skip the final empty label (1), the qtype (2), qclass (2) */ + /* root label (1), type (2), class (2) and ttl (4) */ + int res = getEDNSOption(const_cast(reinterpret_cast(p)) + 14, end - (p + 14), EDNSOptionCode::ECS, &optionBegin, &optionLen); + if (res == 0) { + skipBegin = optionBegin; + skipEnd = optionBegin + optionLen; + if (ecsBegin != nullptr && ecsEnd != nullptr) { + *ecsBegin = optionBegin - packet.c_str(); + *ecsEnd = *ecsBegin + optionLen; + } + } + } + if (skipBegin > p) { + ret = burtle(reinterpret_cast(p), skipBegin-p, ret); + } + if (skipEnd < end) { + ret = burtle(reinterpret_cast(skipEnd), end-skipEnd, ret); + } + + return ret; + } + + static uint32_t canHashPacket(const std::string& packet) + { + uint32_t ret = 0; + ret = burtle(reinterpret_cast(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id + size_t packetSize = packet.size(); + size_t pos = sizeof(dnsheader); + const char* end = packet.c_str() + packetSize; + const char* p = packet.c_str() + pos; + + for(; p < end && *p; ++p) { // XXX if you embed a 0 in your qname we'll stop lowercasing there + const unsigned char l = dns_tolower(*p); // label lengths can safely be lower cased + ret=burtle(&l, 1, ret); + } // XXX the embedded 0 in the qname will break the subnet stripping + + if (p < end) { + ret = burtle(reinterpret_cast(p), end-p, ret); + } + + return ret; + } + + static bool queryHeaderMatches(const std::string& cachedQuery, const std::string& query) + { + if (cachedQuery.size() != query.size()) { + return false; + } + + return (cachedQuery.compare(/* skip the ID */ 2, sizeof(dnsheader) - 2, query, 2, sizeof(dnsheader) - 2) == 0); + } + + static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname) + { + if (!queryHeaderMatches(cachedQuery, query)) { + return false; + } + + size_t pos = sizeof(dnsheader) + qname.wirelength(); + + return (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) == 0); + } + + static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname, uint16_t ecsBegin, uint16_t ecsEnd) + { + if (!queryHeaderMatches(cachedQuery, query)) { + return false; + } + + size_t pos = sizeof(dnsheader) + qname.wirelength(); + + if (ecsBegin != 0 && ecsBegin >= pos && ecsEnd > ecsBegin) { + if (cachedQuery.compare(pos, ecsBegin - pos, query, pos, ecsBegin - pos) != 0) { + return false; + } + + if (cachedQuery.compare(ecsEnd, cachedQuery.size() - ecsEnd, query, ecsEnd, query.size() - ecsEnd) != 0) { + return false; + } + } + else { + if (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) != 0) { + return false; + } + } + + return true; + } + +}; + +#endif /* PACKETCACHE_HH */ diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc new file mode 100644 index 0000000..34ea3ef --- /dev/null +++ b/pdns/packethandler.cc @@ -0,0 +1,1585 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "packetcache.hh" +#include "utility.hh" +#include "base32.hh" +#include +#include +#include +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include "dns.hh" +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "dnspacket.hh" +#include "nameserver.hh" +#include "distributor.hh" +#include "logger.hh" +#include "arguments.hh" +#include "packethandler.hh" +#include "statbag.hh" +#include "resolver.hh" +#include "communicator.hh" +#include "dnsproxy.hh" +#include "version.hh" +#include "common_startup.hh" + +#if 0 +#undef DLOG +#define DLOG(x) x +#endif + +AtomicCounter PacketHandler::s_count; +NetmaskGroup PacketHandler::s_allowNotifyFrom; +set PacketHandler::s_forwardNotify; + +extern string s_programname; + +PacketHandler::PacketHandler():B(s_programname), d_dk(&B) +{ + ++s_count; + d_doDNAME=::arg().mustDo("dname-processing"); + d_doExpandALIAS = ::arg().mustDo("expand-alias"); + d_logDNSDetails= ::arg().mustDo("log-dns-details"); + d_doIPv6AdditionalProcessing = ::arg().mustDo("do-ipv6-additional-processing"); + string fname= ::arg()["lua-prequery-script"]; + if(fname.empty()) + { + d_pdl = NULL; + } + else + { + d_pdl = std::unique_ptr(new AuthLua4()); + d_pdl->loadFile(fname); + } + fname = ::arg()["lua-dnsupdate-policy-script"]; + if (fname.empty()) + { + d_update_policy_lua = NULL; + } + else + { + d_update_policy_lua = std::unique_ptr(new AuthLua4()); + d_update_policy_lua->loadFile(fname); + } +} + +UeberBackend *PacketHandler::getBackend() +{ + return &B; +} + +PacketHandler::~PacketHandler() +{ + --s_count; + DLOG(g_log<qdomain, "PUBLISH-CDNSKEY", publishCDNSKEY); + if (publishCDNSKEY != "1") + return false; + + DNSZoneRecord rr; + bool haveOne=false; + + DNSSECKeeper::keyset_t entryPoints = d_dk.getEntryPoints(p->qdomain); + for(const auto& value: entryPoints) { + rr.dr.d_type=QType::CDNSKEY; + rr.dr.d_ttl=sd.default_ttl; + rr.dr.d_name=p->qdomain; + rr.dr.d_content=std::make_shared(value.first.getDNSKEY()); + rr.auth=true; + r->addRecord(rr); + haveOne=true; + } + + if(::arg().mustDo("direct-dnskey")) { + B.lookup(QType(QType::CDNSKEY), p->qdomain, p, sd.domain_id); + + while(B.get(rr)) { + rr.dr.d_ttl=sd.default_ttl; + r->addRecord(rr); + haveOne=true; + } + } + return haveOne; +} + +/** + * This adds DNSKEY records to the answer packet. Returns true if one was added. + * + * @param p Pointer to the DNSPacket containing the original question + * @param r Pointer to the DNSPacket where the records should be inserted into + * @param sd SOAData of the zone for which DNSKEY records sets should be added + * @return bool that shows if any records were added +**/ +bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd) +{ + DNSZoneRecord rr; + bool haveOne=false; + + DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain); + for(const auto& value: keyset) { + rr.dr.d_type=QType::DNSKEY; + rr.dr.d_ttl=sd.default_ttl; + rr.dr.d_name=p->qdomain; + rr.dr.d_content=std::make_shared(value.first.getDNSKEY()); + rr.auth=true; + r->addRecord(rr); + haveOne=true; + } + + if(::arg().mustDo("direct-dnskey")) { + B.lookup(QType(QType::DNSKEY), p->qdomain, p, sd.domain_id); + + while(B.get(rr)) { + rr.dr.d_ttl=sd.default_ttl; + r->addRecord(rr); + haveOne=true; + } + } + + return haveOne; +} + +/** + * This adds CDS records to the answer packet r. + * + * @param p Pointer to the DNSPacket containing the original question. + * @param r Pointer to the DNSPacket where the records should be inserted into. + * @param sd SOAData of the zone for which CDS records sets should be added, + * used to determine record TTL. + * @return bool that shows if any records were added. +**/ +bool PacketHandler::addCDS(DNSPacket *p, DNSPacket *r, const SOAData& sd) +{ + string publishCDS; + d_dk.getFromMeta(p->qdomain, "PUBLISH-CDS", publishCDS); + if (publishCDS.empty()) + return false; + + vector digestAlgos; + stringtok(digestAlgos, publishCDS, ", "); + + DNSZoneRecord rr; + rr.dr.d_type=QType::CDS; + rr.dr.d_ttl=sd.default_ttl; + rr.dr.d_name=p->qdomain; + rr.auth=true; + + bool haveOne=false; + + DNSSECKeeper::keyset_t keyset = d_dk.getEntryPoints(p->qdomain); + + for(auto const &value : keyset) { + for(auto const &digestAlgo : digestAlgos){ + rr.dr.d_content=std::make_shared(makeDSFromDNSKey(p->qdomain, value.first.getDNSKEY(), pdns_stou(digestAlgo))); + r->addRecord(rr); + haveOne=true; + } + } + + if(::arg().mustDo("direct-dnskey")) { + B.lookup(QType(QType::CDS), p->qdomain, p, sd.domain_id); + + while(B.get(rr)) { + rr.dr.d_ttl=sd.default_ttl; + r->addRecord(rr); + haveOne=true; + } + } + + return haveOne; +} + +/** This adds NSEC3PARAM records. Returns true if one was added */ +bool PacketHandler::addNSEC3PARAM(DNSPacket *p, DNSPacket *r, const SOAData& sd) +{ + DNSZoneRecord rr; + + NSEC3PARAMRecordContent ns3prc; + if(d_dk.getNSEC3PARAM(p->qdomain, &ns3prc)) { + rr.dr.d_type=QType::NSEC3PARAM; + rr.dr.d_ttl=sd.default_ttl; + rr.dr.d_name=p->qdomain; + ns3prc.d_flags = 0; // the NSEC3PARAM 'flag' is defined to always be zero in RFC5155. + rr.dr.d_content=std::make_shared(ns3prc); + rr.auth = true; + r->addRecord(rr); + return true; + } + return false; +} + + +// This is our chaos class requests handler. Return 1 if content was added, 0 if it wasn't +int PacketHandler::doChaosRequest(DNSPacket *p, DNSPacket *r, DNSName &target) +{ + DNSZoneRecord rr; + + if(p->qtype.getCode()==QType::TXT) { + static const DNSName versionbind("version.bind."), versionpdns("version.pdns."), idserver("id.server."); + if (target==versionbind || target==versionpdns) { + // modes: full, powerdns only, anonymous or custom + const static string mode=::arg()["version-string"]; + string content; + if(mode.empty() || mode=="full") + content=fullVersionString(); + else if(mode=="powerdns") + content="Served by PowerDNS - https://www.powerdns.com/"; + else if(mode=="anonymous") { + r->setRcode(RCode::ServFail); + return 0; + } + else + content=mode; + rr.dr.d_content = DNSRecordContent::mastermake(QType::TXT, 1, "\""+content+"\""); + } + else if (target==idserver) { + // modes: disabled, hostname or custom + const static string id=::arg()["server-id"]; + + if (id == "disabled") { + r->setRcode(RCode::Refused); + return 0; + } + string tid=id; + if(!tid.empty() && tid[0]!='"') { // see #6010 however + tid = "\"" + tid + "\""; + } + rr.dr.d_content=DNSRecordContent::mastermake(QType::TXT, 1, tid); + } + else { + r->setRcode(RCode::Refused); + return 0; + } + + rr.dr.d_ttl=5; + rr.dr.d_name=target; + rr.dr.d_type=QType::TXT; + rr.dr.d_class=QClass::CHAOS; + r->addRecord(rr); + return 1; + } + + r->setRcode(RCode::NotImp); + return 0; +} + +vector PacketHandler::getBestReferralNS(DNSPacket *p, SOAData& sd, const DNSName &target) +{ + vector ret; + DNSZoneRecord rr; + DNSName subdomain(target); + do { + if(subdomain == sd.qname) // stop at SOA + break; + B.lookup(QType(QType::NS), subdomain, p, sd.domain_id); + while(B.get(rr)) { + ret.push_back(rr); // this used to exclude auth NS records for some reason + } + if(!ret.empty()) + return ret; + } while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> '' + return ret; +} + +vector PacketHandler::getBestDNAMESynth(DNSPacket *p, SOAData& sd, DNSName &target) +{ + vector ret; + DNSZoneRecord rr; + DNSName prefix; + DNSName subdomain(target); + do { + DLOG(g_log<<"Attempting DNAME lookup for "<(rr.dr); + if (!rec) { + continue; + } + if(rec->d_type == QType::CNAME || rec->d_type == p->qtype.getCode() || (p->qtype.getCode() == QType::ANY && rec->d_type != QType::RRSIG)) { + // noCache=true; + DLOG(g_log<<"Executing Lua: '"<getCode()<<"'"<getCode(), target, sd.qname, sd.domain_id, *p, rec->d_type); + for(const auto& r : recvec) { + rr.dr.d_type = rec->d_type; // might be CNAME + rr.dr.d_content = r; + rr.scopeMask = p->getRealRemote().getBits(); // this makes sure answer is a specific as your question + ret->push_back(rr); + } + } + catch (std::exception &e) { + while (B.get(rr)) ; // don't leave DB handle in bad state + + throw; + } + } + } + else +#endif + if(rr.dr.d_type == p->qtype.getCode() || rr.dr.d_type == QType::CNAME || (p->qtype.getCode() == QType::ANY && rr.dr.d_type != QType::RRSIG)) { + ret->push_back(rr); + } + + wildcard=g_wildcarddnsname+subdomain; + haveSomething=true; + } + + if ( subdomain == sd.qname || haveSomething ) // stop at SOA or result + break; + + B.lookup(QType(QType::ANY), subdomain, p, sd.domain_id); + if (B.get(rr)) { + DLOG(g_log<<"No wildcard match, ancestor exists"<qtype.getCode()!=QType::AXFR) { // this packet needs additional processing + // we now have a copy, push_back on packet might reallocate! + auto& records = r->getRRS(); + vector toAdd; + + for(auto i = records.cbegin() ; i!= records.cend(); ++i) { + if(i->dr.d_place==DNSResourceRecord::ADDITIONAL || + !(i->dr.d_type==QType::MX || i->dr.d_type==QType::NS || i->dr.d_type==QType::SRV)) + continue; + + if(r->d.aa && i->dr.d_name.countLabels() && i->dr.d_type==QType::NS && !B.getSOA(i->dr.d_name,sd) && !retargeted) { // drop AA in case of non-SOA-level NS answer, except for root referral + r->setA(false); + // i->d_place=DNSResourceRecord::AUTHORITY; // XXX FIXME + } + + DNSName lookup; + + if(i->dr.d_type == QType::MX) + lookup = getRR(i->dr)->d_mxname; + else if(i->dr.d_type == QType::SRV) + lookup = getRR(i->dr)->d_target; + else if(i->dr.d_type == QType::NS) + lookup = getRR(i->dr)->getNS(); + else + continue; + + B.lookup(QType(d_doIPv6AdditionalProcessing ? QType::ANY : QType::A), lookup, p, soadata.domain_id); + + while(B.get(rr)) { + if(rr.dr.d_type != QType::A && rr.dr.d_type!=QType::AAAA) + continue; + if(!rr.dr.d_name.isPartOf(soadata.qname)) { + // FIXME we might still pass on the record if it is occluded and the + // backend uses a single id for all zones + continue; + } + rr.dr.d_place=DNSResourceRecord::ADDITIONAL; + toAdd.push_back(rr); + } + } + for(const auto& rec : toAdd) + r->addRecord(rec); + + //records.insert(records.end(), toAdd.cbegin(), toAdd.cend()); // would be faster, but no dedup + } + return 1; +} + + +void PacketHandler::emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& name, const DNSName& next, int mode) +{ + NSECRecordContent nrc; + nrc.d_next = next; + + nrc.set(QType::NSEC); + nrc.set(QType::RRSIG); + if(sd.qname == name) { + nrc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table + nrc.set(QType::DNSKEY); + string publishCDNSKEY; + d_dk.getFromMeta(name, "PUBLISH-CDNSKEY", publishCDNSKEY); + if (publishCDNSKEY == "1") + nrc.set(QType::CDNSKEY); + string publishCDS; + d_dk.getFromMeta(name, "PUBLISH-CDS", publishCDS); + if (! publishCDS.empty()) + nrc.set(QType::CDS); + } + + DNSZoneRecord rr; + + B.lookup(QType(QType::ANY), name, NULL, sd.domain_id); + while(B.get(rr)) { +#ifdef HAVE_LUA_RECORDS + if(rr.dr.d_type == QType::LUA) + nrc.set(getRR(rr.dr)->d_type); + else +#endif + if(rr.dr.d_type == QType::NS || rr.auth) + nrc.set(rr.dr.d_type); + } + + rr.dr.d_name = name; + rr.dr.d_ttl = sd.default_ttl; + rr.dr.d_type = QType::NSEC; + rr.dr.d_content = std::make_shared(std::move(nrc)); + rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY; + rr.auth = true; + + r->addRecord(rr); +} + +void PacketHandler::emitNSEC3(DNSPacket *r, const SOAData& sd, const NSEC3PARAMRecordContent& ns3prc, const DNSName& name, const string& namehash, const string& nexthash, int mode) +{ + NSEC3RecordContent n3rc; + n3rc.d_algorithm = ns3prc.d_algorithm; + n3rc.d_flags = ns3prc.d_flags; + n3rc.d_iterations = ns3prc.d_iterations; + n3rc.d_salt = ns3prc.d_salt; + n3rc.d_nexthash = nexthash; + + DNSZoneRecord rr; + + if(!name.empty()) { + if (sd.qname == name) { + n3rc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table + n3rc.set(QType::NSEC3PARAM); + n3rc.set(QType::DNSKEY); + string publishCDNSKEY; + d_dk.getFromMeta(name, "PUBLISH-CDNSKEY", publishCDNSKEY); + if (publishCDNSKEY == "1") + n3rc.set(QType::CDNSKEY); + string publishCDS; + d_dk.getFromMeta(name, "PUBLISH-CDS", publishCDS); + if (! publishCDS.empty()) + n3rc.set(QType::CDS); + } + + B.lookup(QType(QType::ANY), name, NULL, sd.domain_id); + while(B.get(rr)) { +#ifdef HAVE_LUA_RECORDS + if(rr.dr.d_type == QType::LUA) + n3rc.set(getRR(rr.dr)->d_type); + else +#endif + if(rr.dr.d_type && (rr.dr.d_type == QType::NS || rr.auth)) // skip empty non-terminals + n3rc.set(rr.dr.d_type); + } + } + + const auto numberOfTypesSet = n3rc.numberOfTypesSet(); + if (numberOfTypesSet != 0 && !(numberOfTypesSet == 1 && n3rc.isSet(QType::NS))) { + n3rc.set(QType::RRSIG); + } + + rr.dr.d_name = DNSName(toBase32Hex(namehash))+sd.qname; + rr.dr.d_ttl = sd.default_ttl; + rr.dr.d_type=QType::NSEC3; + rr.dr.d_content=std::make_shared(std::move(n3rc)); + rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY; + rr.auth = true; + + r->addRecord(rr); +} + +/* + mode 0 = No Data Responses, QTYPE is not DS + mode 1 = No Data Responses, QTYPE is DS + mode 2 = Wildcard No Data Responses + mode 3 = Wildcard Answer Responses + mode 4 = Name Error Responses + mode 5 = Direct NSEC request +*/ +void PacketHandler::addNSECX(DNSPacket *p, DNSPacket *r, const DNSName& target, const DNSName& wildcard, const DNSName& auth, int mode) +{ + NSEC3PARAMRecordContent ns3rc; + bool narrow; + if(d_dk.getNSEC3PARAM(auth, &ns3rc, &narrow)) { + if (mode != 5) // no direct NSEC3 queries, rfc5155 7.2.8 + addNSEC3(p, r, target, wildcard, auth, ns3rc, narrow, mode); + } + else { + addNSEC(p, r, target, wildcard, auth, mode); + } +} + +bool getNSEC3Hashes(bool narrow, DNSBackend* db, int id, const std::string& hashed, bool decrement, DNSName& unhashed, std::string& before, std::string& after, int mode) +{ + bool ret; + if(narrow) { // nsec3-narrow + ret=true; + before=hashed; + if(decrement) { + decrementHash(before); + unhashed.clear(); + } + after=hashed; + incrementHash(after); + } + else { + DNSName hashedName = DNSName(toBase32Hex(hashed)); + DNSName beforeName, afterName; + if (!decrement && mode >= 2) + beforeName = hashedName; + ret=db->getBeforeAndAfterNamesAbsolute(id, hashedName, unhashed, beforeName, afterName); + before=fromBase32Hex(beforeName.toString()); + after=fromBase32Hex(afterName.toString()); + } + return ret; +} + +void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const DNSName& target, const DNSName& wildcard, const DNSName& auth, const NSEC3PARAMRecordContent& ns3rc, bool narrow, int mode) +{ + DLOG(g_log<<"addNSEC3() mode="<= 2 && mode <= 4) || doNextcloser) { + DNSName next(target); + do { + unhashed=next; + } + while( next.chopOff() && !(next==closest)); + + hashed=hashQNameWithSalt(ns3rc, unhashed); + DLOG(g_log<<"2 hash: "<getBeforeAndAfterNames(sd.domain_id, auth, target, before, after); + if (mode != 5 || before == target) + emitNSEC(r, sd, before, after, mode); + + if (mode == 2 || mode == 4) { + // wildcard NO-DATA or wildcard denial + before.clear(); + DNSName closest(wildcard); + if (mode == 4) { + closest.chopOff(); + closest.prependRawLabel("*"); + } + sd.db->getBeforeAndAfterNames(sd.domain_id, auth, closest, before, after); + emitNSEC(r, sd, before, after, mode); + } + return; +} + +/* Semantics: + +- only one backend owns the SOA of a zone +- only one AXFR per zone at a time - double startTransaction should fail +- backends need to implement transaction semantics + + +How BindBackend would implement this: + startTransaction makes a file + feedRecord sends everything to that file + commitTransaction moves that file atomically over the regular file, and triggers a reload + rollbackTransaction removes the file + + +How PostgreSQLBackend would implement this: + startTransaction starts a sql transaction, which also deletes all records + feedRecord is an insert statement + commitTransaction commits the transaction + rollbackTransaction aborts it + +How MySQLBackend would implement this: + (good question!) + +*/ + +int PacketHandler::trySuperMaster(DNSPacket *p, const DNSName& tsigkeyname) +{ + if(p->d_tcp) + { + // do it right now if the client is TCP + // rarely happens + return trySuperMasterSynchronous(p, tsigkeyname); + } + else + { + // queue it if the client is on UDP + Communicator.addTrySuperMasterRequest(p); + return 0; + } +} + +int PacketHandler::trySuperMasterSynchronous(const DNSPacket *p, const DNSName& tsigkeyname) +{ + ComboAddress remote = p->getRemote().setPort(53); + if(p->hasEDNSSubnet() && ::arg().contains("trusted-notification-proxy", remote.toString())) { + remote = p->getRealRemote().getNetwork(); + } + + Resolver::res_t nsset; + try { + Resolver resolver; + uint32_t theirserial; + resolver.getSoaSerial(remote, p->qdomain, &theirserial); + resolver.resolve(remote, p->qdomain, QType::NS, &nsset); + } + catch(ResolverException &re) { + g_log<qdomain<<" at: "<< remote <<": "<qdomain<<" at: "<< remote <qdomain<<" from potential supermaster "<qdomain, nsset, &nameserver, &account, &db)) { + g_log<qdomain<<" for potential supermaster "<createSlaveDomain(p->getRemote().toString(), p->qdomain, nameserver, account); + if (tsigkeyname.empty() == false) { + vector meta; + meta.push_back(tsigkeyname.toStringNoDot()); + db->setDomainMetadata(p->qdomain, "AXFR-MASTER-TSIG", meta); + } + } + catch(PDNSException& ae) { + g_log<qdomain<<" for potential supermaster "<qdomain<<"' from supermaster "< do stuff + */ + + g_log<qdomain<<" from "<getRemote()<qdomain<<" from "<getRemote()<<" but slave support is disabled in the configuration"<d_remote ) || p->d_havetsig) { + if (p->d_havetsig && p->getTSIGKeyname().empty() == false) { + g_log<qdomain<<" from "<getRemote()<<", with TSIG key '"<getTSIGKeyname()<<"'"<qdomain<<" from "<getRemote()<<" but the remote is not providing a TSIG key or in allow-notify-from (Refused)"<d_havetsig) || p->d_havetsig) { + if (!p->d_havetsig) { + g_log<qdomain<<" from "<getRemote()<<" while a TSIG key was required (Refused)"< meta; + if (B.getDomainMetadata(p->qdomain,"AXFR-MASTER-TSIG",meta) && meta.size() > 0) { + DNSName expected{meta[0]}; + if (p->getTSIGKeyname() != expected) { + g_log<qdomain<<" from "<getRemote()<<": expected TSIG key '"<getTSIGKeyname()<<"' (Refused)"<qdomain, di, false) || !di.backend) { + if(::arg().mustDo("superslave")) { + g_log<qdomain<<" from "<getRemote()<<" for which we are not authoritative, trying supermaster"<getTSIGKeyname()); + } + g_log<qdomain<<" from "<getRemote()<<" for which we are not authoritative (Refused)"<getRemote().toString())) { + g_log<qdomain<<" from trusted-notification-proxy "<< p->getRemote()<qdomain<<" does not have any masters defined (Refused)"<qdomain<<" from "<getRemote()<<" but we are master (Refused)"<getRemote())) { + g_log<qdomain<<" from "<getRemote()<<" which is not a master (Refused)"< forwardNotify(s_forwardNotify); + for(set::const_iterator j=forwardNotify.begin();j!=forwardNotify.end();++j) { + g_log<qdomain<<" from "<getRemote()<<" to "<<*j<qdomain,*j); + } + } + + if(::arg().mustDo("slave")) { + g_log<qdomain<d_remote); + } + return 0; +} + +bool validDNSName(const DNSName &name) +{ + if (!g_8bitDNS) { + string::size_type pos, length; + char c; + for(const auto& s : name.getRawLabels()) { + length=s.length(); + for(pos=0; pos < length; ++pos) { + c=s[pos]; + if(!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c =='-' || c == '_' || c=='*' || c=='.' || c=='/' || c=='@' || c==' ' || c=='\\' || c==':')) + return false; + } + } + } + return true; +} + +DNSPacket *PacketHandler::question(DNSPacket *p) +{ + DNSPacket *ret; + + if(d_pdl) + { + ret=d_pdl->prequery(p); + if(ret) + return ret; + } + + if(p->d.rd) { + static AtomicCounter &rdqueries=*S.getPointer("rd-queries"); + rdqueries++; + } + + return doQuestion(p); +} + + +void PacketHandler::makeNXDomain(DNSPacket* p, DNSPacket* r, const DNSName& target, const DNSName& wildcard, const SOAData& sd) +{ + DNSZoneRecord rr; + rr=makeEditedDNSZRFromSOAData(d_dk, sd, DNSResourceRecord::AUTHORITY); + rr.dr.d_ttl=min(sd.ttl, sd.default_ttl); + r->addRecord(rr); + + if(d_dnssec) { + addNSECX(p, r, target, wildcard, sd.qname, 4); + } + + r->setRcode(RCode::NXDomain); +} + +void PacketHandler::makeNOError(DNSPacket* p, DNSPacket* r, const DNSName& target, const DNSName& wildcard, const SOAData& sd, int mode) +{ + DNSZoneRecord rr; + rr=makeEditedDNSZRFromSOAData(d_dk, sd, DNSResourceRecord::AUTHORITY); + rr.dr.d_ttl=min(sd.ttl, sd.default_ttl); + r->addRecord(rr); + + if(d_dnssec) { + addNSECX(p, r, target, wildcard, sd.qname, mode); + } + + S.ringAccount("noerror-queries", p->qdomain, p->qtype); +} + + +bool PacketHandler::addDSforNS(DNSPacket* p, DNSPacket* r, SOAData& sd, const DNSName& dsname) +{ + //cerr<<"Trying to find a DS for '"< rrset = getBestDNAMESynth(p, sd, target); + if(!rrset.empty()) { + for(auto& rr: rrset) { + rr.dr.d_place = DNSResourceRecord::ANSWER; + r->addRecord(rr); + } + return true; + } + return false; +} +bool PacketHandler::tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, DNSName &target, DNSName &wildcard, bool& retargeted, bool& nodata) +{ + retargeted = nodata = false; + DNSName bestmatch; + + vector rrset; + if(!getBestWildcard(p, sd, target, wildcard, &rrset)) + return false; + + if(rrset.empty()) { + DLOG(g_log<<"Wildcard matched something, but not of the correct type"<(rr.dr)->getTarget(); + } + + rr.dr.d_place=DNSResourceRecord::ANSWER; + r->addRecord(rr); + } + } + if(d_dnssec && !nodata) { + addNSECX(p, r, bestmatch, wildcard, sd.qname, 3); + } + + return true; +} + +//! Called by the Distributor to ask a question. Returns 0 in case of an error +DNSPacket *PacketHandler::doQuestion(DNSPacket *p) +{ + DNSZoneRecord rr; + SOAData sd; + + int retargetcount=0; + set authSet; + + vector rrset; + bool weDone=0, weRedirected=0, weHaveUnauth=0, doSigs=0; + DNSName haveAlias; + uint8_t aliasScopeMask; + + DNSPacket *r=nullptr; + bool noCache=false; + +#ifdef HAVE_LUA_RECORDS + bool doLua=g_doLuaRecord; +#endif + + if(p->d.qr) { // QR bit from dns packet (thanks RA from N) + if(d_logDNSDetails) + g_log<getRemote()<<", dropping"<d_remote); + return 0; + } + + if(p->d.tc) { // truncated query. MOADNSParser would silently parse this packet in an incomplete way. + if(d_logDNSDetails) + g_log<getRemote()<<", dropping"<d_remote); + return 0; + } + + if (p->hasEDNS() && p->getEDNSVersion() > 0) { + r = p->replyPacket(); + + // PacketWriter::addOpt will take care of setting this correctly in the packet + r->setEDNSRcode(ERCode::BADVERS); + return r; + } + + if(p->d_havetsig) { + DNSName keyname; + string secret; + TSIGRecordContent trc; + if(!p->checkForCorrectTSIG(&B, &keyname, &secret, &trc)) { + r=p->replyPacket(); // generate an empty reply packet + if(d_logDNSDetails) + g_log<d.opcode == Opcode::Update) + r->setRcode(RCode::Refused); + else + r->setRcode(RCode::NotAuth); + return r; + } else { + getTSIGHashEnum(trc.d_algoName, p->d_tsig_algo); + if (p->d_tsig_algo == TSIG_GSS) { + GssContext gssctx(keyname); + if (!gssctx.getPeerPrincipal(p->d_peer_principal)) { + g_log<setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket() + noCache=true; + } + + r=p->replyPacket(); // generate an empty reply packet, possibly with TSIG details inside + + if (p->qtype == QType::TKEY) { + this->tkeyHandler(p, r); + return r; + } + + try { + + // XXX FIXME do this in DNSPacket::parse ? + + if(!validDNSName(p->qdomain)) { + if(d_logDNSDetails) + g_log<getRemote()<<", '"<qdomain<<"': sending servfail"<d_remote); + S.inc("servfail-packets"); + r->setRcode(RCode::ServFail); + return r; + } + if(p->d.opcode) { // non-zero opcode (again thanks RA!) + if(p->d.opcode==Opcode::Update) { + S.inc("dnsupdate-queries"); + int res=processUpdate(p); + if (res == RCode::Refused) + S.inc("dnsupdate-refused"); + else if (res != RCode::ServFail) + S.inc("dnsupdate-answers"); + r->setRcode(res); + r->setOpcode(Opcode::Update); + return r; + } + else if(p->d.opcode==Opcode::Notify) { + S.inc("incoming-notifications"); + int res=processNotify(p); + if(res>=0) { + r->setRcode(res); + r->setOpcode(Opcode::Notify); + return r; + } + delete r; + return 0; + } + + g_log<d.opcode<<" from "<getRemote()<<" for "<qdomain<setRcode(RCode::NotImp); + return r; + } + + // g_log<qdomain<<"' "<qtype.getName()<<" from "<getRemote()<< " (tcp="<d_tcp<<")"<qtype.getCode()==QType::IXFR) { + r->setRcode(RCode::Refused); + return r; + } + + DNSName target=p->qdomain; + + // catch chaos qclass requests + if(p->qclass == QClass::CHAOS) { + if (doChaosRequest(p,r,target)) + goto sendit; + else + return r; + } + + // we only know about qclass IN (and ANY), send Refused for everything else. + if(p->qclass != QClass::IN && p->qclass!=QClass::ANY) { + r->setRcode(RCode::Refused); + return r; + } + + // send TC for udp ANY query if any-to-tcp is enabled. + if(p->qtype.getCode() == QType::ANY && !p->d_tcp && g_anyToTcp) { + r->d.tc = 1; + r->commitD(); + return r; + } + + // for qclass ANY the response should never be authoritative unless the response covers all classes. + if(p->qclass==QClass::ANY) + r->setA(false); + + + retargeted:; + if(retargetcount > 10) { // XXX FIXME, retargetcount++? + g_log<qdomain<<"'"<replyPacket(); + r->setRcode(RCode::ServFail); + return r; + } + + if(!B.getAuth(target, p->qtype, &sd)) { + DLOG(g_log<setA(false); // drop AA if we never had a SOA in the first place + r->setRcode(RCode::Refused); // send REFUSED - but only on empty 'no idea' + } + goto sendit; + } + DLOG(g_log<getRemote()<setRcode(RCode::Refused); + goto sendit; + } + + DLOG(g_log<<"Checking for referrals first, unless this is a DS query"<qtype.getCode() != QType::DS && tryReferral(p, r, sd, target, retargetcount)) + goto sendit; + + DLOG(g_log<<"Got no referrals, trying ANY"<(rr.dr); + if (!rec) { + continue; + } + if(rec->d_type == QType::CNAME || rec->d_type == p->qtype.getCode() || (p->qtype.getCode() == QType::ANY && rec->d_type != QType::RRSIG)) { + noCache=true; + try { + auto recvec=luaSynth(rec->getCode(), target, sd.qname, sd.domain_id, *p, rec->d_type); + if(!recvec.empty()) { + for(const auto& r : recvec) { + rr.dr.d_type = rec->d_type; // might be CNAME + rr.dr.d_content = r; + rr.scopeMask = p->getRealRemote().getBits(); // this makes sure answer is a specific as your question + rrset.push_back(rr); + } + if(rec->d_type == QType::CNAME && p->qtype.getCode() != QType::CNAME) + weRedirected = 1; + else + weDone = 1; + } + } + catch(std::exception &e) { + while (B.get(rr)) ; // don't leave DB handle in bad state + + r=p->replyPacket(); + r->setRcode(RCode::ServFail); + + return r; + } + } + } +#endif + //cerr<<"got content: ["<qtype.getCode() == QType::ANY && (rr.dr.d_type == QType:: DNSKEY || rr.dr.d_type == QType::NSEC3PARAM)) + continue; // Don't send dnssec info. + if (rr.dr.d_type == QType::RRSIG) // RRSIGS are added later any way. + continue; // TODO: this actually means addRRSig should check if the RRSig is already there + + // cerr<<"Auth: "<qtype)<<", "<qtype.getCode() == QType::ANY || rr.dr.d_type == p->qtype.getCode()) && rr.auth) + weDone=1; + // the line below fakes 'unauth NS' for delegations for non-DNSSEC backends. + if((rr.dr.d_type == p->qtype.getCode() && !rr.auth) || (rr.dr.d_type == QType::NS && (!rr.auth || !(sd.qname==rr.dr.d_name)))) + weHaveUnauth=1; + + if(rr.dr.d_type == QType::CNAME && p->qtype.getCode() != QType::CNAME) + weRedirected=1; + + if(DP && rr.dr.d_type == QType::ALIAS && (p->qtype.getCode() == QType::A || p->qtype.getCode() == QType::AAAA || p->qtype.getCode() == QType::ANY)) { + if (!d_doExpandALIAS) { + g_log<(rr.dr)->d_content; + aliasScopeMask=rr.scopeMask; + } + + // Filter out all SOA's and add them in later + if(rr.dr.d_type == QType::SOA) + continue; + + rrset.push_back(rr); + } + + /* Add in SOA if required */ + if(target==sd.qname) { + rr=makeEditedDNSZRFromSOAData(d_dk, sd); + rrset.push_back(rr); + } + + + DLOG(g_log<<"After first ANY query for '"<qtype.getCode() == QType::DS && weHaveUnauth && !weDone && !weRedirected) { + DLOG(g_log<<"Q for DS of a name for which we do have NS, but for which we don't have DS; need to provide an AUTH answer that shows we don't"<qtype.getCode() == QType::ANY)) { + DLOG(g_log<completePacket(r, haveAlias, target, aliasScopeMask); + return 0; + } + + + // referral for DS query + if(p->qtype.getCode() == QType::DS) { + DLOG(g_log<<"Qtype is DS"<qdomainwild=wildcard; + retargetcount++; + goto retargeted; + } + if(nodata) + makeNOError(p, r, target, wildcard, sd, 2); + + goto sendit; + } + else if(tryDNAME(p, r, sd, target)) { + retargetcount++; + goto retargeted; + } + else + { + if (!(((p->qtype.getCode() == QType::CNAME) || (p->qtype.getCode() == QType::ANY)) && retargetcount > 0)) + makeNXDomain(p, r, target, wildcard, sd); + } + + goto sendit; + } + + if(weRedirected) { + for(auto& loopRR: rrset) { + if(loopRR.dr.d_type == QType::CNAME) { + r->addRecord(loopRR); + target = getRR(loopRR.dr)->getTarget(); + retargetcount++; + goto retargeted; + } + } + } + else if(weDone) { + bool haveRecords = false; + for(const auto& loopRR: rrset) { +#ifdef HAVE_LUA_RECORDS + if(loopRR.dr.d_type == QType::LUA) + continue; +#endif + if((p->qtype.getCode() == QType::ANY || loopRR.dr.d_type == p->qtype.getCode()) && loopRR.dr.d_type && loopRR.dr.d_type != QType::ALIAS && loopRR.auth) { + r->addRecord(loopRR); + haveRecords = true; + } + } + + if (haveRecords) { + if(d_dnssec && p->qtype.getCode() == QType::ANY) + completeANYRecords(p, r, sd, target); + } + else + makeNOError(p, r, target, DNSName(), sd, 0); + + goto sendit; + } + else if(weHaveUnauth) { + DLOG(g_log<<"Have unauth data, so need to hunt for best NS records"<qdomain<<"|"<qtype.getCode()<<"): you have a trailing dot, this could be the problem (or run pdnsutil rectify-zone " <qdomain<<"|"<qtype.getCode()<<"): please run pdnsutil rectify-zone "<getRRS()) { + if(loopRR.scopeMask) { + noCache=true; + break; + } + } + if(doSigs) + addRRSigs(d_dk, B, authSet, r->getRRS()); + + if(PC.enabled() && !noCache && p->couldBeCached()) + PC.insert(p, r, r->getMinTTL()); // in the packet cache + } + catch(DBException &e) { + g_log<replyPacket(); // generate an empty reply packet + r->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", p->qdomain, p->qtype); + } + catch(PDNSException &e) { + g_log<qdomain<<"/"<qtype.getName()<<" ("<replyPacket(); // generate an empty reply packet + r->setRcode(RCode::ServFail); + S.inc("servfail-packets"); + S.ringAccount("servfail-queries", p->qdomain, p->qtype); + } + return r; + +} diff --git a/pdns/packethandler.hh b/pdns/packethandler.hh new file mode 100644 index 0000000..b5bdfc7 --- /dev/null +++ b/pdns/packethandler.hh @@ -0,0 +1,121 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PACKETHANDLER_HH +#define PACKETHANDLER_HH + +#include +#include +#include +#include "ueberbackend.hh" +#include "dnspacket.hh" +#include "packetcache.hh" +#include "dnsseckeeper.hh" +#include "lua-auth4.hh" +#include "gss_context.hh" + +#include "namespaces.hh" + +// silly Solaris people define PC +#undef PC + +/** Central DNS logic according to RFC1034. Ask this class a question in the form of a DNSPacket + and it will return, synchronously, a DNSPacket answer, suitable for + sending out over the network. + + The PacketHandler gives your question to the PacketCache for possible inclusion + in the cache. + + In order to do so, the PacketHandler contains a reference to the global extern PacketCache PC + + It also contains an UeberBackend instance for answering the subqueries needed to generate + a complete reply. + +*/ +class NSEC3PARAMRecordContent; + +class PacketHandler +{ +public: + DNSPacket *doQuestion(DNSPacket *); //!< hand us a DNS packet with a question, we give you an answer + DNSPacket *question(DNSPacket *); //!< hand us a DNS packet with a question, we give you an answer + PacketHandler(); + ~PacketHandler(); // defined in packethandler.cc, and does --count + static int numRunning(){return s_count;}; //!< Returns the number of running PacketHandlers. Called by Distributor + + UeberBackend *getBackend(); + + int trySuperMasterSynchronous(const DNSPacket *p, const DNSName& tsigkeyname); + static NetmaskGroup s_allowNotifyFrom; + static set s_forwardNotify; + +private: + int trySuperMaster(DNSPacket *p, const DNSName& tsigkeyname); + int processNotify(DNSPacket *); + void addRootReferral(DNSPacket *r); + int doChaosRequest(DNSPacket *p, DNSPacket *r, DNSName &target); + bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd); + bool addCDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd); + bool addCDS(DNSPacket *p, DNSPacket *r, const SOAData& sd); + bool addNSEC3PARAM(DNSPacket *p, DNSPacket *r, const SOAData& sd); + int doAdditionalProcessingAndDropAA(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool retargeted); + void addNSECX(DNSPacket *p, DNSPacket* r, const DNSName &target, const DNSName &wildcard, const DNSName &auth, int mode); + void addNSEC(DNSPacket *p, DNSPacket* r, const DNSName &target, const DNSName &wildcard, const DNSName& auth, int mode); + void addNSEC3(DNSPacket *p, DNSPacket* r, const DNSName &target, const DNSName &wildcard, const DNSName& auth, const NSEC3PARAMRecordContent& nsec3param, bool narrow, int mode); + void emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& name, const DNSName& next, int mode); + void emitNSEC3(DNSPacket *r, const SOAData& sd, const NSEC3PARAMRecordContent &ns3rc, const DNSName& unhashed, const string& begin, const string& end, int mode); + int processUpdate(DNSPacket *p); + int forwardPacket(const string &msgPrefix, DNSPacket *p, DomainInfo *di); + uint performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool isPresigned, bool* narrow, bool* haveNSEC3, NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial); + int checkUpdatePrescan(const DNSRecord *rr); + int checkUpdatePrerequisites(const DNSRecord *rr, DomainInfo *di); + void increaseSerial(const string &msgPrefix, const DomainInfo *di, bool haveNSEC3, bool narrow, const NSEC3PARAMRecordContent *ns3pr); + + void makeNXDomain(DNSPacket* p, DNSPacket* r, const DNSName& target, const DNSName& wildcard, const SOAData& sd); + void makeNOError(DNSPacket* p, DNSPacket* r, const DNSName& target, const DNSName& wildcard, const SOAData& sd, int mode); + vector getBestReferralNS(DNSPacket *p, SOAData& sd, const DNSName &target); + vector getBestDNAMESynth(DNSPacket *p, SOAData& sd, DNSName &target); + bool tryDNAME(DNSPacket *p, DNSPacket*r, SOAData& sd, DNSName &target); + bool tryReferral(DNSPacket *p, DNSPacket*r, SOAData& sd, const DNSName &target, bool retargeted); + + bool getBestWildcard(DNSPacket *p, SOAData& sd, const DNSName &target, DNSName &wildcard, vector* ret); + bool tryWildcard(DNSPacket *p, DNSPacket*r, SOAData& sd, DNSName &target, DNSName &wildcard, bool& retargeted, bool& nodata); + bool addDSforNS(DNSPacket* p, DNSPacket* r, SOAData& sd, const DNSName& dsname); + void completeANYRecords(DNSPacket *p, DNSPacket*r, SOAData& sd, const DNSName &target); + + void tkeyHandler(DNSPacket *p, DNSPacket *r); // d_pdl; + std::unique_ptr d_update_policy_lua; + + UeberBackend B; // every thread an own instance + DNSSECKeeper d_dk; // B is shared with DNSSECKeeper +}; +bool getNSEC3Hashes(bool narrow, DNSBackend* db, int id, const std::string& hashed, bool decrement, DNSName& unhashed, string& before, string& after, int mode=0); +std::shared_ptr makeSOAContent(const SOAData& sd); +#endif /* PACKETHANDLER */ diff --git a/pdns/pdns.init.in b/pdns/pdns.init.in new file mode 100755 index 0000000..63c1a54 --- /dev/null +++ b/pdns/pdns.init.in @@ -0,0 +1,206 @@ +#!/bin/sh +# chkconfig: - 80 75 +# description: PDNS is a versatile high performance authoritative nameserver + +### BEGIN INIT INFO +# Provides: pdns +# Required-Start: $remote_fs $network $syslog +# Required-Stop: $remote_fs $network $syslog +# Should-Start: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: PowerDNS authoritative server +# Description: PowerDNS authoritative server +### END INIT INFO + +set -e + +exec_prefix=@exec_prefix@ +BINARYPATH=@bindir@ +SBINARYPATH=@sbindir@ +SOCKETPATH=@socketdir@ +DAEMON_ARGS="" + +[ -f "$SBINARYPATH/pdns_server" ] || exit 0 + +[ -r /etc/default/pdns ] && . /etc/default/pdns + +[ "$START" = "no" ] && exit 0 + +# Make sure that /var/run exists +mkdir -p $SOCKETPATH +cd $SOCKETPATH +suffix=$(basename $0 | cut -d- -f2- -s) +if [ -n "$suffix" ] +then + EXTRAOPTS=--config-name=$suffix + PROGNAME=pdns-$suffix +else + PROGNAME=pdns +fi + +pdns_server="$SBINARYPATH/pdns_server $DAEMON_ARGS $EXTRAOPTS" + +doPC() +{ + ret=$($BINARYPATH/pdns_control $EXTRAOPTS $1 $2 2> /dev/null) +} + +NOTRUNNING=0 +doPC ping || NOTRUNNING=$? + +case "$1" in + status) + if test "$NOTRUNNING" = "0" + then + doPC status + echo $ret + else + echo "not running" + exit 3 + fi + ;; + + stop) + echo -n "Stopping PowerDNS authoritative nameserver: " + if test "$NOTRUNNING" = "0" + then + doPC quit + echo $ret + else + echo "not running" + fi + ;; + + + force-stop) + echo -n "Stopping PowerDNS authoritative nameserver: " + killall -v -9 pdns_server + echo "killed" + ;; + + start) + echo -n "Starting PowerDNS authoritative nameserver: " + if test "$NOTRUNNING" = "0" + then + echo "already running" + else + if $pdns_server --daemon --guardian=yes + then + echo "started" + else + echo "starting failed" + exit 1 + fi + fi + ;; + + force-reload | restart) + echo -n "Restarting PowerDNS authoritative nameserver: " + if test "$NOTRUNNING" = "1" + then + echo "not running, starting" + else + + echo -n stopping and waiting.. + doPC quit + sleep 3 + echo done + fi + $0 start + ;; + + reload) + echo -n "Reloading PowerDNS authoritative nameserver: " + if test "$NOTRUNNING" = "0" + then + doPC cycle + echo requested reload + else + echo not running yet + $0 start + fi + ;; + + monitor) + if test "$NOTRUNNING" = "0" + then + echo "already running" + else + $pdns_server --daemon=no --guardian=no --control-console --loglevel=9 + fi + ;; + + dump) + if test "$NOTRUNNING" = "0" + then + doPC list + echo $ret + else + echo "not running" + fi + ;; + + show) + if [ $# -lt 2 ] + then + echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + echo -n "$2=" + doPC show $2 ; echo $ret + else + echo "not running" + fi + ;; + + mrtg) + if [ $# -lt 2 ] + then + echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + doPC show $2 ; echo $ret + if [ "$3x" != "x" ] + then + doPC show $3 ; echo $ret + else + echo 0 + fi + doPC uptime ; echo $ret + echo PowerDNS daemon + else + echo "not running" + fi + + ;; + + cricket) + if [ $# -lt 2 ] + then + echo Insufficient parameters + exit + fi + if test "$NOTRUNNING" = "0" + then + doPC show $2 ; echo $ret + else + echo "not running" + fi + + ;; + + + + *) + echo pdns [start\|stop\|force-reload\|reload\|restart\|status\|dump\|show\|mrtg\|cricket\|monitor] + + ;; +esac + + diff --git a/pdns/pdns.service.in b/pdns/pdns.service.in new file mode 100644 index 0000000..60a6e07 --- /dev/null +++ b/pdns/pdns.service.in @@ -0,0 +1,32 @@ +[Unit] +Description=PowerDNS Authoritative Server +Documentation=man:pdns_server(1) man:pdns_control(1) +Documentation=https://doc.powerdns.com +Wants=network-online.target +After=network-online.target mysqld.service postgresql.service slapd.service mariadb.service + +[Service] +ExecStart=@sbindir@/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no +Type=notify +Restart=on-failure +RestartSec=1 +StartLimitInterval=0 + +# Sandboxing +CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_CHOWN CAP_SYS_CHROOT +LockPersonality=true +ProtectControlGroups=true +ProtectHome=true +ProtectKernelModules=true +ProtectKernelTunables=true +# ProtectSystem=full will disallow write access to /etc and /usr, possibly +# not being able to write slaved-zones into sqlite3 or zonefiles. +ProtectSystem=full +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +RestrictNamespaces=true +RestrictRealtime=true +SystemCallArchitectures=native +SystemCallFilter=~ @clock @debug @module @mount @raw-io @reboot @swap @cpu-emulation @obsolete + +[Install] +WantedBy=multi-user.target diff --git a/pdns/pdnsexception.hh b/pdns/pdnsexception.hh new file mode 100644 index 0000000..f820f55 --- /dev/null +++ b/pdns/pdnsexception.hh @@ -0,0 +1,47 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNSEXCEPTION_HH +#define PDNSEXCEPTION_HH +/* (C) 2002 POWERDNS.COM BV */ + +#include + +#include "namespaces.hh" + +//! Generic Exception thrown +class PDNSException +{ +public: + PDNSException() : reason("Unspecified") {}; + PDNSException(string r) : reason(r) {}; + + string reason; //! Print this to tell the user what went wrong +}; + +class TimeoutException : public PDNSException +{ +public: + TimeoutException() : PDNSException() {} + TimeoutException(string r) : PDNSException(r) {} +}; + +#endif diff --git a/pdns/pdnsutil.cc b/pdns/pdnsutil.cc new file mode 100644 index 0000000..efb9378 --- /dev/null +++ b/pdns/pdnsutil.cc @@ -0,0 +1,3342 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnsseckeeper.hh" +#include "dnssecinfra.hh" +#include "statbag.hh" +#include "base32.hh" +#include "base64.hh" + +#include +#include +#include +#include "tsigutils.hh" +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "arguments.hh" +#include "auth-packetcache.hh" +#include "auth-querycache.hh" +#include "zoneparser-tng.hh" +#include "signingpipe.hh" +#include "dns_random.hh" +#include "ipcipher.hh" +#include +#include //termios, TCSANOW, ECHO, ICANON +#include "opensslsigners.hh" +#ifdef HAVE_LIBSODIUM +#include +#endif +#ifdef HAVE_SQLITE3 +#include "ssqlite3.hh" +#include "bind-dnssec.schema.sqlite3.sql.h" +#endif + +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; + +namespace po = boost::program_options; +po::variables_map g_vm; + +string s_programname="pdns"; + +namespace { + bool g_verbose; +} + +ArgvMap &arg() +{ + static ArgvMap arg; + return arg; +} + +void loadMainConfig(const std::string& configdir) +{ + ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=configdir; + ::arg().set("default-ttl","Seconds a result is valid if not set otherwise")="3600"; + ::arg().set("launch","Which backends to launch"); + ::arg().set("dnssec","if we should do dnssec")="true"; + ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=g_vm["config-name"].as(); + ::arg().setCmd("help","Provide a helpful message"); + ::arg().set("load-modules","Load this module - supply absolute or relative path")=""; + //::arg().laxParse(argc,argv); + + if(::arg().mustDo("help")) { + cout<<"syntax:"< modules; + + stringtok(modules,::arg()["load-modules"], ", "); + if (!UeberBackend::loadModules(modules, ::arg()["module-dir"])) { + exit(1); + } + } + + g_log.toConsole(Logger::Error); // so we print any errors + BackendMakers().launch(::arg()["launch"]); // vrooooom! + if(::arg().asNum("loglevel") >= 3) // so you can't kill our errors + g_log.toConsole((Logger::Urgency)::arg().asNum("loglevel")); + + //cerr<<"Backend: "<<::arg()["launch"]<<", '" << ::arg()["gmysql-dbname"] <<"'" < domains; + if(!fname.empty()) { + ifstream ifs(fname.c_str()); + if(!ifs) { + cerr<<"Could not open '"< domainInfo; + bool result = true; + + B.getAllDomains(&domainInfo); + for(DomainInfo di : domainInfo) { + if (!quiet) { + cerr<<"Rectifying "<* suppliedrecords=0) +{ + uint64_t numerrors=0, numwarnings=0; + + DomainInfo di; + try { + if (!B.getDomainInfo(zone, di)) { + cout<<"[Error] Unable to get domain information for zone '"< checkKeyErrors; + bool validKeys=dk.checkKeys(zone, &checkKeyErrors); + + if (haveNSEC3) { + if(isSecure && zone.wirelength() > 222) { + numerrors++; + cout<<"[Error] zone '" << zone << "' has NSEC3 semantics but is too long to have the hash prepended. Zone name is " << zone.wirelength() << " bytes long, whereas the maximum is 222 bytes." << endl; + } + + vector dbkeyset; + B.getDomainKeys(zone, dbkeyset); + + for(DNSBackend::KeyData& kd : dbkeyset) { + DNSKEYRecordContent dkrc; + shared_ptr(DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content)); + + if(dkrc.d_algorithm == DNSSECKeeper::RSASHA1) { + cout<<"[Warning] zone '"< tlsas, cnames, noncnames, glue, checkglue; + set > checkOcclusion; + set recordcontents; + map ttl; + + ostringstream content; + pair::iterator,bool> ret; + + vector records; + if(!suppliedrecords) { + DNSResourceRecord drr; + sd.db->list(zone, sd.domain_id, g_verbose); + while(sd.db->get(drr)) { + records.push_back(drr); + } + } + else + records=*suppliedrecords; + + for(auto &rr : records) { // we modify this + if(rr.qtype.getCode() == QType::TLSA) + tlsas.insert(rr.qname); + if(rr.qtype.getCode() == QType::SOA) { + vectorparts; + stringtok(parts, rr.content); + + if(parts.size() < 7) { + cout<<"[Warning] SOA autocomplete is deprecated, missing field(s) in SOA content: "< drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); + string tmp=drc->serialize(rr.qname); + tmp = drc->getZoneRepresentation(true); + if (rr.qtype.getCode() != QType::AAAA) { + if (!pdns_iequals(tmp, rr.content)) { + if(rr.qtype.getCode() == QType::SOA) { + tmp = drc->getZoneRepresentation(false); + } + if(!pdns_iequals(tmp, rr.content)) { + cout<<"[Warning] Parsed and original record content are not equal: "<(toLower(content.str()), rr.ttl)); + if (ret.second == false && ret.first->second != rr.ttl) { + cout<<"[Error] TTL mismatch in rrset: '"<second<<" != "<doesDNSSEC()); + for( const auto &qname : checkOcclusion ) { + if( qname.second == QType::NS ) { + if( qname.first == rr.qname ) { + ds_ns = true; + } + if ( done ) { + continue; + } + if( rr.auth == 0 ) { + if( rr.qname.isPartOf( qname.first ) && ( qname.first != rr.qname || rr.qtype != QType::DS ) ) { + ok = done = true; + } + if( rr.qtype == QType::ENT && qname.first.isPartOf( rr.qname ) ) { + ok = done = true; + } + } else if( rr.qname.isPartOf( qname.first ) && ( ( qname.first != rr.qname || rr.qtype != QType::DS ) || rr.qtype == QType::NS ) ) { + ok = false; + done = true; + } + } + } + if( ! ds_ns && rr.qtype.getCode() == QType::DS && rr.qname != zone ) { + cout << "[Warning] DS record without a delegation '" << rr.qname<<"'." << endl; + numwarnings++; + } + if( ! ok && ! suppliedrecords ) { + cout << "[Error] Following record is auth=" << rr.auth << ", run pdnsutil rectify-zone?: " << rr.qname << " IN " << rr.qtype.getName() << " " << rr.content << endl; + numerrors++; + } + } + + cout<<"Checked "< domainInfo; + multi_index_container< + DomainInfo, + indexed_by< + ordered_non_unique< member, CanonDNSNameCompare >, + ordered_non_unique< member > + > + > seenInfos; + auto& seenNames = seenInfos.get<0>(); + auto& seenIds = seenInfos.get<1>(); + + B.getAllDomains(&domainInfo, true); + int errors=0; + for(auto di : domainInfo) { + if (checkZone(dk, B, di.zone) > 0) { + errors++; + } + + auto seenName = seenNames.find(di.zone); + if (seenName != seenNames.end()) { + cout<<"[Error] Another SOA for zone '"<serial<<")."<getPrefix()<<" has already been used by zone '"<zone<<"' in backend "<backend->getPrefix()<<"."<startTransaction(zone, -1); + + if (!sd.db->replaceRRSet(sd.domain_id, zone, rr.qtype, vector(1, rr))) { + sd.db->abortTransaction(); + cerr<<"Backend did not replace SOA record. Backend might not support this operation."<doesDNSSEC()) { + NSEC3PARAMRecordContent ns3pr; + bool narrow; + bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow); + + DNSName ordername; + if(haveNSEC3) { + if(!narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zone))); + } else + ordername=DNSName(""); + if(g_verbose) + cerr<<"'"< '"<< ordername <<"'"<updateDNSSECOrderNameAndAuth(sd.domain_id, rr.qname, ordername, true); + } + + sd.db->commitTransaction(); + + cout<<"SOA serial for zone "<deleteDomain(zone)) + return EXIT_SUCCESS; + + cerr<<"Failed to delete domain '"< 29) + cout<getBits()).length() >= 8) ? 1 : 8 - std::to_string(key.first.getKey()->getBits()).length(); + if (key.first.getKey()->getBits() < 1) { + cout<<"invalid "<getBits()<= 13) ? 1 : 13 - algname.length(); + cout< 5) ? 1 : 5 - std::to_string(key.second.id).length(); + cout<convertToISCVector(); + string engine, slot, label = ""; + for (auto const &elem : stormap) { + //cout<= 12) ? 1 : 12 - engine.length()-slot.length()-label.length()-2; + cout< domainInfo; + B.getAllDomains(&domainInfo); + bool printHeader = true; + for (auto const di : domainInfo) { + listKey(di, dk, printHeader); + printHeader = false; + } + } + return EXIT_SUCCESS; +} + +int listZone(const DNSName &zone) { + UeberBackend B; + DomainInfo di; + + if (! B.getDomainInfo(zone, di)) { + cerr<<"Domain '"<list(zone, di.id); + DNSResourceRecord rr; + cout<<"$ORIGIN ."<get(rr)) { + if(rr.qtype.getCode()) { + if ( (rr.qtype.getCode() == QType::NS || rr.qtype.getCode() == QType::SRV || rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::CNAME) && !rr.content.empty() && rr.content[rr.content.size()-1] != '.') + rr.content.append(1, '.'); + + cout<startTransaction(zone, di.id)) { + cerr<<"Unable to start transaction for load of zone '"<commitTransaction(); + return EXIT_SUCCESS; +} + +int editZone(const DNSName &zone) { + UeberBackend B; + DomainInfo di; + DNSSECKeeper dk(&B); + + if (! B.getDomainInfo(zone, di)) { + cerr<<"Domain '"< pre, post; + char tmpnam[]="/tmp/pdnsutil-XXXXXX"; + int tmpfd=mkstemp(tmpnam); + if(tmpfd < 0) + unixDie("Making temporary filename in "+string(tmpnam)); + struct deleteme { + ~deleteme() { unlink(d_name.c_str()); } + deleteme(string name) : d_name(name) {} + string d_name; + } dm(tmpnam); + + vector checkrr; + int gotoline=0; + string editor="editor"; + if(auto e=getenv("EDITOR")) // <3 + editor=e; + string cmdline; + editAgain:; + di.backend->list(zone, di.id); + pre.clear(); post.clear(); + { + if(tmpfd < 0 && (tmpfd=open(tmpnam, O_CREAT | O_WRONLY | O_TRUNC, 0600)) < 0) + unixDie("Error reopening temporary file "+string(tmpnam)); + string header("; Warning - every name in this file is ABSOLUTE!\n$ORIGIN .\n"); + if(write(tmpfd, header.c_str(), header.length()) < 0) + unixDie("Writing zone to temporary file"); + DNSResourceRecord rr; + while(di.backend->get(rr)) { + if(!rr.qtype.getCode()) + continue; + DNSRecord dr(rr); + pre.push_back(dr); + } + sort(pre.begin(), pre.end(), DNSRecord::prettyCompare); + for(const auto& dr : pre) { + ostringstream os; + os<getZoneRepresentation(true)< 0) + cmdline+="+"+std::to_string(gotoline)+" "; + cmdline += tmpnam; + int err=system(cmdline.c_str()); + if(err) { + unixDie("Editing file with: '"+cmdline+"', perhaps set EDITOR variable"); + } + cmdline.clear(); + ZoneParserTNG zpt(tmpnam, g_rootdnsname); + DNSResourceRecord zrr; + map, vector > grouped; + try { + while(zpt.get(zrr)) { + DNSRecord dr(zrr); + post.push_back(dr); + grouped[{dr.d_name,dr.d_type}].push_back(dr); + } + } + catch(std::exception& e) { + cerr<<"Problem: "< diff; + + map, string> changed; + set_difference(pre.cbegin(), pre.cend(), post.cbegin(), post.cend(), back_inserter(diff), DNSRecord::prettyCompare); + for(const auto& d : diff) { + ostringstream str; + str<<"\033[0;31m-"<< d.d_name <<" "<getZoneRepresentation(true)<<"\033[0m"<getZoneRepresentation(true)<<"\033[0m"< 0) + cout<<"Detected the following changes:"<startTransaction(zone, -1); + for(const auto& change : changed) { + vector vrr; + for(const DNSRecord& rr : grouped[change.first]) { + DNSResourceRecord crr = DNSResourceRecord::fromWire(rr); + crr.domain_id = di.id; + vrr.push_back(crr); + } + di.backend->replaceRRSet(di.id, change.first.first, QType(change.first.second), vrr); + } + rectifyZone(dk, zone, false, false); + di.backend->commitTransaction(); + return EXIT_SUCCESS; +} + +static int xcryptIP(const std::string& cmd, const std::string& ip, const std::string& rkey) +{ + + ComboAddress ca(ip), ret; + + if(cmd=="ipencrypt") + ret = encryptCA(ca, rkey); + else + ret = decryptCA(ca, rkey); + + cout<startTransaction(zone, di.id)) { + cerr<<"Unable to start transaction for load of zone '"<feedRecord(rr, DNSName()); + } + db->commitTransaction(); + return EXIT_SUCCESS; +} + +int createZone(const DNSName &zone, const DNSName& nsname) { + UeberBackend B; + DomainInfo di; + if (B.getDomainInfo(zone, di)) { + cerr<<"Domain '"<getZoneRepresentation(true); + rr.domain_id = di.id; + di.backend->startTransaction(zone, di.id); + di.backend->feedRecord(rr, DNSName()); + if(!nsname.empty()) { + cout<<"Also adding one NS record"<feedRecord(rr, DNSName()); + } + + di.backend->commitTransaction(); + + return EXIT_SUCCESS; +} + +int createSlaveZone(const vector& cmds) { + UeberBackend B; + DomainInfo di; + DNSName zone(cmds[1]); + if (B.getDomainInfo(zone, di)) { + cerr<<"Domain '"< masters; + for (unsigned i=2; i < cmds.size(); i++) { + ComboAddress master(cmds[i], 53); + masters.push_back(master.toStringWithPort()); + } + cerr<<"Creating slave zone '"<setKind(zone, DomainInfo::Slave); + di.backend->setMaster(zone, boost::join(masters, ",")); + return EXIT_SUCCESS; +} + +int changeSlaveZoneMaster(const vector& cmds) { + UeberBackend B; + DomainInfo di; + DNSName zone(cmds[1]); + if (!B.getDomainInfo(zone, di)) { + cerr<<"Domain '"< masters; + for (unsigned i=2; i < cmds.size(); i++) { + ComboAddress master(cmds[i], 53); + masters.push_back(master.toStringWithPort()); + } + cerr<<"Updating slave zone '"<setMaster(zone, boost::join(masters, ",")); + return EXIT_SUCCESS; + } + catch (PDNSException& e) { + cerr<<"Setting master for zone '"<& cmds) { + DNSResourceRecord rr; + vector newrrs; + DNSName zone(cmds[1]); + DNSName name; + if(cmds[2]=="@") + name=zone; + else + name=DNSName(cmds[2])+zone; + + rr.qtype = DNSRecordContent::TypeToNumber(cmds[3]); + rr.ttl = ::arg().asNum("default-ttl"); + + UeberBackend B; + DomainInfo di; + + if(!B.getDomainInfo(zone, di)) { + cerr<<"Domain '"<startTransaction(zone, -1); + + if(addOrReplace) { // the 'add' case + di.backend->lookup(rr.qtype, rr.qname, 0, di.id); + + while(di.backend->get(oldrr)) + newrrs.push_back(oldrr); + } + + unsigned int contentStart = 4; + if(cmds.size() > 5) { + rr.ttl=atoi(cmds[4].c_str()); + if(std::to_string(rr.ttl)==cmds[4]) { + contentStart++; + } + else { + rr.ttl = ::arg().asNum("default-ttl"); + } + } + + di.backend->lookup(QType(QType::ANY), rr.qname, 0, di.id); + bool found=false; + if(rr.qtype.getCode() == QType::CNAME) { // this will save us SO many questions + + while(di.backend->get(oldrr)) { + if(addOrReplace || oldrr.qtype.getCode() != QType::CNAME) // the replace case is ok if we replace one CNAME by the other + found=true; + } + if(found) { + cerr<<"Attempting to add CNAME to "<get(oldrr)) { + if(oldrr.qtype.getCode() == QType::CNAME) + found=true; + } + if(found) { + cerr<<"Attempting to add record to "<getZoneRepresentation(true); + + newrrs.push_back(rr); + } + + + di.backend->replaceRRSet(di.id, name, rr.qtype, newrrs); + // need to be explicit to bypass the ueberbackend cache! + di.backend->lookup(rr.qtype, name, 0, di.id); + cout<<"New rrset:"<get(rr)) { + cout<commitTransaction(); + return EXIT_SUCCESS; +} + +// delete-rrset zone name type +int deleteRRSet(const std::string& zone_, const std::string& name_, const std::string& type_) +{ + UeberBackend B; + DomainInfo di; + DNSName zone(zone_); + if(!B.getDomainInfo(zone, di)) { + cerr<<"Domain '"<startTransaction(zone, -1); + di.backend->replaceRRSet(di.id, name, qt, vector()); + di.backend->commitTransaction(); + return EXIT_SUCCESS; +} + +int listAllZones(const string &type="") { + + int kindFilter = -1; + if (type.size()) { + if (toUpper(type) == "MASTER") + kindFilter = 0; + else if (toUpper(type) == "SLAVE") + kindFilter = 1; + else if (toUpper(type) == "NATIVE") + kindFilter = 2; + else { + cerr<<"Syntax: pdnsutil list-all-zones [master|slave|native]"< domains; + B.getAllDomains(&domains, true); + + int count = 0; + for (const auto& di: domains) { + if (di.kind == kindFilter || kindFilter == -1) { + cout< signatures; + uint32_t rnd; + unsigned char* octets = (unsigned char*)&rnd; + char tmp[25]; + DTime dt; + dt.set(); + for(unsigned int n=0; n < 100000; ++n) { + rnd = dns_random(UINT32_MAX); + snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", + octets[0], octets[1], octets[2], octets[3]); + rr.content=tmp; + + snprintf(tmp, sizeof(tmp), "r-%u", rnd); + rr.qname=DNSName(tmp)+zone; + DNSZoneRecord dzr; + dzr.dr=DNSRecord(rr); + if(csp.submit(dzr)) + while(signatures = csp.getChunk(), !signatures.empty()) + ; + } + cerr<<"Flushing the pipe, "< > toSign; + DNSName qname, apex; + dsrc.d_digesttype=0; + while(zpt.get(rr)) { + if(rr.qtype.getCode() == QType::DNSKEY) { + cerr<<"got DNSKEY!"<(DNSRecordContent::mastermake(QType::DNSKEY, 1, rr.content)); + } + else if(rr.qtype.getCode() == QType::RRSIG) { + cerr<<"got RRSIG"<(DNSRecordContent::mastermake(QType::RRSIG, 1, rr.content)); + } + else if(rr.qtype.getCode() == QType::DS) { + cerr<<"got DS"<(DNSRecordContent::mastermake(QType::DS, 1, rr.content)); + } + else { + qname = rr.qname; + toSign.push_back(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); + } + } + + string msg = getMessageForRRSET(qname, rrc, toSign); + cerr<<"Verify: "<verify(msg, rrc.d_signature)< key=DNSCryptoKeyEngine::makeFromISCString(drc, "Private-key-format: v1.2\n" + "Algorithm: 12 (ECC-GOST)\n" + "GostAsn1: MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQg/9MiXtXKg9FDXDN/R9CmVhJDyuzRAIgh4tPwCu4NHIs=\n"); + string resign=key->sign(hash); + cerr<verify(hash, resign)<setAccount(zone, account)) { + cerr<<"Could not find backend willing to accept new zone configuration"<setKind(zone, kind)) { + cerr<<"Could not find backend willing to accept new zone configuration"< meta; + + if (B.getDomainMetadata(zone, "TSIG-ALLOW-AXFR", meta) && meta.size() > 0) { + cout << "Zone has following allowed TSIG key(s): " << boost::join(meta, ",") << endl; + } + + meta.clear(); + if (B.getDomainMetadata(zone, "AXFR-MASTER-TSIG", meta) && meta.size() > 0) { + cout << "Zone uses following TSIG key(s): " << boost::join(meta, ",") << endl; + } + + std::map > metamap; + if(B.getAllDomainMetadata(zone, metamap)) { + cout<<"Metadata items: "; + if(metamap.empty()) + cout<<"None"; + cout< keys; + DNSZoneRecord zr; + + di.backend->lookup(QType(QType::DNSKEY), zone, nullptr, di.id ); + while(di.backend->get(zr)) { + keys.push_back(*getRR(zr.dr)); + } + + if(keys.empty()) { + cerr << "No keys for zone '"< engine(DNSCryptoKeyEngine::makeFromPublicKeyString(key.d_algorithm, key.d_key)); // throws on unknown algo or bad key + bits=engine->getBits(); + } + catch(std::exception& e) { + cerr<<"Could not process key to extract metadata: "<getBits() < 1) { + cerr<<" " <createSlaveDomain("127.0.0.1", zone, "", "_testschema"); + cout<<"Slave domain created"<startTransaction(zone, di.id); + + rr.qtype=QType::SOA; + rr.qname=zone; + rr.ttl=86400; + rr.domain_id=di.id; + rr.auth=1; + rr.content="ns1.example.com. ahu.example.com. 2012081039 7200 3600 1209600 3600"; + cout<<"Feeding SOA"<feedRecord(rr, DNSName()); + rr.qtype=QType::TXT; + // 300 As + rr.content="\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\""; + cout<<"Feeding overlong TXT"<feedRecord(rr, DNSName()); + cout<<"Committing"<commitTransaction(); + cout<<"Querying TXT"<lookup(QType(QType::TXT), zone, NULL, di.id); + if(db->get(rrget)) + { + DNSResourceRecord rrthrowaway; + if(db->get(rrthrowaway)) // should not touch rr but don't assume anything + { + cout<<"Expected one record, got multiple, aborting"<startTransaction(zone, di.id); + + rr.qtype=QType::SOA; + rr.qname=zone; + rr.ttl=86400; + rr.domain_id=di.id; + rr.auth=1; + rr.content="ns1.example.com. ahu.example.com. 2012081039 7200 3600 1209600 3600"; + cout<<"Feeding SOA"<feedRecord(rr, DNSName()); + + rr.qtype=QType::A; + rr.qname=DNSName("_underscore")+zone; + rr.content="127.0.0.1"; + db->feedRecord(rr, DNSName()); + + rr.qname=DNSName("bla")+zone; + cout<<"Committing"<commitTransaction(); + + cout<<"Securing zone"<getBeforeAndAfterNames(di.id, zone, DNSName("z")+zone, before, after); + cout<<"got '"<setNotified(di.id, 500); + db->getDomainInfo(zone, di); + if(di.notified_serial != 500) { + cout<<"[-] Set serial 500, got back "<setNotified(di.id, 2147484148); + } catch(const PDNSException &pe) { + cout<<"While setting serial, got error: "<getDomainInfo(zone, di); + if(di.notified_serial != 2147484148) { + cout<<"[-] Set serial 2147484148, got back "<& values, bool clobber) { + UeberBackend B("default"); + DomainInfo di; + + if (!B.getDomainInfo(zone, di)) { + cerr << "Invalid zone '" << zone << "'" << endl; + return 1; + } + + vector all_metadata; + + if (!clobber) { + B.getDomainMetadata(zone, kind, all_metadata); + } + + all_metadata.insert(all_metadata.end(), values.begin(), values.end()); + + if (!B.setDomainMetadata(zone, kind, all_metadata)) { + cerr << "Unable to set meta for '" << zone << "'" << endl; + return 1; + } + + cout << "Set '" << zone << "' meta " << kind << " = " << boost::join(all_metadata, ", ") << endl; + return 0; +} + +int main(int argc, char** argv) +try +{ + po::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("version", "show version") + ("verbose,v", "be verbose") + ("force", "force an action") + ("config-name", po::value()->default_value(""), "virtual configuration name") + ("config-dir", po::value()->default_value(SYSCONFDIR), "location of pdns.conf") + ("commands", po::value >()); + + po::positional_options_description p; + p.add("commands", -1); + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), g_vm); + po::notify(g_vm); + + vector cmds; + + if(g_vm.count("commands")) + cmds = g_vm["commands"].as >(); + + g_verbose = g_vm.count("verbose"); + + if (g_vm.count("version")) { + cout<<"pdnsutil "< [params ..]\n"<()); + + if (cmds[0] == "test-algorithm") { + if(cmds.size() != 2) { + cerr << "Syntax: pdnsutil test-algorithm algonum"< 2) { + cerr<<"Syntax: pdnsutil list-algorithms [with-backend]"< statements; + stringtok(statements, sqlCreate, ";"); + for(const string& statement : statements) { + db.execute(statement); + } + } + catch(SSqlException& se) { + throw PDNSException("Error creating database in BIND backend: "+se.txtReason()); + } + return 0; +#else + cerr<<"bind-dnssec-db requires building PowerDNS with SQLite3"<= 2 && cmds[1] == "quiet"); + if (!rectifyAllZones(dk, quiet)) { + return 1; + } + } + else if(cmds[0] == "check-zone") { + if(cmds.size() != 2) { + cerr << "Syntax: pdnsutil check-zone ZONE"< 1 ? cmds[1] : ""); + } + else if (cmds[0] == "check-all-zones") { + bool exitOnError = ((cmds.size() >= 2 ? cmds[1] : "") == "exit-on-error"); + exit(checkAllZones(dk, exitOnError)); + } + else if (cmds[0] == "list-all-zones") { + if (cmds.size() > 2) { + cerr << "Syntax: pdnsutil list-all-zones [master|slave|native]"< 3) ? cmds[3] : "", pdns_stou(cmds[2])); + } + else if(cmds[0] == "verify-crypto") { + if(cmds.size() != 2) { + cerr << "Syntax: pdnsutil verify-crypto FILE"<0) { + algorithm = tmp_algo; + } else if(pdns_iequals(cmds[n], "active")) { + active=true; + } else if(pdns_iequals(cmds[n], "inactive") || pdns_iequals(cmds[n], "passive")) { // 'passive' eventually needs to be removed + active=false; + } else if(pdns_stou(cmds[n])) { + bits = pdns_stou(cmds[n]); + } else { + cerr<<"Unknown algorithm, key flag or size '"< 2 ? DNSName(cmds[2]): DNSName())); + } + else if(cmds[0] == "create-slave-zone") { + if(cmds.size() < 3 ) { + cerr<<"Syntax: pdnsutil create-slave-zone ZONE master-ip [master-ip..]"< 2) { + cerr<<"Syntax: pdnsutil list-keys [ZONE]"< mustRectify; + unsigned int zoneErrors=0; + for(unsigned int n = 1; n < cmds.size(); ++n) { + DNSName zone(cmds[n]); + dk.startTransaction(zone, -1); + if(secureZone(dk, zone)) { + mustRectify.push_back(zone); + } else { + zoneErrors++; + } + dk.commitTransaction(); + } + + for(const auto& zone : mustRectify) + rectifyZone(dk, zone); + + if (zoneErrors) { + return 1; + } + return 0; + } + else if (cmds[0] == "secure-all-zones") { + if (cmds.size() >= 2 && !pdns_iequals(cmds[1], "increase-serial")) { + cerr << "Syntax: pdnsutil secure-all-zones [increase-serial]"< domainInfo; + B.getAllDomains(&domainInfo); + + unsigned int zonesSecured=0, zoneErrors=0; + for(DomainInfo di : domainInfo) { + if(!dk.isSecuredZone(di.zone)) { + cout<<"Securing "< 2 ? cmds[2] : "1 0 1 ab"; + bool narrow = cmds.size() > 3 && cmds[3]=="narrow"; + NSEC3PARAMRecordContent ns3pr(nsec3params); + + DNSName zone(cmds[1]); + if (zone.wirelength() > 222) { + cerr<<"Cannot enable NSEC3 for " << zone << " as it is too long (" << zone.wirelength() << " bytes, maximum is 222 bytes)"<convertToISC() < key(DNSCryptoKeyEngine::makeFromPEMString(drc, raw)); + dpk.setKey(key); + + dpk.d_algorithm = pdns_stou(cmds[3]); + + if(dpk.d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) + dpk.d_algorithm = DNSSECKeeper::RSASHA1; + + cerr<<(int)dpk.d_algorithm< 4) { + if(pdns_iequals(cmds[4], "ZSK")) + dpk.d_flags = 256; + else if(pdns_iequals(cmds[4], "KSK")) + dpk.d_flags = 257; + else { + cerr<<"Unknown key flag '"< key(DNSCryptoKeyEngine::makeFromISCFile(drc, fname.c_str())); + dpk.setKey(key); + dpk.d_algorithm = drc.d_algorithm; + + if(dpk.d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) + dpk.d_algorithm = DNSSECKeeper::RSASHA1; + + dpk.d_flags = 257; + bool active=true; + + for(unsigned int n = 3; n < cmds.size(); ++n) { + if(pdns_iequals(cmds[n], "ZSK")) + dpk.d_flags = 256; + else if(pdns_iequals(cmds[n], "KSK")) + dpk.d_flags = 257; + else if(pdns_iequals(cmds[n], "active")) + active = 1; + else if(pdns_iequals(cmds[n], "passive") || pdns_iequals(cmds[n], "inactive")) // passive eventually needs to be removed + active = 0; + else { + cerr<<"Unknown key flag '"<0) { + algorithm = tmp_algo; + } else if(pdns_stou(cmds[n])) + bits = pdns_stou(cmds[n]); + else { + cerr<<"Unknown algorithm, key flag or size '"< dpk(DNSCryptoKeyEngine::make(algorithm)); + if(!bits) { + if(algorithm <= 10) + bits = keyOrZone ? 2048 : 1024; + else { + if(algorithm == DNSSECKeeper::ECCGOST || algorithm == DNSSECKeeper::ECDSA256 || algorithm == DNSSECKeeper::ED25519) + bits = 256; + else if(algorithm == DNSSECKeeper::ECDSA384) + bits = 384; + else if(algorithm == DNSSECKeeper::ED448) + bits = 456; + else { + throw runtime_error("Can not guess key size for algorithm "+std::to_string(algorithm)); + } + } + } + dpk->create(bits); + dspk.setKey(dpk); + dspk.d_algorithm = algorithm; + dspk.d_flags = keyOrZone ? 257 : 256; + + // print key to stdout + cout << "Flags: " << dspk.d_flags << endl << + dspk.getKey()->convertToISC() << endl; + } else if (cmds[0]=="generate-tsig-key") { + string usage = "Syntax: " + cmds[0] + " name (hmac-md5|hmac-sha1|hmac-sha224|hmac-sha256|hmac-sha384|hmac-sha512)"; + if (cmds.size() < 3) { + cerr << usage << endl; + return 0; + } + DNSName name(cmds[1]); + DNSName algo(cmds[2]); + string key; + try { + key = makeTSIGKey(algo); + } catch(const PDNSException& e) { + cerr << "Could not create new TSIG key " << name << " " << algo << ": "<< e.reason << endl; + return 1; + } + + UeberBackend B("default"); + if (B.setTSIGKey(name, DNSName(algo), key)) { // you are feeling bored, put up DNSName(algo) up earlier + cout << "Create new TSIG key " << name << " " << algo << " " << key << endl; + } else { + cerr << "Failure storing new TSIG key " << name << " " << algo << " " << key << endl; + return 1; + } + return 0; + } else if (cmds[0]=="import-tsig-key") { + if (cmds.size() < 4) { + cerr << "Syntax: " << cmds[0] << " name algorithm key" << endl; + return 0; + } + DNSName name(cmds[1]); + string algo = cmds[2]; + string key = cmds[3]; + + UeberBackend B("default"); + if (B.setTSIGKey(name, DNSName(algo), key)) { + cout << "Imported TSIG key " << name << " " << algo << endl; + } else { + cerr << "Failure importing TSIG key " << name << " " << algo << endl; + return 1; + } + return 0; + } else if (cmds[0]=="delete-tsig-key") { + if (cmds.size() < 2) { + cerr << "Syntax: " << cmds[0] << " name" << endl; + return 0; + } + DNSName name(cmds[1]); + + UeberBackend B("default"); + if (B.deleteTSIGKey(name)) { + cout << "Deleted TSIG key " << name << endl; + } else { + cerr << "Failure deleting TSIG key " << name << endl; + return 1; + } + return 0; + } else if (cmds[0]=="list-tsig-keys") { + std::vector keys; + UeberBackend B("default"); + if (B.getTSIGKeys(keys)) { + for(const TSIGKey &key : keys) { + cout << key.name.toString() << " " << key.algorithm.toString() << " " << key.key << endl; + } + } + return 0; + } else if (cmds[0]=="activate-tsig-key") { + string metaKey; + if (cmds.size() < 4) { + cerr << "Syntax: " << cmds[0] << " ZONE NAME {master|slave}" << endl; + return 0; + } + DNSName zname(cmds[1]); + string name = cmds[2]; + if (cmds[3] == "master") + metaKey = "TSIG-ALLOW-AXFR"; + else if (cmds[3] == "slave") + metaKey = "AXFR-MASTER-TSIG"; + else { + cerr << "Invalid parameter '" << cmds[3] << "', expected master or slave" << endl; + return 1; + } + UeberBackend B("default"); + std::vector meta; + if (!B.getDomainMetadata(zname, metaKey, meta)) { + cerr << "Failure enabling TSIG key " << name << " for " << zname << endl; + return 1; + } + bool found = false; + for(std::string tmpname : meta) { + if (tmpname == name) { found = true; break; } + } + if (!found) meta.push_back(name); + if (B.setDomainMetadata(zname, metaKey, meta)) { + cout << "Enabled TSIG key " << name << " for " << zname << endl; + } else { + cerr << "Failure enabling TSIG key " << name << " for " << zname << endl; + return 1; + } + return 0; + } else if (cmds[0]=="deactivate-tsig-key") { + string metaKey; + if (cmds.size() < 4) { + cerr << "Syntax: " << cmds[0] << " ZONE NAME {master|slave}" << endl; + return 0; + } + DNSName zname(cmds[1]); + string name = cmds[2]; + if (cmds[3] == "master") + metaKey = "TSIG-ALLOW-AXFR"; + else if (cmds[3] == "slave") + metaKey = "AXFR-MASTER-TSIG"; + else { + cerr << "Invalid parameter '" << cmds[3] << "', expected master or slave" << endl; + return 1; + } + + UeberBackend B("default"); + std::vector meta; + if (!B.getDomainMetadata(zname, metaKey, meta)) { + cerr << "Failure disabling TSIG key " << name << " for " << zname << endl; + return 1; + } + std::vector::iterator iter = meta.begin(); + for(;iter != meta.end(); ++iter) if (*iter == name) break; + if (iter != meta.end()) meta.erase(iter); + if (B.setDomainMetadata(zname, metaKey, meta)) { + cout << "Disabled TSIG key " << name << " for " << zname << endl; + } else { + cerr << "Failure disabling TSIG key " << name << " for " << zname << endl; + return 1; + } + return 0; + } else if (cmds[0]=="get-meta") { + UeberBackend B("default"); + if (cmds.size() < 2) { + cerr << "Syntax: " << cmds[0] << " zone [kind kind ..]" << endl; + return 1; + } + DNSName zone(cmds[1]); + vector keys; + DomainInfo di; + + if (!B.getDomainInfo(zone, di)) { + cerr << "Invalid zone '" << zone << "'" << endl; + return 1; + } + + if (cmds.size() > 2) { + keys.assign(cmds.begin() + 2, cmds.end()); + std::cout << "Metadata for '" << zone << "'" << endl; + for(const string kind : keys) { + vector meta; + meta.clear(); + if (B.getDomainMetadata(zone, kind, meta)) { + cout << kind << " = " << boost::join(meta, ", ") << endl; + } + } + } else { + std::map > meta; + std::cout << "Metadata for '" << zone << "'" << endl; + B.getAllDomainMetadata(zone, meta); + for(const auto& each_meta: meta) { + cout << each_meta.first << " = " << boost::join(each_meta.second, ", ") << endl; + } + } + return 0; + + } else if (cmds[0]=="set-meta" || cmds[0]=="add-meta") { + if (cmds.size() < 3) { + cerr << "Syntax: " << cmds[0] << " ZONE KIND [VALUE VALUE ..]" << endl; + return 1; + } + DNSName zone(cmds[1]); + string kind = cmds[2]; + static vector multiMetaWhitelist = {"ALLOW-AXFR-FROM", "ALLOW-DNSUPDATE-FROM", + "ALSO-NOTIFY", "TSIG-ALLOW-AXFR", "TSIG-ALLOW-DNSUPDATE", "GSS-ALLOW-AXFR-PRINCIPAL", + "PUBLISH-CDS"}; + bool clobber = true; + if (cmds[0] == "add-meta") { + clobber = false; + if (find(multiMetaWhitelist.begin(), multiMetaWhitelist.end(), kind) == multiMetaWhitelist.end() && kind.find("X-") != 0) { + cerr<<"Refusing to add metadata to single-value metadata "< meta(cmds.begin() + 3, cmds.end()); + return addOrSetMeta(zone, kind, meta, clobber); + } else if (cmds[0]=="hsm") { +#ifdef HAVE_P11KIT1 + UeberBackend B("default"); + if (cmds.size() < 2) { + cerr << "Missing sub-command for pdnsutil hsm"<< std::endl; + return 0; + } else if (cmds[1] == "assign") { + DNSCryptoKeyEngine::storvector_t storvect; + DomainInfo di; + std::vector keys; + + if (cmds.size() < 9) { + std::cout << "Usage: pdnsutil hsm assign ZONE ALGORITHM {ksk|zsk} MODULE TOKEN PIN LABEL (PUBLABEL)" << std::endl; + return 1; + } + + DNSName zone(cmds[2]); + + // verify zone + if (!B.getDomainInfo(zone, di)) { + cerr << "Unable to assign module to unknown zone '" << zone << "'" << std::endl; + return 1; + } + + int algorithm = DNSSECKeeper::shorthand2algorithm(cmds[3]); + if (algorithm<0) { + cerr << "Unable to use unknown algorithm '" << cmds[3] << "'" << std::endl; + return 1; + } + + int64_t id; + bool keyOrZone = (cmds[4] == "ksk" ? true : false); + string module = cmds[5]; + string slot = cmds[6]; + string pin = cmds[7]; + string label = cmds[8]; + string pub_label; + if (cmds.size() > 9) + pub_label = cmds[9]; + else + pub_label = label; + + std::ostringstream iscString; + iscString << "Private-key-format: v1.2" << std::endl << + "Algorithm: " << algorithm << std::endl << + "Engine: " << module << std::endl << + "Slot: " << slot << std::endl << + "PIN: " << pin << std::endl << + "Label: " << label << std::endl << + "PubLabel: " << pub_label << std::endl; + + DNSKEYRecordContent drc; + DNSSECPrivateKey dpk; + dpk.d_flags = (keyOrZone ? 257 : 256); + + shared_ptr dke(DNSCryptoKeyEngine::makeFromISCString(drc, iscString.str())); + if(!dke->checkKey()) { + cerr << "Invalid DNS Private Key in engine " << module << " slot " << slot << std::endl; + return 1; + } + dpk.setKey(dke); + + // make sure this key isn't being reused. + B.getDomainKeys(zone, keys); + id = -1; + + for(DNSBackend::KeyData& kd : keys) { + if (kd.content == iscString.str()) { + // it's this one, I guess... + id = kd.id; + break; + } + } + + if (id > -1) { + cerr << "You have already assigned this key with ID=" << id << std::endl; + return 1; + } + + if (!dk.addKey(zone, dpk, id)) { + cerr << "Unable to assign module slot to zone" << std::endl; + return 1; + } + + cerr << "Module " << module << " slot " << slot << " assigned to " << zone << " with key id " << id << endl; + + return 0; + } else if (cmds[1] == "create-key") { + + if (cmds.size() < 4) { + cerr << "Usage: pdnsutil hsm create-key ZONE KEY-ID [BITS]" << endl; + return 1; + } + DomainInfo di; + DNSName zone(cmds[2]); + unsigned int id; + int bits = 2048; + // verify zone + if (!B.getDomainInfo(zone, di)) { + cerr << "Unable to create key for unknown zone '" << zone << "'" << std::endl; + return 1; + } + + id = pdns_stou(cmds[3]); + std::vector keys; + if (!B.getDomainKeys(zone, keys)) { + cerr << "No keys found for zone " << zone << std::endl; + return 1; + } + + std::shared_ptr dke = nullptr; + // lookup correct key + for(DNSBackend::KeyData &kd : keys) { + if (kd.id == id) { + // found our key. + DNSKEYRecordContent dkrc; + dke = DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content); + } + } + + if (!dke) { + cerr << "Could not find key with ID " << id << endl; + return 1; + } + if (cmds.size() > 4) { + bits = pdns_stou(cmds[4]); + } + if (bits < 1) { + cerr << "Invalid bit size " << bits << "given, must be positive integer"; + return 1; + } + try { + dke->create(bits); + } catch (PDNSException& e) { + cerr << e.reason << endl; + return 1; + } + + cerr << "Key of size " << bits << " created" << std::endl; + return 0; + } +#else + cerr<<"PKCS#11 support not enabled"<getPrefix() == cmds[1]) src = b; + if (b->getPrefix() == cmds[2]) tgt = b; + } + if (!src) { + cerr<<"Unknown source backend '"<getPrefix()<<" to "<getPrefix()< domains; + + tgt->getAllDomains(&domains, true); + if (domains.size()>0) + throw PDNSException("Target backend has domain(s), please clean it first"); + + src->getAllDomains(&domains, true); + // iterate zones + for(const DomainInfo& di: domains) { + size_t nr,nc,nm,nk; + DomainInfo di_new; + DNSResourceRecord rr; + cout<<"Processing '"<createDomain(di.zone)) throw PDNSException("Failed to create zone"); + if (!tgt->getDomainInfo(di.zone, di_new)) throw PDNSException("Failed to create zone"); + tgt->setKind(di_new.zone, di.kind); + tgt->setAccount(di_new.zone,di.account); + string masters=""; + bool first = true; + for(const auto& master: di.masters) { + if (!first) + masters += ", "; + first = false; + masters += master.toStringWithPortExcept(53); + } + tgt->setMaster(di_new.zone, masters); + // move records + if (!src->list(di.zone, di.id, true)) throw PDNSException("Failed to list records"); + nr=0; + + tgt->startTransaction(di.zone, di_new.id); + + while(src->get(rr)) { + rr.domain_id = di_new.id; + if (!tgt->feedRecord(rr, DNSName())) throw PDNSException("Failed to feed record"); + nr++; + } + + // move comments + nc=0; + if (src->listComments(di.id)) { + Comment c; + while(src->getComment(c)) { + c.domain_id = di_new.id; + tgt->feedComment(c); + nc++; + } + } + // move metadata + nm=0; + std::map > meta; + if (src->getAllDomainMetadata(di.zone, meta)) { + for (const auto& i : meta) { + if (!tgt->setDomainMetadata(di.zone, i.first, i.second)) throw PDNSException("Failed to feed domain metadata"); + nm++; + } + } + // move keys + nk=0; + // temp var for KeyID + int64_t keyID; + std::vector keys; + if (src->getDomainKeys(di.zone, keys)) { + for(const DNSBackend::KeyData& k: keys) { + tgt->addDomainKey(di.zone, k, keyID); + nk++; + } + } + tgt->commitTransaction(); + cout<<"Moved "< tkeys; + if (src->getTSIGKeys(tkeys)) { + for(auto& tk: tkeys) { + if (!tgt->setTSIGKey(tk.name, tk.algorithm, tk.key)) throw PDNSException("Failed to feed TSIG key"); + ntk++; + } + } + cout<<"Moved "<getPrefix() == cmds[1]) db = b; + } + + if (!db) { + cerr<<"Unknown backend '"<directBackendCmd(*i); + } + + return 0; + } else { + cerr<<"Unknown command '"< // for 'operator+=()' +#include +#include + +#include +#include + +#include "pdns/dnssecinfra.hh" +#include "pdns/logger.hh" +#include "pdns/pdnsexception.hh" +#include "pdns/sha.hh" +#include "pdns/lock.hh" + +#ifdef HAVE_LIBCRYPTO_ECDSA +#include +#endif + +#include "pkcs11signers.hh" +/* TODO + + - list possible tokens and supported modes + - Engine: , Slot: , PIN: + - ECDSA support (how to test?) + +NB! If you do use this, here is a simple way to get softhsm working + +create /etc/pkcs11/modules/softhsm.module + +put + +module: /usr/lib/softhsm/libsofthsm.so +managed: yes + +in it. you need to use softhsm tools to manage this all. + +*/ + +#ifdef HAVE_P11KIT1_V2 +static CK_FUNCTION_LIST** p11_modules; +#endif + +// map for signing algorithms +static std::map dnssec2smech = boost::assign::map_list_of +(5, CKM_SHA1_RSA_PKCS) +(7, CKM_SHA1_RSA_PKCS) +(8, CKM_SHA256_RSA_PKCS) +(10, CKM_SHA512_RSA_PKCS) +(13, CKM_ECDSA) +(14, CKM_ECDSA); + +// map for hashing algorithms +static std::map dnssec2hmech = boost::assign::map_list_of +(5, CKM_SHA_1) +(7, CKM_SHA_1) +(8, CKM_SHA256) +(10, CKM_SHA512) +(13, CKM_SHA256) +(14, CKM_SHA384); + +typedef enum { Attribute_Byte, Attribute_Long, Attribute_String } CkaValueType; + +// Attribute handling +class P11KitAttribute { +private: + CK_ATTRIBUTE_TYPE type; + CK_BYTE ckByte; + CK_ULONG ckLong; + std::string ckString; + CkaValueType ckType; + unsigned char *buffer; + CK_ULONG buflen; +protected: + void Init() { + buffer = NULL; + buflen = 0; + }; +public: + P11KitAttribute(CK_ATTRIBUTE_TYPE type_, const std::string& value) { + Init(); + this->type = type_; + setString(value); + } + + P11KitAttribute(CK_ATTRIBUTE_TYPE type_, char value) { + Init(); + this->type = type_; + setByte(value); + } + + P11KitAttribute(CK_ATTRIBUTE_TYPE type_, unsigned char value) { + Init(); + this->type = type_; + setByte(value); + } + + P11KitAttribute(CK_ATTRIBUTE_TYPE type_, unsigned long value) { + Init(); + this->type = type_; + setLong(value); + } + + CkaValueType valueType() const { + return ckType; + } + + const std::string &str() const { + return ckString; + }; + + unsigned char byte() const { + return ckByte; + } + + unsigned long ulong() const { + return ckLong; + } + + void setString(const std::string& value) { + this->ckString = value; + this->ckType = Attribute_String; + } + + void setByte(char value) { + this->ckByte = value; + this->ckType = Attribute_Byte; + } + + void setByte(unsigned char value) { + this->ckByte = value; + this->ckType = Attribute_Byte; + } + + void setLong(unsigned long value) { + this->ckLong = value; + this->ckType = Attribute_Long; + } + +// this bit is used for getting attribute from object +// we provide a pointer for GetAttributeValue to write to + CK_BYTE_PTR allocate(CK_ULONG amount) { + buffer = new unsigned char[amount]; + buflen = amount; + return buffer; + } + +// and here we copy the results back and delete buffer + void commit(CK_ULONG amount) { + if (buffer) { + this->ckString.assign((char*)buffer, amount); + delete [] buffer; + } + buffer = NULL; + buflen = 0; + } + +// this is *writable* attribute (you write into it) + void wattr(CK_ATTRIBUTE_PTR attr) { + attr->type = type; + switch(ckType) { + case Attribute_Byte: { + attr->pValue = (void*)&ckByte; + attr->ulValueLen = 1; + break; + } + case Attribute_Long: { + attr->pValue = (void*)&ckLong; + attr->ulValueLen = sizeof(CK_ULONG); + break; + } + case Attribute_String: { + attr->pValue = buffer; + attr->ulValueLen = buflen; + } + }; + }; + +// this is *readable* attribute (you read from it) + void rattr(CK_ATTRIBUTE_PTR attr) const { + attr->type = type; + switch(ckType) { + case Attribute_Byte: { + attr->pValue = (void*)&ckByte; + attr->ulValueLen = 1; + break; + } + case Attribute_Long: { + attr->pValue = (void*)&ckLong; + attr->ulValueLen = sizeof(CK_ULONG); + break; + } + case Attribute_String: { + attr->pValue = (void*)ckString.c_str(); + attr->ulValueLen = ckString.size(); + } + }; + }; +}; + + +class Pkcs11Slot { + private: + bool d_logged_in; + CK_FUNCTION_LIST* d_functions; // module functions + CK_SESSION_HANDLE d_session; + CK_SLOT_ID d_slot; + CK_RV d_err; + pthread_mutex_t d_m; + + void logError(const std::string& operation) const { + if (d_err) { + std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X)") % operation % p11_kit_strerror(d_err) % d_err ); + g_log<d_m), NULL); + Lock l(&d_m); + + if ((d_err = d_functions->C_OpenSession(this->d_slot, CKF_SERIAL_SESSION|CKF_RW_SESSION, 0, 0, &(this->d_session)))) { + logError("C_OpenSession"); + throw PDNSException("Could not open session"); + } + // check if we need to login + if ((d_err = d_functions->C_GetTokenInfo(d_slot, &tokenInfo)) == 0) { + d_logged_in = !((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED); + } else { + logError("C_GetTokenInfo"); + throw PDNSException("Cannot get token info for slot " + std::to_string(slot)); + } + } + + bool Login(const std::string& pin) { + if (d_logged_in) return true; + + unsigned char *uPin = new unsigned char[pin.size()]; + memcpy(uPin, pin.c_str(), pin.size()); + d_err = d_functions->C_Login(this->d_session, CKU_USER, uPin, pin.size()); + memset(uPin, 0, pin.size()); + delete [] uPin; + logError("C_Login"); + + if (d_err == 0) { + d_logged_in = true; + } + + return d_logged_in; + } + + bool LoggedIn() const { return d_logged_in; } + + CK_SESSION_HANDLE& Session() { return d_session; } + + CK_FUNCTION_LIST* f() { return d_functions; } + + pthread_mutex_t *m() { return &d_m; } + + static std::shared_ptr GetSlot(const std::string& module, const string& tokenId); + static CK_RV HuntSlot(const string& tokenId, CK_SLOT_ID &slotId, _CK_SLOT_INFO* info, CK_FUNCTION_LIST* functions); +}; + +class Pkcs11Token { + private: + std::shared_ptr d_slot; + + CK_OBJECT_HANDLE d_public_key; + CK_OBJECT_HANDLE d_private_key; + CK_KEY_TYPE d_key_type; + + CK_ULONG d_bits; + std::string d_exponent; + std::string d_modulus; + std::string d_ec_point; + std::string d_ecdsa_params; + + std::string d_label; + std::string d_pub_label; + + bool d_loaded; + CK_RV d_err; + + void logError(const std::string& operation) const { + if (d_err) { + std::string msg = boost::str( boost::format("PKCS#11 operation %s failed: %s (0x%X)") % operation % p11_kit_strerror(d_err) % d_err ); + g_log<(obj.c_str()); + order = BN_new(); + if ((key = d2i_ECParameters(NULL, &in, obj.size())) != NULL && + EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) == 1) { + bits = BN_num_bits(order); + } + + BN_free(order); + if (key != NULL) + EC_KEY_free(key); + + if (bits == 0) + throw PDNSException("Unsupported EC key"); + + return bits; +#else + if (d_ecdsa_params == "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07") return 256; + else if (d_ecdsa_params == "\x06\x05\x2b\x81\x04\x00\x22") return 384; + else throw PDNSException("Unsupported EC key"); +#endif + } + + public: + Pkcs11Token(const std::shared_ptr& slot, const std::string& label, const std::string& pub_label); + ~Pkcs11Token(); + + bool Login(const std::string& pin) { + if (pin.empty()) return false; // no empty pin. + if (d_slot->Login(pin) == true) { + LoadAttributes(); + } + + return LoggedIn(); + } + + bool LoggedIn() { + if (d_loaded == false && d_slot->LoggedIn() == true) { + LoadAttributes(); + } + return d_slot->LoggedIn(); + } + + void LoadAttributes() { + Lock l(d_slot->m()); + std::vector attr; + std::vector key; + attr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY)); +// attr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); + attr.push_back(P11KitAttribute(CKA_LABEL, d_label)); + FindObjects2(attr, key, 1); + if (key.size() == 0) { + g_log<& pubAttributes, std::vector& privAttributes, CK_OBJECT_HANDLE_PTR pubKey, CK_OBJECT_HANDLE_PTR privKey) { + { + Lock l(d_slot->m()); + + size_t k; + CK_ATTRIBUTE_PTR pubAttr, privAttr; + pubAttr = new CK_ATTRIBUTE[pubAttributes.size()]; + privAttr = new CK_ATTRIBUTE[privAttributes.size()]; + + k = 0; + for(P11KitAttribute& attribute : pubAttributes) { + attribute.rattr(pubAttr+k); + k++; + } + + k = 0; + for(P11KitAttribute& attribute : privAttributes) { + attribute.rattr(privAttr+k); + k++; + } + + d_err = this->d_slot->f()->C_GenerateKeyPair(d_slot->Session(), mechanism, pubAttr, pubAttributes.size(), privAttr, privAttributes.size(), pubKey, privKey); + logError("C_GenerateKeyPair"); + delete [] pubAttr; + delete [] privAttr; + } + + if (d_err == 0) LoadAttributes(); + + return d_err; + } + + int Sign(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); + + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most signatures. + + // perform signature + if ((d_err = this->d_slot->f()->C_SignInit(d_slot->Session(), mechanism, d_private_key))) { logError("C_SignInit"); return d_err; } + d_err = this->d_slot->f()->C_Sign(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen); + + if (!d_err) { + result.assign((char*)buffer, buflen); + } + + memset(buffer,0,sizeof buffer); + logError("C_Sign"); + return d_err; + } + + int Verify(const std::string& data, const std::string& signature, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); + + if ((d_err = this->d_slot->f()->C_VerifyInit(d_slot->Session(), mechanism, d_public_key))) { logError("C_VerifyInit"); return d_err; } + d_err = this->d_slot->f()->C_Verify(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), (unsigned char*)signature.c_str(), signature.size()); + logError("C_Verify"); + return d_err; + } + + int Digest(const std::string& data, std::string& result, CK_MECHANISM_PTR mechanism) { + Lock l(d_slot->m()); + + CK_BYTE buffer[1024]; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + if ((d_err = this->d_slot->f()->C_DigestInit(d_slot->Session(), mechanism))) { logError("C_DigestInit"); return d_err; } + d_err = this->d_slot->f()->C_Digest(d_slot->Session(), (unsigned char*)data.c_str(), data.size(), buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_Digest"); + return d_err; + } + + int DigestInit(CK_MECHANISM_PTR mechanism) { + d_err = d_slot->f()->C_DigestInit(d_slot->Session(), mechanism); + logError("C_DigestInit"); + return d_err; + } + + int DigestUpdate(const std::string& data) { + d_err = d_slot->f()->C_DigestUpdate(d_slot->Session(), (unsigned char*)data.c_str(), data.size()); + logError("C_DigestUpdate"); + return d_err; + } + + int DigestKey(std::string& result) { + Lock l(d_slot->m()); + CK_MECHANISM mech; + mech.mechanism = CKM_SHA_1; + + DigestInit(&mech); + + if (d_key_type == CKK_RSA) { + DigestUpdate(d_modulus); + DigestUpdate(d_exponent); + } else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) { + DigestUpdate(d_ec_point); + } + + DigestFinal(result); + + return d_err; + } + + int DigestFinal(std::string& result) { + CK_BYTE buffer[1024] = {0}; + CK_ULONG buflen = sizeof buffer; // should be enough for most digests + d_err = d_slot->f()->C_DigestFinal(d_slot->Session(), buffer, &buflen); + if (!d_err) { + result.assign((char*)buffer, buflen); + } + memset(buffer,0,sizeof buffer); + logError("C_DigestFinal"); + return d_err; + } + + int FindObjects(const std::vector& attributes, std::vector& objects, int maxobjects) { + Lock l(d_slot->m()); + return FindObjects2(attributes, objects, maxobjects); + } + + int FindObjects2(const std::vector& attributes, std::vector& objects, int maxobjects) { + CK_RV rv; + size_t k; + unsigned long count; + + CK_ATTRIBUTE_PTR attr; + CK_OBJECT_HANDLE_PTR handles = new CK_OBJECT_HANDLE[maxobjects]; + attr = new CK_ATTRIBUTE[attributes.size()]; + + k = 0; + for(const P11KitAttribute& attribute : attributes) { + attribute.rattr(attr+k); + k++; + } + + // perform search + d_err = this->d_slot->f()->C_FindObjectsInit(d_slot->Session(), attr, k); + + if (d_err) { + delete [] attr; + delete [] handles; + logError("C_FindObjectsInit"); + return d_err; + } + + count = maxobjects; + rv = d_err = this->d_slot->f()->C_FindObjects(d_slot->Session(), handles, maxobjects, &count); + objects.clear(); + + if (!rv) { + for(k=0;kd_slot->f()->C_FindObjectsFinal(d_slot->Session()); + logError("C_FindObjectsFinal"); + + return rv; + } + + int GetAttributeValue(const CK_OBJECT_HANDLE& object, std::vector& attributes) + { + Lock l(d_slot->m()); + return GetAttributeValue2(object, attributes); + } + + int GetAttributeValue2(const CK_OBJECT_HANDLE& object, std::vector& attributes) + { + size_t k; + CK_ATTRIBUTE_PTR attr; + attr = new CK_ATTRIBUTE[attributes.size()]; + + k = 0; + for(P11KitAttribute &attribute : attributes) { + attribute.wattr(attr+k); + k++; + } + + // round 1 - get attribute sizes + d_err = d_slot->f()->C_GetAttributeValue(d_slot->Session(), object, attr, attributes.size()); + logError("C_GetAttributeValue"); + if (d_err) { + delete [] attr; + return d_err; + } + + // then allocate memory + for(size_t idx=0; idx < attributes.size(); idx++) { + if (attributes[idx].valueType() == Attribute_String) { + attr[idx].pValue = attributes[idx].allocate(attr[idx].ulValueLen); + } + } + + // round 2 - get actual values + d_err = d_slot->f()->C_GetAttributeValue(d_slot->Session(), object, attr, attributes.size()); + logError("C_GetAttributeValue"); + + // copy values to map and release allocated memory + for(size_t idx=0; idx < attributes.size(); idx++) { + if (attributes[idx].valueType() == Attribute_String) { + attributes[idx].commit(attr[idx].ulValueLen); + } + } + + delete [] attr; + + return d_err; + }; + + const std::string& Modulus() { + return d_modulus; + } + + const std::string& Exponent() { + return d_exponent; + } + + const std::string& ECPoint() { + return d_ec_point; + } + + const std::string& ECParameters() { + return d_ecdsa_params; + } + + CK_KEY_TYPE KeyType() { + return d_key_type; + } + + CK_ULONG Bits() { + return d_bits; + } + + static std::shared_ptr GetToken(const std::string& module, const string& tokenId, const std::string& label, const std::string& pub_label); +}; + +static std::map > pkcs11_slots; +static std::map > pkcs11_tokens; + +CK_RV Pkcs11Slot::HuntSlot(const string& tokenId, CK_SLOT_ID &slotId, _CK_SLOT_INFO* info, CK_FUNCTION_LIST* functions) +{ + CK_RV err; + unsigned int i; + unsigned long slots; + _CK_TOKEN_INFO tinfo; + + // go thru all slots + // this is required by certain tokens, otherwise C_GetSlotInfo will not return a token + err = functions->C_GetSlotList(CK_FALSE, NULL_PTR, &slots); + if (err) { + g_log< Pkcs11Slot::GetSlot(const std::string& module, const string& tokenId) { + // see if we can find module + std::string sidx = module; + sidx.append("|"); + sidx.append(tokenId); + std::map >::iterator slotIter; + CK_RV err; + CK_FUNCTION_LIST* functions; + + // see if we have slot + if ((slotIter = pkcs11_slots.find(sidx)) != pkcs11_slots.end()) { + return slotIter->second; + } + +#ifdef HAVE_P11KIT1_V2 + functions = p11_kit_module_for_name(p11_modules, module.c_str()); +#else + functions = p11_kit_registered_name_to_module(module.c_str()); +#endif + if (functions == NULL) throw PDNSException("Cannot find PKCS#11 module " + module); + functions->C_Initialize(NULL); // initialize the module in case it hasn't been done yet. + + // try to locate a slot + _CK_SLOT_INFO info; + CK_SLOT_ID slotId; + + if ((err = Pkcs11Slot::HuntSlot(tokenId, slotId, &info, functions))) { + throw PDNSException(std::string("Cannot find PKCS#11 token ") + tokenId + std::string(" on module ") + module + std::string(": ") + boost::str( boost::format("%s (0x%X)") % p11_kit_strerror(err) % err)); + } + + // store slot + pkcs11_slots[sidx] = std::make_shared(functions, slotId); + + return pkcs11_slots[sidx]; +} + +std::shared_ptr Pkcs11Token::GetToken(const std::string& module, const string& tokenId, const std::string& label, const std::string& pub_label) { + // see if we can find module + std::string tidx = module; + tidx.append("|"); + tidx.append(tokenId); + tidx.append("|"); + tidx.append(label); + std::map >::iterator tokenIter; + if ((tokenIter = pkcs11_tokens.find(tidx)) != pkcs11_tokens.end()) return tokenIter->second; + + std::shared_ptr slot = Pkcs11Slot::GetSlot(module, tokenId); + pkcs11_tokens[tidx] = std::make_shared(slot, label, pub_label); + return pkcs11_tokens[tidx]; +} + +Pkcs11Token::Pkcs11Token(const std::shared_ptr& slot, const std::string& label, const std::string& pub_label) : + d_bits(0), + d_slot(slot), + d_label(label), + d_pub_label(pub_label), + d_err(0), + d_loaded(false) +{ + // open a session + if (this->d_slot->LoggedIn()) LoadAttributes(); +} + +Pkcs11Token::~Pkcs11Token() { +} + +bool PKCS11ModuleSlotLogin(const std::string& module, const string& tokenId, const std::string& pin) +{ + std::shared_ptr slot; + slot = Pkcs11Slot::GetSlot(module, tokenId); + if (slot->LoggedIn()) return true; // no point failing + return slot->Login(pin); +} + +PKCS11DNSCryptoKeyEngine::PKCS11DNSCryptoKeyEngine(unsigned int algorithm): DNSCryptoKeyEngine(algorithm) {} +PKCS11DNSCryptoKeyEngine::~PKCS11DNSCryptoKeyEngine() {} +PKCS11DNSCryptoKeyEngine::PKCS11DNSCryptoKeyEngine(const PKCS11DNSCryptoKeyEngine& orig) : DNSCryptoKeyEngine(orig.d_algorithm) {} + +void PKCS11DNSCryptoKeyEngine::create(unsigned int bits) { + std::vector pubAttr; + std::vector privAttr; + CK_MECHANISM mech; + CK_OBJECT_HANDLE pubKey, privKey; + CK_RV rv; + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + std::string pubExp("\000\001\000\001", 4); // 65537 + + pubAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PUBLIC_KEY)); + pubAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA)); + pubAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE)); + pubAttr.push_back(P11KitAttribute(CKA_ENCRYPT, (char)CK_TRUE)); + pubAttr.push_back(P11KitAttribute(CKA_VERIFY, (char)CK_TRUE)); + pubAttr.push_back(P11KitAttribute(CKA_WRAP, (char)CK_TRUE)); + pubAttr.push_back(P11KitAttribute(CKA_MODULUS_BITS, (unsigned long)bits)); + pubAttr.push_back(P11KitAttribute(CKA_PUBLIC_EXPONENT, pubExp)); + pubAttr.push_back(P11KitAttribute(CKA_LABEL, d_pub_label)); + + privAttr.push_back(P11KitAttribute(CKA_CLASS, (unsigned long)CKO_PRIVATE_KEY)); + privAttr.push_back(P11KitAttribute(CKA_KEY_TYPE, (unsigned long)CKK_RSA)); + privAttr.push_back(P11KitAttribute(CKA_TOKEN, (char)CK_TRUE)); + privAttr.push_back(P11KitAttribute(CKA_PRIVATE, (char)CK_TRUE)); +// privAttr.push_back(P11KitAttribute(CKA_SUBJECT, "CN=keygen")); + privAttr.push_back(P11KitAttribute(CKA_ID, "\x01\x02\x03\x04")); // this is mandatory if you want to export anything + privAttr.push_back(P11KitAttribute(CKA_SENSITIVE, (char)CK_TRUE)); + privAttr.push_back(P11KitAttribute(CKA_DECRYPT, (char)CK_TRUE)); + privAttr.push_back(P11KitAttribute(CKA_SIGN, (char)CK_TRUE)); + privAttr.push_back(P11KitAttribute(CKA_UNWRAP, (char)CK_TRUE)); + privAttr.push_back(P11KitAttribute(CKA_LABEL, d_label)); + + mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + if ((rv = d_slot->GenerateKeyPair(&mech, pubAttr, privAttr, &pubKey, &privKey))) { + throw PDNSException("Keypair generation failed"); + } +}; + +std::string PKCS11DNSCryptoKeyEngine::sign(const std::string& msg) const { + std::string result; + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + CK_MECHANISM mech; + mech.mechanism = dnssec2smech[d_algorithm]; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + if (mech.mechanism == CKM_ECDSA) { + if (d_slot->Sign(this->hash(msg), result, &mech)) throw PDNSException("Could not sign data"); + } else { + if (d_slot->Sign(msg, result, &mech)) throw PDNSException("Could not sign data"); + } + return result; +}; + +std::string PKCS11DNSCryptoKeyEngine::hash(const std::string& msg) const { + std::string result; + CK_MECHANISM mech; + mech.mechanism = dnssec2hmech[d_algorithm]; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + if (d_slot->Digest(msg, result, &mech)) { + g_log< d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + CK_MECHANISM mech; + mech.mechanism = dnssec2smech[d_algorithm]; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + if (mech.mechanism == CKM_ECDSA) { + return (d_slot->Verify(this->hash(msg), signature, &mech)==0); + } else { + return (d_slot->Verify(msg, signature, &mech) == 0); + } +}; + +std::string PKCS11DNSCryptoKeyEngine::getPubKeyHash() const { + // find us a public key + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + std::string result; + if (d_slot->DigestKey(result) == 0) return result; + throw PDNSException("Could not digest key (maybe it's missing?)"); +}; + +std::string PKCS11DNSCryptoKeyEngine::getPublicKeyString() const { + std::string result(""); + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + if (d_slot->KeyType() == CKK_RSA) { + if (d_slot->Exponent().length() < 255) { + result.assign(1, (char) (unsigned int) d_slot->Exponent().length()); + } else { + result.assign(1, 0); + uint16_t len=htons(d_slot->Exponent().length()); + result.append((char*)&len, 2); + } + result.append(d_slot->Exponent()); + result.append(d_slot->Modulus()); + } else { + result.append(d_slot->ECPoint()); + } + return result; +}; + +int PKCS11DNSCryptoKeyEngine::getBits() const { + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Not logged in to token"); + + return d_slot->Bits(); +}; + +DNSCryptoKeyEngine::storvector_t PKCS11DNSCryptoKeyEngine::convertToISCVector() const { + storvector_t storvect; + typedef std::vector > outputs_t; + outputs_t outputs; + + boost::assign::push_back(storvect) + (make_pair("Algorithm", std::to_string(d_algorithm))) + (make_pair("Engine", d_module)) + (make_pair("Slot", d_slot_id)) + (make_pair("PIN", d_pin)) + (make_pair("Label", d_label)) + (make_pair("PubLabel", d_pub_label)); + return storvect; +}; + +void PKCS11DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, stormap_t& stormap) { + drc.d_algorithm = pdns_stou(stormap["algorithm"]); + d_module = stormap["engine"]; + d_slot_id = stormap["slot"]; + boost::trim(d_slot_id); + d_pin = stormap["pin"]; + d_label = stormap["label"]; + if (stormap.find("publabel") != stormap.end()) + d_pub_label = stormap["publabel"]; + else + d_pub_label = d_label; + // validate parameters + + std::shared_ptr d_slot; + d_slot = Pkcs11Token::GetToken(d_module, d_slot_id, d_label, d_pub_label); + if (d_pin != "" && d_slot->LoggedIn() == false) + if (d_slot->Login(d_pin) == false) + throw PDNSException("Could not log in to token (PIN wrong?)"); +}; + +std::shared_ptr PKCS11DNSCryptoKeyEngine::maker(unsigned int algorithm) +{ + return std::make_shared(algorithm); +} + +// this is called during program startup +namespace { + static struct LoaderStruct + { + LoaderStruct() + { +#ifdef HAVE_P11KIT1_V2 + p11_modules = p11_kit_modules_load_and_initialize(0); +#else + p11_kit_initialize_registered(); +#endif + }; + ~LoaderStruct() { +#ifdef HAVE_P11KIT1_V2 + p11_kit_modules_release(p11_modules); +#else + p11_kit_finalize_registered(); +#endif + }; + } loaderPkcs11; +} diff --git a/pdns/pkcs11signers.hh b/pdns/pkcs11signers.hh new file mode 100644 index 0000000..094eddf --- /dev/null +++ b/pdns/pkcs11signers.hh @@ -0,0 +1,71 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_PKCS11SIGNERS_HH +#define PDNS_PKCS11SIGNERS_HH + +class PKCS11DNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ + protected: + std::string d_module; + std::string d_slot_id; + std::string d_pin; + std::string d_label; + std::string d_pub_label; + + public: + PKCS11DNSCryptoKeyEngine(unsigned int algorithm); + ~PKCS11DNSCryptoKeyEngine(); + + bool operator<(const PKCS11DNSCryptoKeyEngine& rhs) const + { + return false; + } + PKCS11DNSCryptoKeyEngine(const PKCS11DNSCryptoKeyEngine& orig); + + string getName() const override { return "P11 Kit PKCS#11"; }; + + void create(unsigned int bits) override; + + storvector_t convertToISCVector() const override; + + std::string sign(const std::string& msg) const override; + + std::string hash(const std::string& msg) const override; + + bool verify(const std::string& msg, const std::string& signature) const override; + + std::string getPubKeyHash() const override; + + std::string getPublicKeyString() const override; + int getBits() const override; + + void fromISCMap(DNSKEYRecordContent& drc, stormap_t& stormap) override; + + void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override { throw "Unimplemented"; }; + void fromPublicKeyString(const std::string& content) override { throw "Unimplemented"; }; + + static std::shared_ptr maker(unsigned int algorithm); +}; + +bool PKCS11ModuleSlotLogin(const std::string& module, const string& tokenId, const std::string& pin); + +#endif /* PDNS_PKCS11SIGNERS_HH */ diff --git a/pdns/pollmplexer.cc b/pdns/pollmplexer.cc new file mode 100644 index 0000000..399ad13 --- /dev/null +++ b/pdns/pollmplexer.cc @@ -0,0 +1,182 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "mplexer.hh" +#include "sstuff.hh" +#include +#include +#include "misc.hh" +#include "namespaces.hh" + +FDMultiplexer* FDMultiplexer::getMultiplexerSilent() +{ + FDMultiplexer* ret = nullptr; + for(const auto& i : FDMultiplexer::getMultiplexerMap()) { + try { + ret = i.second(); + return ret; + } + catch(const FDMultiplexerException& fe) { + } + catch(...) { + } + } + return ret; +} + + +class PollFDMultiplexer : public FDMultiplexer +{ +public: + PollFDMultiplexer() + {} + virtual ~PollFDMultiplexer() + { + } + + virtual int run(struct timeval* tv, int timeout=500) override; + virtual void getAvailableFDs(std::vector& fds, int timeout) override; + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override; + virtual void removeFD(callbackmap_t& cbmap, int fd) override; + + string getName() const override + { + return "poll"; + } +private: + vector preparePollFD() const; +}; + +static FDMultiplexer* make() +{ + return new PollFDMultiplexer(); +} + +static struct RegisterOurselves +{ + RegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(1, &make)); + } +} doIt; + +void PollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd) +{ + accountingAddFD(cbmap, fd, toDo, parameter, ttd); +} + +void PollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + if(d_inrun && d_iter->d_fd==fd) // trying to remove us! + ++d_iter; + + if(!cbmap.erase(fd)) + throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); +} + +vector PollFDMultiplexer::preparePollFD() const +{ + vector pollfds; + pollfds.reserve(d_readCallbacks.size() + d_writeCallbacks.size()); + + struct pollfd pollfd; + for(const auto& cb : d_readCallbacks) { + pollfd.fd = cb.d_fd; + pollfd.events = POLLIN; + pollfds.push_back(pollfd); + } + + for(const auto& cb : d_writeCallbacks) { + pollfd.fd = cb.d_fd; + pollfd.events = POLLOUT; + pollfds.push_back(pollfd); + } + + return pollfds; +} + +void PollFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) +{ + auto pollfds = preparePollFD(); + int ret = poll(&pollfds[0], pollfds.size(), timeout); + + if (ret < 0 && errno != EINTR) + throw FDMultiplexerException("poll returned error: " + stringerror()); + + for(const auto& pollfd : pollfds) { + if (pollfd.revents & POLLIN || pollfd.revents & POLLOUT) { + fds.push_back(pollfd.fd); + } + } +} + +int PollFDMultiplexer::run(struct timeval* now, int timeout) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + + auto pollfds = preparePollFD(); + + int ret=poll(&pollfds[0], pollfds.size(), timeout); + gettimeofday(now, 0); // MANDATORY! + + if(ret < 0 && errno!=EINTR) + throw FDMultiplexerException("poll returned error: "+stringerror()); + + d_iter=d_readCallbacks.end(); + d_inrun=true; + + for(const auto& pollfd : pollfds) { + if(pollfd.revents & POLLIN) { + d_iter=d_readCallbacks.find(pollfd.fd); + + if(d_iter != d_readCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + continue; // so we don't refind ourselves as writable! + } + } + else if(pollfd.revents & POLLOUT) { + d_iter=d_writeCallbacks.find(pollfd.fd); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + } + } + } + d_inrun=false; + return ret; +} + +#if 0 + +void acceptData(int fd, boost::any& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "< +#include +#endif +#include +#include "mplexer.hh" +#include "sstuff.hh" +#include + +#include "misc.hh" + +#include "namespaces.hh" + +class PortsFDMultiplexer : public FDMultiplexer +{ +public: + PortsFDMultiplexer(); + virtual ~PortsFDMultiplexer() + { + close(d_portfd); + } + + virtual int run(struct timeval* tv, int timeout=500); + + virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd=nullptr); + virtual void removeFD(callbackmap_t& cbmap, int fd); + string getName() + { + return "solaris completion ports"; + } +private: + int d_portfd; + boost::shared_array d_pevents; + static int s_maxevents; // not a hard maximum +}; + + +static FDMultiplexer* makePorts() +{ + return new PortsFDMultiplexer(); +} + +static struct PortsRegisterOurselves +{ + PortsRegisterOurselves() { + FDMultiplexer::getMultiplexerMap().insert(make_pair(0, &makePorts)); // priority 0! + } +} doItPorts; + + +int PortsFDMultiplexer::s_maxevents=1024; +PortsFDMultiplexer::PortsFDMultiplexer() : d_pevents(new port_event_t[s_maxevents]) +{ + d_portfd=port_create(); // not hard max + if(d_portfd < 0) + throw FDMultiplexerException("Setting up port: "+stringerror()); +} + +void PortsFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd) +{ + accountingAddFD(cbmap, fd, toDo, parameter, ttd); + + if(port_associate(d_portfd, PORT_SOURCE_FD, fd, (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT, 0) < 0) { + cbmap.erase(fd); + throw FDMultiplexerException("Adding fd to port set: "+stringerror()); + } +} + +void PortsFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd) +{ + if(!cbmap.erase(fd)) + throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer"); + + if(port_dissociate(d_portfd, PORT_SOURCE_FD, fd) < 0 && errno != ENOENT) // it appears under some circumstances, ENOENT will be returned, without this being an error. Apache has this same "fix" + throw FDMultiplexerException("Removing fd from port set: "+stringerror()); +} + +int PortsFDMultiplexer::run(struct timeval* now, int timeout) +{ + if(d_inrun) { + throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n"); + } + + struct timespec timeoutspec; + timeoutspec.tv_sec = time / 1000; + timeoutspec.tv_nsec = (time % 1000) * 1000000; + unsigned int numevents=1; + int ret= port_getn(d_portfd, d_pevents.get(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec); + + /* port_getn has an unusual API - (ret == -1, errno == ETIME) can + mean partial success; you must check (*numevents) in this case + and process anything in there, otherwise you'll never see any + events from that object again. We don't care about pure timeouts + (ret == -1, errno == ETIME, *numevents == 0) so we don't bother + with that case. */ + if(ret == -1 && errno!=ETIME) { + if(errno!=EINTR) + throw FDMultiplexerException("completion port_getn returned error: "+stringerror()); + // EINTR is not really an error + gettimeofday(now,0); + return 0; + } + gettimeofday(now,0); + if(!numevents) // nothing + return 0; + + d_inrun=true; + + for(unsigned int n=0; n < numevents; ++n) { + d_iter=d_readCallbacks.find(d_pevents[n].portev_object); + + if(d_iter != d_readCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + if(d_readCallbacks.count(d_pevents[n].portev_object) && port_associate(d_portfd, PORT_SOURCE_FD, d_pevents[n].portev_object, + POLLIN, 0) < 0) + throw FDMultiplexerException("Unable to add fd back to ports (read): "+stringerror()); + continue; // so we don't find ourselves as writable again + } + + d_iter=d_writeCallbacks.find(d_pevents[n].portev_object); + + if(d_iter != d_writeCallbacks.end()) { + d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter); + if(d_writeCallbacks.count(d_pevents[n].portev_object) && port_associate(d_portfd, PORT_SOURCE_FD, d_pevents[n].portev_object, + POLLOUT, 0) < 0) + throw FDMultiplexerException("Unable to add fd back to ports (write): "+stringerror()); + } + + } + + d_inrun=false; + return numevents; +} + +#if 0 +void acceptData(int fd, boost::any& parameter) +{ + cout<<"Have data on fd "<(parameter); + string packet; + IPEndpoint rem; + sock->recvFrom(packet, rem); + cout<<"Received "<set_qname(qname.toString()); + question->set_qtype(qtype); + question->set_qclass(qclass); + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setBytes(size_t bytes) +{ +#ifdef HAVE_PROTOBUF + d_message.set_inbytes(bytes); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setResponseCode(uint8_t rcode) +{ +#ifdef HAVE_PROTOBUF + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (response) { + response->set_rcode(rcode); + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setTime(time_t sec, uint32_t usec) +{ +#ifdef HAVE_PROTOBUF + d_message.set_timesec(sec); + d_message.set_timeusec(usec); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setQueryTime(time_t sec, uint32_t usec) +{ +#ifdef HAVE_PROTOBUF + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (response) { + response->set_querytimesec(sec); + response->set_querytimeusec(usec); + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setEDNSSubnet(const Netmask& subnet, uint8_t mask) +{ +#ifdef HAVE_PROTOBUF + if (!subnet.empty()) { + ComboAddress ca(subnet.getNetwork()); + ca.truncate(mask); + if (ca.sin4.sin_family == AF_INET) { + d_message.set_originalrequestorsubnet(&ca.sin4.sin_addr.s_addr, sizeof(ca.sin4.sin_addr.s_addr)); + } + else if (ca.sin4.sin_family == AF_INET6) { + d_message.set_originalrequestorsubnet(&ca.sin6.sin6_addr.s6_addr, sizeof(ca.sin6.sin6_addr.s6_addr)); + } + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::addTag(const std::string& strValue) +{ +#ifdef HAVE_PROTOBUF + + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (!response) + return; + + response->add_tags(strValue); + +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::addRR(const DNSName& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob) +{ +#ifdef HAVE_PROTOBUF + + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (!response) + return; + PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs(); + if (rr) { + rr->set_name(qname.toString()); + rr->set_type(uType); + rr->set_class_(uClass); + rr->set_ttl(uTTL); + rr->set_rdata(strBlob.c_str(), strBlob.size()); + } + +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME) +{ +#ifdef HAVE_PROTOBUF + if (len < sizeof(struct dnsheader)) + return; + + const struct dnsheader* dh = (const struct dnsheader*) packet; + + if (ntohs(dh->ancount) == 0) + return; + + if (ntohs(dh->qdcount) == 0) + return; + + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (!response) + return; + + std::string packetStr(packet, len); + PacketReader pr(packetStr); + + size_t idx = 0; + DNSName rrname; + uint16_t qdcount = ntohs(dh->qdcount); + uint16_t ancount = ntohs(dh->ancount); + uint16_t rrtype; + uint16_t rrclass; + string blob; + struct dnsrecordheader ah; + + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + + /* consume remaining qd if any */ + if (qdcount > 1) { + for(idx = 1; idx < qdcount; idx++) { + rrname = pr.getName(); + rrtype = pr.get16BitInt(); + rrclass = pr.get16BitInt(); + (void) rrtype; + (void) rrclass; + } + } + + /* parse AN */ + for (idx = 0; idx < ancount; idx++) { + rrname = pr.getName(); + pr.getDnsrecordheader(ah); + + if (ah.d_type == QType::A || ah.d_type == QType::AAAA) { + pr.xfrBlob(blob); + + PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs(); + if (rr) { + rr->set_name(rrname.toString()); + rr->set_type(ah.d_type); + rr->set_class_(ah.d_class); + rr->set_ttl(ah.d_ttl); + rr->set_rdata(blob.c_str(), blob.length()); + } + } else if (ah.d_type == QType::CNAME && includeCNAME) { + PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs(); + if (rr) { + rr->set_name(rrname.toString()); + rr->set_type(ah.d_type); + rr->set_class_(ah.d_class); + rr->set_ttl(ah.d_ttl); + DNSName target; + pr.xfrName(target, true); + rr->set_rdata(target.toString()); + } + } + else { + pr.xfrBlob(blob); + } + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setRequestor(const std::string& requestor) +{ +#ifdef HAVE_PROTOBUF + d_message.set_from(requestor); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setRequestor(const ComboAddress& requestor) +{ +#ifdef HAVE_PROTOBUF + if (requestor.sin4.sin_family == AF_INET) { + d_message.set_from(&requestor.sin4.sin_addr.s_addr, sizeof(requestor.sin4.sin_addr.s_addr)); + } + else if (requestor.sin4.sin_family == AF_INET6) { + d_message.set_from(&requestor.sin6.sin6_addr.s6_addr, sizeof(requestor.sin6.sin6_addr.s6_addr)); + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setRequestorId(const std::string& requestorId) +{ +#ifdef HAVE_PROTOBUF + d_message.set_requestorid(requestorId); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setDeviceId(const std::string& deviceId) +{ +#ifdef HAVE_PROTOBUF + d_message.set_deviceid(deviceId); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setServerIdentity(const std::string& serverId) +{ +#ifdef HAVE_PROTOBUF + d_message.set_serveridentity(serverId); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setResponder(const std::string& responder) +{ +#ifdef HAVE_PROTOBUF + d_message.set_to(responder); +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::setResponder(const ComboAddress& responder) +{ +#ifdef HAVE_PROTOBUF + if (responder.sin4.sin_family == AF_INET) { + d_message.set_to(&responder.sin4.sin_addr.s_addr, sizeof(responder.sin4.sin_addr.s_addr)); + } + else if (responder.sin4.sin_family == AF_INET6) { + d_message.set_to(&responder.sin6.sin6_addr.s6_addr, sizeof(responder.sin6.sin6_addr.s6_addr)); + } +#endif /* HAVE_PROTOBUF */ +} + +void DNSProtoBufMessage::serialize(std::string& data) const +{ +#ifdef HAVE_PROTOBUF + d_message.SerializeToString(&data); +#endif /* HAVE_PROTOBUF */ +} + +std::string DNSProtoBufMessage::toDebugString() const +{ +#ifdef HAVE_PROTOBUF + return d_message.DebugString(); +#else + return std::string(); +#endif /* HAVE_PROTOBUF */ +} + +#ifdef HAVE_PROTOBUF + +void DNSProtoBufMessage::setUUID(const boost::uuids::uuid& uuid) +{ + std::string* messageId = d_message.mutable_messageid(); + messageId->resize(uuid.size()); + std::copy(uuid.begin(), uuid.end(), messageId->begin()); +} + +void DNSProtoBufMessage::setInitialRequestID(const boost::uuids::uuid& uuid) +{ + std::string* messageId = d_message.mutable_initialrequestid(); + messageId->resize(uuid.size()); + std::copy(uuid.begin(), uuid.end(), messageId->begin()); +} + +void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id) +{ + struct timespec ts; + gettime(&ts, true); + setTime(ts.tv_sec, ts.tv_nsec / 1000); + + setUUID(uuid); + d_message.set_id(ntohs(id)); + + if (requestor) { + d_message.set_socketfamily(requestor->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6); + } + else if (responder) { + d_message.set_socketfamily(responder->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6); + } + + d_message.set_socketprotocol(isTCP ? PBDNSMessage_SocketProtocol_TCP : PBDNSMessage_SocketProtocol_UDP); + + if (responder) { + setResponder(*responder); + } + if (requestor) { + setRequestor(*requestor); + } +} + + +DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes) +{ + update(uuid, requestor, responder, isTCP, qid); + + setType(type); + + setBytes(bytes); + setQuestion(domain, qtype, qclass); +} + +void DNSProtoBufMessage::copyFrom(const DNSProtoBufMessage& msg) +{ + d_message.CopyFrom(msg.d_message); +} + +#endif /* HAVE_PROTOBUF */ diff --git a/pdns/protobuf.hh b/pdns/protobuf.hh new file mode 100644 index 0000000..c52af41 --- /dev/null +++ b/pdns/protobuf.hh @@ -0,0 +1,87 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include + +#include "config.h" + +#include "dnsname.hh" +#include "iputils.hh" + +#ifdef HAVE_PROTOBUF +#include +#include "dnsmessage.pb.h" +#endif /* HAVE_PROTOBUF */ + +class DNSProtoBufMessage +{ +public: + enum DNSProtoBufMessageType { + Query, + Response, + OutgoingQuery, + IncomingResponse + }; + + DNSProtoBufMessage() + { + } + + DNSProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType type); + + ~DNSProtoBufMessage() + { + } + + void setType(DNSProtoBufMessage::DNSProtoBufMessageType type); + void setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass); + void setEDNSSubnet(const Netmask& subnet, uint8_t mask=128); + void setBytes(size_t bytes); + void setTime(time_t sec, uint32_t usec); + void setQueryTime(time_t sec, uint32_t usec); + void setResponseCode(uint8_t rcode); + void addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME=false); + void serialize(std::string& data) const; + void setRequestor(const std::string& requestor); + void setRequestor(const ComboAddress& requestor); + void setResponder(const std::string& responder); + void setResponder(const ComboAddress& responder); + void setRequestorId(const std::string& requestorId); + void setDeviceId(const std::string& deviceId); + void setServerIdentity(const std::string& serverId); + std::string toDebugString() const; + void addTag(const std::string& strValue); + void addRR(const DNSName& qame, uint16_t utype, uint16_t uClass, uint32_t uTTl, const std::string& strBlob); + +#ifdef HAVE_PROTOBUF + DNSProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes); + void update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id); + void setUUID(const boost::uuids::uuid& uuid); + void setInitialRequestID(const boost::uuids::uuid& uuid); + void copyFrom(const DNSProtoBufMessage& msg); + +protected: + PBDNSMessage d_message; +#endif /* HAVE_PROTOBUF */ +}; diff --git a/pdns/qtype.cc b/pdns/qtype.cc new file mode 100644 index 0000000..31f3831 --- /dev/null +++ b/pdns/qtype.cc @@ -0,0 +1,116 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "dns.hh" +#include +#include +#include +#include +#include +#include "qtype.hh" +#include "misc.hh" + +static_assert(sizeof(QType) == 2, "QType is not 2 bytes in size, something is wrong!"); + +vector QType::names; +// XXX FIXME we need to do something with initializer order here! +QType::init QType::initializer; + +QType::QType() +{ + code = 0; +} + +bool QType::isSupportedType() { + for(vector::iterator pos=names.begin();possecond==code) + return true; + return false; +} + +bool QType::isMetadataType() { + if (code == QType::AXFR || + code == QType::MAILA || + code == QType::MAILB || + code == QType::TSIG || + code == QType::IXFR) + return true; + + return false; +} + +uint16_t QType::getCode() const +{ + return code; +} + +const string QType::getName() const +{ + vector::iterator pos; + for(pos=names.begin();possecond==code) + return pos->first; + + return "TYPE"+itoa(code); +} + +QType &QType::operator=(uint16_t n) +{ + code=n; + return *this; +} + +int QType::chartocode(const char *p) +{ + string P = toUpper(p); + vector::iterator pos; + + for(pos=names.begin(); pos < names.end(); ++pos) + if(pos->first == P) + return pos->second; + + if(*p=='#') { + return atoi(p+1); + } + + if(boost::starts_with(P, "TYPE")) + return atoi(p+4); + + return 0; +} + +QType &QType::operator=(const char *p) +{ + code=chartocode(p); + return *this; +} + +QType &QType::operator=(const string &s) +{ + code=chartocode(s.c_str()); + return *this; +} + + +QType::QType(uint16_t n): QType() +{ + code=n; +} diff --git a/pdns/qtype.hh b/pdns/qtype.hh new file mode 100644 index 0000000..d94238f --- /dev/null +++ b/pdns/qtype.hh @@ -0,0 +1,240 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef QTYPE_HH +#define QTYPE_HH +// $Id$ +#include +#include +#include "namespaces.hh" + +/** The QType class is meant to deal easily with the different kind of resource types, like 'A', 'NS', + * 'CNAME' etcetera. These types have both a name and a number. This class can seamlessly move between + * them. Use it like this: + +\code + QType t; + t="CNAME"; + cout< namenum; + static vector names; + + inline bool operator==(const QType &comp) const { + return(comp.code==code); + } + + inline bool operator!=(const QType &comp) const { + return(comp.code!=code); + } + + inline bool operator==(QType::typeenum comp) const { + return(comp==code); + } + + inline bool operator!=(QType::typeenum comp) const { + return(comp!=code); + } + + inline bool operator==(uint16_t comp) const { + return(comp==code); + } + + inline bool operator!=(uint16_t comp) const { + return(comp!=code); + } + +private: + static class init { + public: + void qtype_insert(const char* a, uint16_t num) + { + names.push_back(make_pair(string(a), num)); + } + + init() + { + qtype_insert("A", 1); + qtype_insert("NS", 2); + qtype_insert("CNAME", 5); + qtype_insert("SOA", 6); + qtype_insert("MB", 7); + qtype_insert("MG", 8); + qtype_insert("MR", 9); + qtype_insert("PTR", 12); + qtype_insert("HINFO", 13); + qtype_insert("MINFO", 14); + qtype_insert("MX", 15); + qtype_insert("TXT", 16); + qtype_insert("RP", 17); + qtype_insert("AFSDB", 18); + qtype_insert("SIG", 24); + qtype_insert("KEY", 25); + qtype_insert("AAAA", 28); + qtype_insert("LOC", 29); + qtype_insert("SRV", 33); + qtype_insert("NAPTR", 35); + qtype_insert("KX", 36); + qtype_insert("CERT", 37); + qtype_insert("A6", 38); + qtype_insert("DNAME", 39); + qtype_insert("OPT", 41); + qtype_insert("DS", 43); + qtype_insert("SSHFP", 44); + qtype_insert("IPSECKEY", 45); + qtype_insert("RRSIG", 46); + qtype_insert("NSEC", 47); + qtype_insert("DNSKEY", 48); + qtype_insert("DHCID", 49); + qtype_insert("NSEC3", 50); + qtype_insert("NSEC3PARAM", 51); + qtype_insert("TLSA", 52); + qtype_insert("SMIMEA", 53); + qtype_insert("RKEY", 57); + qtype_insert("CDS", 59); + qtype_insert("CDNSKEY", 60); + qtype_insert("OPENPGPKEY", 61); + qtype_insert("SPF", 99); + qtype_insert("EUI48", 108); + qtype_insert("EUI64", 109); + qtype_insert("TKEY", 249); +// qtype_insert("TSIG", 250); + qtype_insert("IXFR", 251); + qtype_insert("AXFR", 252); + qtype_insert("MAILB", 253); + qtype_insert("MAILA", 254); + qtype_insert("ANY", 255); + qtype_insert("URI", 256); + qtype_insert("CAA", 257); + qtype_insert("DLV", 32769); + qtype_insert("ADDR", 65400); + qtype_insert("ALIAS", 65401); + qtype_insert("LUA", 65402); + } + } initializer; + + uint16_t code; +}; + +struct QClass +{ + enum QClassEnum {IN=1, CHAOS=3, NONE=254, ANY=255}; +}; +#endif diff --git a/pdns/rcpgenerator.cc b/pdns/rcpgenerator.cc new file mode 100644 index 0000000..bebe2d3 --- /dev/null +++ b/pdns/rcpgenerator.cc @@ -0,0 +1,664 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "rcpgenerator.hh" +#include "ascii.hh" +#include "dnsparser.hh" +#include "misc.hh" +#include "utility.hh" +#include +#include + +#include +#include "base32.hh" +#include "base64.hh" +#include "namespaces.hh" + +RecordTextReader::RecordTextReader(const string& str, const DNSName& zone) : d_string(str), d_zone(zone), d_pos(0) +{ + /* remove whitespace */ + if(!d_string.empty() && ( dns_isspace(*d_string.begin()) || dns_isspace(*d_string.rbegin()) )) + boost::trim_if(d_string, dns_isspace); + d_end = d_string.size(); +} + +void RecordTextReader::xfr48BitInt(uint64_t &val) +{ + xfr64BitInt(val); + if (val > 281474976710655LL) + throw RecordTextException("Overflow reading 48 bit integer from record content"); // fixme improve +} + +void RecordTextReader::xfr64BitInt(uint64_t &val) +{ + skipSpaces(); + + if(!isdigit(d_string.at(d_pos))) + throw RecordTextException("expected digits at position "+std::to_string(d_pos)+" in '"+d_string+"'"); + + size_t pos; + val=std::stoull(d_string.substr(d_pos), &pos); + + d_pos += pos; +} + + +void RecordTextReader::xfr32BitInt(uint32_t &val) +{ + skipSpaces(); + + if(!isdigit(d_string.at(d_pos))) + throw RecordTextException("expected digits at position "+std::to_string(d_pos)+" in '"+d_string+"'"); + + size_t pos; + val=pdns_stou(d_string.c_str()+d_pos, &pos); + + d_pos += pos; +} + +void RecordTextReader::xfrTime(uint32_t &val) +{ + struct tm tm; + memset(&tm, 0, sizeof(tm)); + + uint64_t itmp; + xfr64BitInt(itmp); + + if (itmp <= (uint32_t)~0) { + // formatted as seconds since epoch, not as YYYYMMDDHHmmSS: + val = (uint32_t) itmp; + return; + } + + ostringstream tmp; + + tmp< 3) + throw RecordTextException(string("unable to parse IP address, too many dots")); + } + else if(isdigit(d_string.at(d_pos))) { + last_was_digit = true; + octet*=10; + octet+=d_string.at(d_pos) - '0'; + if(octet > 255) + throw RecordTextException("unable to parse IP address"); + } + else if(dns_isspace(d_string.at(d_pos))) + break; + else { + throw RecordTextException(string("unable to parse IP address, strange character: ")+d_string.at(d_pos)); + } + d_pos++; + if(d_pos == d_string.length()) + break; + } + if (count != 3) + throw RecordTextException(string("unable to parse IP address, not enough dots")); + if (!last_was_digit) + throw RecordTextException(string("unable to parse IP address, trailing dot")); + val<<=8; + val+=octet; + val=ntohl(val); +} + + +void RecordTextReader::xfrIP6(std::string &val) +{ + struct in6_addr tmpbuf; + + skipSpaces(); + + size_t len; + // lookup end of value - think of ::ffff encoding too, has dots in it! + for(len=0; + d_pos+len < d_string.length() && (isxdigit(d_string.at(d_pos+len)) || d_string.at(d_pos+len) == ':' || d_string.at(d_pos+len)=='.'); + len++); + + if(!len) + throw RecordTextException("while parsing IPv6 address, expected xdigits at position "+std::to_string(d_pos)+" in '"+d_string+"'"); + + // end of value is here, try parse as IPv6 + string address=d_string.substr(d_pos, len); + + if (inet_pton(AF_INET6, address.c_str(), &tmpbuf) != 1) { + throw RecordTextException("while parsing IPv6 address: '" + address + "' is invalid"); + } + + val = std::string((char*)tmpbuf.s6_addr, 16); + + d_pos += len; +} + +void RecordTextReader::xfrCAWithoutPort(uint8_t version, ComboAddress &val) +{ + if (version == 4) { + uint32_t ip; + xfrIP(ip); + val = makeComboAddressFromRaw(4, string((const char*) &ip, 4)); + } + else if (version == 6) { + string ip; + xfrIP6(ip); + val = makeComboAddressFromRaw(6, ip); + } + else throw RecordTextException("invalid address family"); +} + +void RecordTextReader::xfrCAPort(ComboAddress &val) +{ + uint16_t port; + xfr16BitInt(port); + val.sin4.sin_port = port; +} + +bool RecordTextReader::eof() +{ + return d_pos==d_end; +} + +void RecordTextReader::xfr16BitInt(uint16_t &val) +{ + uint32_t tmp; + xfr32BitInt(tmp); + val=tmp; + if(val!=tmp) + throw RecordTextException("Overflow reading 16 bit integer from record content"); // fixme improve +} + +void RecordTextReader::xfr8BitInt(uint8_t &val) +{ + uint32_t tmp; + xfr32BitInt(tmp); + val=tmp; + if(val!=tmp) + throw RecordTextException("Overflow reading 8 bit integer from record content"); // fixme improve +} + +// this code should leave all the escapes around +void RecordTextReader::xfrName(DNSName& val, bool, bool) +{ + skipSpaces(); + DNSName sval; + + const char* strptr=d_string.c_str(); + string::size_type begin_pos = d_pos; + while(d_pos < d_end) { + if(strptr[d_pos]!='\r' && dns_isspace(strptr[d_pos])) + break; + + d_pos++; + } + sval = DNSName(std::string(strptr+begin_pos, strptr+d_pos)); + + if(sval.empty()) + sval=d_zone; + else if(!d_zone.empty()) + sval+=d_zone; + val = sval; +} + +static bool isbase64(char c, bool acceptspace) +{ + if(dns_isspace(c)) + return acceptspace; + if(c >= '0' && c <= '9') + return true; + if(c >= 'a' && c <= 'z') + return true; + if(c >= 'A' && c <= 'Z') + return true; + if(c=='+' || c=='/' || c=='=') + return true; + return false; +} + +void RecordTextReader::xfrBlobNoSpaces(string& val, int len) { + skipSpaces(); + int pos=(int)d_pos; + const char* strptr=d_string.c_str(); + while(d_pos < d_end && isbase64(strptr[d_pos], false)) + d_pos++; + + string tmp; + tmp.assign(d_string.c_str()+pos, d_string.c_str() + d_pos); + boost::erase_all(tmp," "); + val.clear(); + B64Decode(tmp, val); + + if (len>-1 && val.size() != static_cast(len)) + throw RecordTextException("Record length "+std::to_string(val.size()) + " does not match expected length '"+std::to_string(len)); +} + +void RecordTextReader::xfrBlob(string& val, int) +{ + skipSpaces(); + int pos=(int)d_pos; + const char* strptr=d_string.c_str(); + while(d_pos < d_end && isbase64(strptr[d_pos], true)) + d_pos++; + + string tmp; + tmp.assign(d_string.c_str()+pos, d_string.c_str() + d_pos); + boost::erase_all(tmp," "); + val.clear(); + B64Decode(tmp, val); +} + + +static inline uint8_t hextodec(uint8_t val) +{ + if(val >= '0' && val<='9') + return val-'0'; + else if(val >= 'A' && val<='F') + return 10+(val-'A'); + else if(val >= 'a' && val<='f') + return 10+(val-'a'); + else + throw RecordTextException("Unknown hexadecimal character '"+std::to_string(val)+"'"); +} + + +void HEXDecode(const char* begin, const char* end, string& out) +{ + if(end - begin == 1 && *begin=='-') { + out.clear(); + return; + } + out.clear(); + out.reserve((end-begin)/2); + uint8_t mode=0, val=0; + for(; begin != end; ++begin) { + if(!isalnum(*begin)) + continue; + if(mode==0) { + val = 16*hextodec(*begin); + mode=1; + } else { + val += hextodec(*begin); + out.append(1, (char) val); + mode = 0; + val = 0; + } + } + if(mode) + out.append(1, (char) val); + +} + +void RecordTextReader::xfrHexBlob(string& val, bool keepReading) +{ + skipSpaces(); + int pos=(int)d_pos; + while(d_pos < d_end && (keepReading || !dns_isspace(d_string[d_pos]))) + d_pos++; + + HEXDecode(d_string.c_str()+pos, d_string.c_str() + d_pos, val); +} + +void RecordTextReader::xfrBase32HexBlob(string& val) +{ + skipSpaces(); + int pos=(int)d_pos; + while(d_pos < d_end && !dns_isspace(d_string[d_pos])) + d_pos++; + + val=fromBase32Hex(string(d_string.c_str()+pos, d_pos-pos)); +} + + +void RecordTextWriter::xfrBase32HexBlob(const string& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + d_string.append(toUpper(toBase32Hex(val))); +} + + +void RecordTextReader::xfrText(string& val, bool multi, bool lenField) +{ + val.clear(); + val.reserve(d_end - d_pos); + + while(d_pos != d_end) { + if(!val.empty()) + val.append(1, ' '); + + skipSpaces(); + if(d_string[d_pos]!='"') { // special case 'plenus' - without quotes + string::size_type pos = d_pos; + while(pos != d_end && isalnum(d_string[pos])) + pos++; + if(pos == d_end) { + val.append(1, '"'); + val.append(d_string.c_str() + d_pos, d_end - d_pos); + val.append(1, '"'); + d_pos = d_end; + break; + } + throw RecordTextException("Data field in DNS should start with quote (\") at position "+std::to_string(d_pos)+" of '"+d_string+"'"); + } + val.append(1, '"'); + while(++d_pos < d_end && d_string[d_pos]!='"') { + if(d_string[d_pos]=='\\' && d_pos+1!=d_end) { + val.append(1, d_string[d_pos++]); + } + val.append(1, d_string[d_pos]); + } + val.append(1,'"'); + if(d_pos == d_end) + throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'"); + d_pos++; + if(!multi) + break; + } +} + +void RecordTextReader::xfrUnquotedText(string& val, bool lenField) +{ + val.clear(); + val.reserve(d_end - d_pos); + + if(!val.empty()) + val.append(1, ' '); + + skipSpaces(); + val.append(1, d_string[d_pos]); + while(++d_pos < d_end && d_string[d_pos] != ' '){ + val.append(1, d_string[d_pos]); + } +} + +void RecordTextReader::xfrType(uint16_t& val) +{ + skipSpaces(); + int pos=(int)d_pos; + while(d_pos < d_end && !dns_isspace(d_string[d_pos])) + d_pos++; + + string tmp; + tmp.assign(d_string.c_str()+pos, d_string.c_str() + d_pos); + + val=DNSRecordContent::TypeToNumber(tmp); +} + + +void RecordTextReader::skipSpaces() +{ + const char* strptr = d_string.c_str(); + while(d_pos < d_end && dns_isspace(strptr[d_pos])) + d_pos++; + if(d_pos == d_end) + throw RecordTextException("missing field at the end of record content '"+d_string+"'"); +} + + +RecordTextWriter::RecordTextWriter(string& str, bool noDot) : d_string(str) +{ + d_string.clear(); + d_nodot=noDot; +} + +void RecordTextWriter::xfr48BitInt(const uint64_t& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + d_string+=std::to_string(val); +} + + +void RecordTextWriter::xfr32BitInt(const uint32_t& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + d_string+=std::to_string(val); +} + +void RecordTextWriter::xfrType(const uint16_t& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + d_string+=DNSRecordContent::NumberToType(val); +} + +// this function is on the fast path for the pdns_recursor +void RecordTextWriter::xfrIP(const uint32_t& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + char tmp[17]; + uint32_t ip=val; + uint8_t vals[4]; + + memcpy(&vals[0], &ip, sizeof(ip)); + + char *pos=tmp; + + for(int n=0; n < 4; ++n) { + if(vals[n]<10) { + *(pos++)=vals[n]+'0'; + } else if(vals[n] < 100) { + *(pos++)=(vals[n]/10) +'0'; + *(pos++)=(vals[n]%10) +'0'; + } else { + *(pos++)=(vals[n]/100) +'0'; + vals[n]%=100; + *(pos++)=(vals[n]/10) +'0'; + *(pos++)=(vals[n]%10) +'0'; + } + if(n!=3) + *(pos++)='.'; + } + *pos=0; + d_string.append(tmp, pos); +} + +void RecordTextWriter::xfrIP6(const std::string& val) +{ + char tmpbuf[16]; + char addrbuf[40]; + + if(!d_string.empty()) + d_string.append(1,' '); + + val.copy(tmpbuf,16); + + if (inet_ntop(AF_INET6, tmpbuf, addrbuf, sizeof addrbuf) == NULL) + throw RecordTextException("Unable to convert to ipv6 address"); + + d_string += std::string(addrbuf); +} + +void RecordTextWriter::xfrCAWithoutPort(uint8_t version, ComboAddress &val) +{ + string ip = val.toString(); + + if(!d_string.empty()) + d_string.append(1,' '); + + d_string += ip; +} + +void RecordTextWriter::xfrCAPort(ComboAddress &val) +{ + xfr16BitInt(val.sin4.sin_port); +} + +void RecordTextWriter::xfrTime(const uint32_t& val) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + struct tm tm; + time_t time=val; // Y2038 bug! + gmtime_r(&time, &tm); + + static const boost::format fmt("%04d%02d%02d" "%02d%02d%02d"); + d_string += boost::str(boost::format(fmt) % (tm.tm_year+1900) % (tm.tm_mon+1) % tm.tm_mday % tm.tm_hour % tm.tm_min % tm.tm_sec); +} + + +void RecordTextWriter::xfr16BitInt(const uint16_t& val) +{ + xfr32BitInt(val); +} + +void RecordTextWriter::xfr8BitInt(const uint8_t& val) +{ + xfr32BitInt(val); +} + +// should not mess with the escapes +void RecordTextWriter::xfrName(const DNSName& val, bool, bool noDot) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + if(d_nodot) { + d_string+=val.toStringRootDot(); + } + else + { + d_string+=val.toString(); + } +} + +void RecordTextWriter::xfrBlobNoSpaces(const string& val, int size) +{ + xfrBlob(val, size); +} + +void RecordTextWriter::xfrBlob(const string& val, int) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + d_string+=Base64Encode(val); +} + +void RecordTextWriter::xfrHexBlob(const string& val, bool) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + if(val.empty()) { + d_string.append(1,'-'); + return; + } + + string::size_type limit=val.size(); + char tmp[5]; + for(string::size_type n = 0; n < limit; ++n) { + snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)val[n]); + d_string+=tmp; + } +} + +void RecordTextWriter::xfrText(const string& val, bool multi, bool lenField) +{ + if(!d_string.empty()) + d_string.append(1,' '); + + d_string.append(val); +} + +void RecordTextWriter::xfrUnquotedText(const string& val, bool lenField) +{ + if(!d_string.empty()) + d_string.append(1,' '); + d_string.append(val); +} + +#ifdef TESTING + +int main(int argc, char**argv) +try +{ + RecordTextReader rtr(argv[1], argv[2]); + + unsigned int order, pref; + string flags, services, regexp, replacement; + string mx; + + rtr.xfrInt(order); + rtr.xfrInt(pref); + rtr.xfrText(flags); + rtr.xfrText(services); + rtr.xfrText(regexp); + rtr.xfrName(replacement); + + cout<<"order: "< +#include +#include + +#include "namespaces.hh" +#include "dnsname.hh" +#include "iputils.hh" + +class RecordTextException : public runtime_error +{ +public: + RecordTextException(const string& str) : runtime_error(str) + {} +}; + +class RecordTextReader +{ +public: + RecordTextReader(const string& str, const DNSName& zone=DNSName("")); + void xfr64BitInt(uint64_t& val); + void xfr48BitInt(uint64_t& val); + void xfr32BitInt(uint32_t& val); + void xfr16BitInt(uint16_t& val); + void xfr8BitInt(uint8_t& val); + + void xfrType(uint16_t& val); + void xfrIP(uint32_t& val); + void xfrIP6(std::string& val); + void xfrCAWithoutPort(uint8_t version, ComboAddress &val); + void xfrCAPort(ComboAddress &val); + void xfrTime(uint32_t& val); + + void xfrName(DNSName& val, bool compress=false, bool noDot=false); + void xfrText(string& val, bool multi=false, bool lenField=true); + void xfrUnquotedText(string& val, bool lenField=true); + void xfrHexBlob(string& val, bool keepReading=false); + void xfrBase32HexBlob(string& val); + + void xfrBlobNoSpaces(string& val, int len=-1); + void xfrBlob(string& val, int len=-1); + + const string getRemaining() const { + return d_string.substr(d_pos); + } + + bool eof(); +private: + string d_string; + DNSName d_zone; + string::size_type d_pos; + string::size_type d_end; + void skipSpaces(); +}; + +class RecordTextWriter +{ +public: + RecordTextWriter(string& str, bool noDot=false); + void xfr48BitInt(const uint64_t& val); + void xfr32BitInt(const uint32_t& val); + void xfr16BitInt(const uint16_t& val); + void xfr8BitInt(const uint8_t& val); + void xfrIP(const uint32_t& val); + void xfrIP6(const std::string& val); + void xfrCAWithoutPort(uint8_t version, ComboAddress &val); + void xfrCAPort(ComboAddress &val); + void xfrTime(const uint32_t& val); + void xfrBase32HexBlob(const string& val); + + void xfrType(const uint16_t& val); + void xfrName(const DNSName& val, bool compress=false, bool noDot=false); + void xfrText(const string& val, bool multi=false, bool lenField=true); + void xfrUnquotedText(const string& val, bool lenField=true); + void xfrBlobNoSpaces(const string& val, int len=-1); + void xfrBlob(const string& val, int len=-1); + void xfrHexBlob(const string& val, bool keepReading=false); + bool eof() { return true; }; + + const string getRemaining() const { + return ""; + } +private: + string& d_string; + bool d_nodot; +}; +#endif diff --git a/pdns/rec-lua-conf.hh b/pdns/rec-lua-conf.hh new file mode 100644 index 0000000..1cd2e62 --- /dev/null +++ b/pdns/rec-lua-conf.hh @@ -0,0 +1,93 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include + +#include "sholder.hh" +#include "sortlist.hh" +#include "filterpo.hh" +#include "validate.hh" + +struct ProtobufExportConfig +{ + std::set exportTypes = { QType::A, QType::AAAA, QType::CNAME }; + std::vector servers; + uint64_t maxQueuedEntries{100}; + uint16_t timeout{2}; + uint16_t reconnectWaitTime{1}; + bool asyncConnect{false}; + bool enabled{false}; + bool logQueries{true}; + bool logResponses{true}; + bool taggedOnly{false}; +}; + +struct FrameStreamExportConfig +{ + std::vector servers; + bool enabled{false}; + bool logQueries{true}; + bool logResponses{true}; + unsigned bufferHint{0}; + unsigned flushTimeout{0}; + unsigned inputQueueSize{0}; + unsigned outputQueueSize{0}; + unsigned queueNotifyThreshold{0}; + unsigned reopenInterval{0}; +}; + +struct TrustAnchorFileInfo { + uint32_t interval{24}; + std::string fname; +}; + +class LuaConfigItems +{ +public: + LuaConfigItems(); + SortList sortlist; + DNSFilterEngine dfe; + TrustAnchorFileInfo trustAnchorFileInfo; // Used to update the Trust Anchors from file periodically + map dsAnchors; + map negAnchors; + ProtobufExportConfig protobufExportConfig; + ProtobufExportConfig outgoingProtobufExportConfig; + FrameStreamExportConfig frameStreamExportConfig; + + /* we need to increment this every time the configuration + is reloaded, so we know if we need to reload the protobuf + remote loggers */ + uint64_t generation{0}; + uint8_t protobufMaskV4{32}; + uint8_t protobufMaskV6{128}; +}; + +extern GlobalStateHolder g_luaconfs; + +struct luaConfigDelayedThreads +{ + std::vector, boost::optional, bool, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, std::shared_ptr, std::string> > rpzMasterThreads; +}; + +void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads); +void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation); + diff --git a/pdns/receiver.cc b/pdns/receiver.cc new file mode 100644 index 0000000..c7b2af9 --- /dev/null +++ b/pdns/receiver.cc @@ -0,0 +1,636 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "packetcache.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIBSODIUM +#include +#endif +#include "opensslsigners.hh" + +#include "dns.hh" +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "dnspacket.hh" +#include "nameserver.hh" +#include "distributor.hh" +#include "logger.hh" +#include "arguments.hh" +#include "packethandler.hh" +#include "statbag.hh" +#include "tcpreceiver.hh" +#include "misc.hh" +#include "dynlistener.hh" +#include "dynhandler.hh" +#include "communicator.hh" +#include "dnsproxy.hh" +#include "utility.hh" +#include "common_startup.hh" +#include "dnsrecords.hh" +#include "version.hh" + +#ifdef HAVE_LUA_RECORDS +#include "minicurl.hh" +#endif /* HAVE_LUA_RECORDS */ + +time_t s_starttime; + +string s_programname="pdns"; // used in packethandler.cc + +const char *funnytext= +"*****************************************************************************\n"\ +"Ok, you just ran pdns_server through 'strings' hoping to find funny messages.\n"\ +"Well, you found one. \n"\ +"Two ions are flying through their particle accelerator, says the one to the\n" +"other 'I think I've lost an electron!' \n"\ +"So the other one says, 'Are you sure?'. 'YEAH! I'M POSITIVE!'\n"\ +" the pdns crew - pdns@powerdns.com\n" +"*****************************************************************************\n"; + + +// start (sys)logging + + +/** +\file receiver.cc +\brief The main loop of powerdns + +This file is where it all happens - main is here, as are the two pivotal threads qthread() and athread() +*/ + +void daemonize(void) +{ + if(fork()) + exit(0); // bye bye + + setsid(); + + int i=open("/dev/null",O_RDWR); /* open stdin */ + if(i < 0) + g_log<&parts, pid_t ppid) +{ + kill(cpid, SIGKILL); // why? + kill(cpid, SIGKILL); // why? + sleep(1); + return "ok"; +} + +static string DLRestHandler(const vector&parts, pid_t ppid) +{ + string line; + + for(vector::const_iterator i=parts.begin();i!=parts.end();++i) { + if(i!=parts.begin()) + line.append(1,' '); + line.append(*i); + } + line.append(1,'\n'); + + Lock l(&g_guardian_lock); + + try { + writen2(g_fd1[1],line.c_str(),line.size()+1); + } + catch(PDNSException &ae) { + return "Error communicating with instance: "+ae.reason; + } + char mesg[512]; + string response; + while(fgets(mesg,sizeof(mesg),g_fp)) { + if(*mesg=='\0') + break; + response+=mesg; + } + boost::trim_right(response); + return response; +} + + + +static int guardian(int argc, char **argv) +{ + if(isGuarded(argv)) + return 0; + + int infd=0, outfd=1; + + DynListener dlg(s_programname); + dlg.registerFunc("QUIT",&DLQuitHandler, "quit daemon"); + dlg.registerFunc("CYCLE",&DLCycleHandler, "restart instance"); + dlg.registerFunc("PING",&DLPingHandler, "ping guardian"); + dlg.registerFunc("STATUS",&DLStatusHandler, "get instance status from guardian"); + dlg.registerRestFunc(&DLRestHandler); + dlg.go(); + string progname=argv[0]; + + bool first=true; + cpid=0; + + pthread_mutex_lock(&g_guardian_lock); + + for(;;) { + int pid; + setStatus("Launching child"); + + if(pipe(g_fd1)<0 || pipe(g_fd2)<0) { + g_log<((progname+"-instance").c_str())); + for(n=1;n0) { // parent + close(g_fd1[0]); + close(g_fd2[1]); + + if(first) { + first=false; + signal(SIGTERM, takedown); + + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGUSR2, SIG_IGN); + + writePid(); + } + pthread_mutex_unlock(&g_guardian_lock); + int status; + cpid=pid; + for(;;) { + int ret=waitpid(pid,&status,WNOHANG); + + if(ret<0) { + g_log< +static void tbhandler(int num) +{ + g_log<= 0) + g_log.setFacility(val); + else + g_log< modules; + + stringtok(modules,::arg()["load-modules"], ", "); + if (!UeberBackend::loadModules(modules, ::arg()["module-dir"])) { + exit(1); + } + } + + BackendMakers().launch(::arg()["launch"]); // vrooooom! + + if(!::arg().getCommands().empty()) { + cerr<<"Fatal: non-option on the command line, perhaps a '--setting=123' statement missed the '='?"<"); + DynListener::registerFunc("RPING",&DLPingHandler, "ping instance"); + DynListener::registerFunc("QUIT",&DLRQuitHandler, "quit daemon"); + DynListener::registerFunc("UPTIME",&DLUptimeHandler, "get instance uptime"); + DynListener::registerFunc("NOTIFY-HOST",&DLNotifyHostHandler, "notify host for specific domain", " "); + DynListener::registerFunc("NOTIFY",&DLNotifyHandler, "queue a notification", ""); + DynListener::registerFunc("RELOAD",&DLReloadHandler, "reload all zones"); + DynListener::registerFunc("REDISCOVER",&DLRediscoverHandler, "discover any new zones"); + DynListener::registerFunc("VERSION",&DLVersionHandler, "get instance version"); + DynListener::registerFunc("PURGE",&DLPurgeHandler, "purge entries from packet cache", "[]"); + DynListener::registerFunc("CCOUNTS",&DLCCHandler, "get cache statistics"); + DynListener::registerFunc("QTYPES", &DLQTypesHandler, "get QType statistics"); + DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes"); + DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes"); + DynListener::registerFunc("SET",&DLSettingsHandler, "set config variables", " "); + DynListener::registerFunc("RETRIEVE",&DLNotifyRetrieveHandler, "retrieve slave domain", ""); + DynListener::registerFunc("CURRENT-CONFIG",&DLCurrentConfigHandler, "retrieve the current configuration"); + DynListener::registerFunc("LIST-ZONES",&DLListZones, "show list of zones", "[master|slave|native]"); + DynListener::registerFunc("TOKEN-LOGIN", &DLTokenLogin, "Login to a PKCS#11 token", " "); + + if(!::arg()["tcp-control-address"].empty()) { + DynListener* dlTCP=new DynListener(ComboAddress(::arg()["tcp-control-address"], ::arg().asNum("tcp-control-port"))); + dlTCP->go(); + } + + // reparse, with error checking + if(!::arg().mustDo("no-config")) + ::arg().file(configname.c_str()); + ::arg().parse(argc,argv); + + if(::arg()["server-id"].empty()) { + char tmp[128]; + if(gethostname(tmp, sizeof(tmp)-1) == 0) { + ::arg().set("server-id")=tmp; + } else { + g_log<(); // this fails when we are not root, throws exception + g_udpReceivers.push_back(N); + + size_t rthreads = ::arg().asNum("receiver-threads", 1); + if (rthreads > 1 && N->canReusePort()) { + g_udpReceivers.resize(rthreads); + + for (size_t idx = 1; idx < rthreads; idx++) { + try { + g_udpReceivers[idx] = std::make_shared(true); + } + catch(const PDNSException& e) { + g_log<(); + } + catch(const ArgException &A) { + g_log< +#include +#include "dns.hh" +#include "qtype.hh" +#include "misc.hh" +#include "dnsname.hh" +#include +#include "dnsrecords.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include "iputils.hh" +#include "validate.hh" +#undef max + +#include "namespaces.hh" +using namespace ::boost::multi_index; + +class MemRecursorCache : public boost::noncopyable // : public RecursorCache +{ +public: + MemRecursorCache() : d_cachecachevalid(false) + { + cacheHits = cacheMisses = 0; + } + unsigned int size() const; + unsigned int bytes() const; + size_t ecsIndexSize() const; + + int32_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures=nullptr, std::vector>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr, bool* wasAuth=nullptr); + + void replace(time_t, const DNSName &qname, const QType& qt, const vector& content, const vector>& signatures, const std::vector>& authorityRecs, bool auth, boost::optional ednsmask=boost::none, vState state=Indeterminate); + + void doPrune(unsigned int keep); + uint64_t doDump(int fd); + + int doWipeCache(const DNSName& name, bool sub, uint16_t qtype=0xffff); + bool doAgeCache(time_t now, const DNSName& name, uint16_t qtype, uint32_t newTTL); + bool updateValidationStatus(time_t now, const DNSName &qname, const QType& qt, const ComboAddress& who, bool requireAuth, vState newState, boost::optional capTTD); + + uint64_t cacheHits, cacheMisses; + +private: + + struct CacheEntry + { + CacheEntry(const boost::tuple& key, bool auth): + d_qname(key.get<0>()), d_netmask(key.get<2>()), d_state(Indeterminate), d_ttd(0), d_qtype(key.get<1>()), d_auth(auth) + { + } + + typedef vector> records_t; + time_t getTTD() const + { + return d_ttd; + } + + records_t d_records; + std::vector> d_signatures; + std::vector> d_authorityRecs; + DNSName d_qname; + Netmask d_netmask; + mutable vState d_state; + mutable time_t d_ttd; + uint16_t d_qtype; + bool d_auth; + }; + + /* The ECS Index (d_ecsIndex) keeps track of whether there is any ECS-specific + entry for a given (qname,qtype) entry in the cache (d_cache), and if so + provides a NetmaskTree of those ECS entries. + This allows figuring out quickly if we should look for an entry + specific to the requestor IP, and if so which entry is the most + specific one. + Keeping the entries in the regular cache is currently necessary + because of the way we manage expired entries (moving them to the + front of the expunge queue to be deleted at a regular interval). + */ + class ECSIndexEntry + { + public: + ECSIndexEntry(const DNSName& qname, uint16_t qtype): d_nmt(true), d_qname(qname), d_qtype(qtype) + { + } + + Netmask lookupBestMatch(const ComboAddress& addr) const + { + Netmask result = Netmask(); + + const auto best = d_nmt.lookup(addr); + if (best != nullptr) { + result = best->first; + } + + return result; + } + + void addMask(const Netmask& nm) const + { + d_nmt.insert(nm).second = true; + } + + void removeNetmask(const Netmask& nm) const + { + d_nmt.erase(nm); + } + + bool isEmpty() const + { + return d_nmt.empty(); + } + + mutable NetmaskTree d_nmt; + DNSName d_qname; + uint16_t d_qtype; + }; + + struct HashedTag {}; + struct SequencedTag {}; + struct NameOnlyHashedTag {}; + struct OrderedTag {}; + + typedef multi_index_container< + CacheEntry, + indexed_by < + ordered_unique, + composite_key< + CacheEntry, + member, + member, + member + >, + composite_key_compare, std::less > + >, + sequenced >, + hashed_non_unique, + member + > + > + > cache_t; + + typedef MemRecursorCache::cache_t::index::type::iterator OrderedTagIterator_t; + typedef MemRecursorCache::cache_t::index::type::iterator NameOnlyHashedTagIterator_t; + + typedef multi_index_container< + ECSIndexEntry, + indexed_by < + hashed_unique , + composite_key< + ECSIndexEntry, + member, + member + > + >, + ordered_unique, + composite_key< + ECSIndexEntry, + member, + member + >, + composite_key_compare > + > + > + > ecsIndex_t; + + cache_t d_cache; + ecsIndex_t d_ecsIndex; + std::pair d_cachecache; + DNSName d_cachedqname; + bool d_cachecachevalid; + + bool entryMatches(OrderedTagIterator_t& entry, uint16_t qt, bool requireAuth, const ComboAddress& who); + std::pair getEntries(const DNSName &qname, const QType& qt); + cache_t::const_iterator getEntryUsingECSIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who); + int32_t handleHit(OrderedTagIterator_t& entry, const DNSName& qname, const ComboAddress& who, vector* res, vector>* signatures, std::vector>* authorityRecs, bool* variable, vState* state, bool* wasAuth); + +public: + void preRemoval(const CacheEntry& entry) + { + if (entry.d_netmask.empty()) { + return; + } + + auto key = tie(entry.d_qname, entry.d_qtype); + auto ecsIndexEntry = d_ecsIndex.find(key); + if (ecsIndexEntry != d_ecsIndex.end()) { + ecsIndexEntry->removeNetmask(entry.d_netmask); + if (ecsIndexEntry->isEmpty()) { + d_ecsIndex.erase(ecsIndexEntry); + } + } + } +}; +#endif diff --git a/pdns/resolver.cc b/pdns/resolver.cc new file mode 100644 index 0000000..fb8c830 --- /dev/null +++ b/pdns/resolver.cc @@ -0,0 +1,582 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include "resolver.hh" +#include +#include +#include +#include +#include "misc.hh" +#include +#include +#include "dnsrecords.hh" +#include +#include +#include +#include +#include "dns.hh" +#include "qtype.hh" + +#include "pdnsexception.hh" +#include "arguments.hh" +#include "base64.hh" +#include "dnswriter.hh" +#include "dnsparser.hh" + + +#include "dns_random.hh" +#include +#include "gss_context.hh" +#include "namespaces.hh" + +int makeQuerySocket(const ComboAddress& local, bool udpOrTCP, bool nonLocalBind) +{ + ComboAddress ourLocal(local); + + int sock=socket(ourLocal.sin4.sin_family, udpOrTCP ? SOCK_DGRAM : SOCK_STREAM, 0); + if(sock < 0) { + if(errno == EAFNOSUPPORT && local.sin4.sin_family == AF_INET6) { + return -1; + } + unixDie("Creating local resolver socket for "+ourLocal.toString()); + } + + setCloseOnExec(sock); + + if(nonLocalBind) + Utility::setBindAny(local.sin4.sin_family, sock); + + if(udpOrTCP) { + // udp, try hard to bind an unpredictable port + int tries=10; + while(--tries) { + ourLocal.sin4.sin_port = htons(10000+(dns_random(10000))); + + if (::bind(sock, (struct sockaddr *)&ourLocal, ourLocal.getSocklen()) >= 0) + break; + } + // cerr<<"bound udp port "<=0) + close(locals["default4"]); + if(locals["default6"]>=0) + close(locals["default6"]); + throw; + } +} + +Resolver::~Resolver() +{ + for (auto& iter: locals) { + if (iter.second >= 0) + close(iter.second); + } +} + +uint16_t Resolver::sendResolve(const ComboAddress& remote, const ComboAddress& local, + const DNSName &domain, int type, int *localsock, bool dnssecOK, + const DNSName& tsigkeyname, const DNSName& tsigalgorithm, + const string& tsigsecret) +{ + uint16_t randomid; + vector packet; + DNSPacketWriter pw(packet, domain, type); + pw.getHeader()->id = randomid = dns_random(0xffff); + + if(dnssecOK) { + pw.addOpt(2800, 0, EDNSOpts::DNSSECOK); + pw.commit(); + } + + if(!tsigkeyname.empty()) { + // cerr<<"Adding TSIG to notification, key name: '"<::iterator lptr; + + // reuse an existing local socket or make a new one + if ((lptr = locals.find(lstr)) != locals.end()) { + sock = lptr->second; + } else { + // try to make socket + sock = makeQuerySocket(local, true); + if (sock < 0) + throw ResolverException("Unable to create local socket on "+lstr+" to "+remote.toStringWithPort()+": "+stringerror()); + setNonBlocking( sock ); + locals[lstr] = sock; + } + } + + if (localsock != nullptr) { + *localsock = sock; + } + if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) { + throw ResolverException("Unable to ask query of "+remote.toStringWithPort()+": "+stringerror()); + } + return randomid; +} + +static int parseResult(MOADNSParser& mdp, const DNSName& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result) +{ + result->clear(); + + if(mdp.d_header.rcode) + return mdp.d_header.rcode; + + if(origQname.countLabels()) { // not AXFR + if(mdp.d_header.id != id) + throw ResolverException("Remote nameserver replied with wrong id"); + if(mdp.d_header.qdcount != 1) + throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp.d_header.qdcount)+")"); + if(mdp.d_qname != origQname) + throw ResolverException(string("resolver: received an answer to another question (")+mdp.d_qname.toLogString()+"!="+ origQname.toLogString()+".)"); + } + + vector ret; + DNSResourceRecord rr; + result->reserve(mdp.d_answers.size()); + + for (const auto& i: mdp.d_answers) { + rr.qname = i.first.d_name; + rr.qtype = i.first.d_type; + rr.ttl = i.first.d_ttl; + rr.content = i.first.d_content->getZoneRepresentation(true); + result->push_back(rr); + } + + return 0; +} + +bool Resolver::tryGetSOASerial(DNSName *domain, ComboAddress* remote, uint32_t *theirSerial, uint32_t *theirInception, uint32_t *theirExpire, uint16_t* id) +{ + auto fds = std::unique_ptr(new struct pollfd[locals.size()]); + size_t i = 0, k; + int sock; + + for (const auto& iter: locals) { + fds[i].fd = iter.second; + fds[i].events = POLLIN; + ++i; + } + + if (poll(fds.get(), i, 250) < 1) { // wait for 0.25s + return false; + } + + sock = -1; + + // determine who + for(k=0;ksin6.sin6_family = AF_INET6; // make sure getSocklen() below returns a large enough value + socklen_t addrlen=remote->getSocklen(); + char buf[3000]; + err = recvfrom(sock, buf, sizeof(buf), 0,(struct sockaddr*)(remote), &addrlen); + if(err < 0) { + if(errno == EAGAIN) + return false; + + throw ResolverException("recvfrom error waiting for answer: "+stringerror()); + } + + MOADNSParser mdp(false, (char*)buf, err); + *id=mdp.d_header.id; + *domain = mdp.d_qname; + + if(domain->empty()) + throw ResolverException("SOA query to '" + remote->toStringWithPort() + "' produced response without domain name (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); + + if(mdp.d_answers.empty()) + throw ResolverException("Query to '" + remote->toStringWithPort() + "' for SOA of '" + domain->toLogString() + "' produced no results (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); + + if(mdp.d_qtype != QType::SOA) + throw ResolverException("Query to '" + remote->toStringWithPort() + "' for SOA of '" + domain->toLogString() + "' returned wrong record type"); + + if(mdp.d_header.rcode != 0) + throw ResolverException("Query to '" + remote->toStringWithPort() + "' for SOA of '" + domain->toLogString() + "' returned Rcode " + RCode::to_s(mdp.d_header.rcode)); + + *theirInception = *theirExpire = 0; + bool gotSOA=false; + for(const MOADNSParser::answers_t::value_type& drc : mdp.d_answers) { + if(drc.first.d_type == QType::SOA && drc.first.d_name == *domain) { + shared_ptr src=getRR(drc.first); + if (src) { + *theirSerial=src->d_st.serial; + gotSOA = true; + } + } + if(drc.first.d_type == QType::RRSIG && drc.first.d_name == *domain) { + shared_ptr rrc=getRR(drc.first); + if(rrc && rrc->d_type == QType::SOA) { + *theirInception= std::max(*theirInception, rrc->d_siginception); + *theirExpire = std::max(*theirExpire, rrc->d_sigexpire); + } + } + } + if(!gotSOA) + throw ResolverException("Query to '" + remote->toString() + "' for SOA of '" + domain->toLogString() + "' did not return a SOA"); + return true; +} + +int Resolver::resolve(const ComboAddress& to, const DNSName &domain, int type, Resolver::res_t* res, const ComboAddress &local) +{ + try { + int sock = -1; + int id = sendResolve(to, local, domain, type, &sock); + int err=waitForData(sock, 0, 3000000); + + if(!err) { + throw ResolverException("Timeout waiting for answer"); + } + if(err < 0) + throw ResolverException("Error waiting for answer: "+stringerror()); + + ComboAddress from; + socklen_t addrlen = sizeof(from); + char buffer[3000]; + int len; + + if((len=recvfrom(sock, buffer, sizeof(buffer), 0,(struct sockaddr*)(&from), &addrlen)) < 0) + throw ResolverException("recvfrom error waiting for answer: "+stringerror()); + + if (from != to) { + throw ResolverException("Got answer from the wrong peer while resolving ("+from.toStringWithPort()+" instead of "+to.toStringWithPort()+", discarding"); + } + + MOADNSParser mdp(false, buffer, len); + return parseResult(mdp, domain, type, id, res); + } + catch(ResolverException &re) { + throw ResolverException(re.reason+" from "+to.toLogString()); + } + return -1; +} + +int Resolver::resolve(const ComboAddress& ipport, const DNSName &domain, int type, Resolver::res_t* res) { + ComboAddress local; + local.sin4.sin_family = 0; + return resolve(ipport, domain, type, res, local); +} + +void Resolver::getSoaSerial(const ComboAddress& ipport, const DNSName &domain, uint32_t *serial) +{ + vector res; + int ret = resolve(ipport, domain, QType::SOA, &res); + + if(ret || res.empty()) + throw ResolverException("Query to '" + ipport.toLogString() + "' for SOA of '" + domain.toLogString() + "' produced no answers"); + + if(res[0].qtype.getCode() != QType::SOA) + throw ResolverException("Query to '" + ipport.toLogString() + "' for SOA of '" + domain.toLogString() + "' produced a "+res[0].qtype.getName()+" record"); + + vectorparts; + stringtok(parts, res[0].content); + if(parts.size()<3) + throw ResolverException("Query to '" + ipport.toLogString() + "' for SOA of '" + domain.toLogString() + "' produced an unparseable response"); + + try { + *serial=pdns_stou(parts[2]); + } + catch(const std::out_of_range& oor) { + throw ResolverException("Query to '" + ipport.toLogString() + "' for SOA of '" + domain.toLogString() + "' produced an unparseable serial"); + } +} + +AXFRRetriever::AXFRRetriever(const ComboAddress& remote, + const DNSName& domain, + const TSIGTriplet& tt, + const ComboAddress* laddr, + size_t maxReceivedBytes, + uint16_t timeout) + : d_tsigVerifier(tt, remote, d_trc), d_receivedBytes(0), d_maxReceivedBytes(maxReceivedBytes) +{ + ComboAddress local; + if (laddr != nullptr) { + local = ComboAddress(*laddr); + } else { + string qlas = remote.sin4.sin_family == AF_INET ? "query-local-address" : "query-local-address6"; + if (::arg()[qlas].empty()) { + throw ResolverException("Unable to determine source address for AXFR request to " + remote.toStringWithPort() + " for " + domain.toLogString() + ". " + qlas + " is unset"); + } + local=ComboAddress(::arg()[qlas]); + } + d_sock = -1; + try { + d_sock = makeQuerySocket(local, false); // make a TCP socket + if (d_sock < 0) + throw ResolverException("Error creating socket for AXFR request to "+d_remote.toStringWithPort()); + d_buf = shared_array(new char[65536]); + d_remote = remote; // mostly for error reporting + this->connect(timeout); + d_soacount = 0; + + vector packet; + DNSPacketWriter pw(packet, domain, QType::AXFR); + pw.getHeader()->id = dns_random(0xffff); + + if(!tt.name.empty()) { + if (tt.algo == DNSName("hmac-md5")) + d_trc.d_algoName = tt.algo + DNSName("sig-alg.reg.int"); + else + d_trc.d_algoName = tt.algo; + d_trc.d_time = time(0); + d_trc.d_fudge = 300; + d_trc.d_origID=ntohs(pw.getHeader()->id); + d_trc.d_eRcode=0; + addTSIG(pw, d_trc, tt.name, tt.secret, "", false); + } + + uint16_t replen=htons(packet.size()); + Utility::iovec iov[2]; + iov[0].iov_base=reinterpret_cast(&replen); + iov[0].iov_len=2; + iov[1].iov_base=packet.data(); + iov[1].iov_len=packet.size(); + + int ret=Utility::writev(d_sock, iov, 2); + if(ret < 0) + throw ResolverException("Error sending question to "+d_remote.toStringWithPort()+": "+stringerror()); + if(ret != (int)(2+packet.size())) { + throw ResolverException("Partial write on AXFR request to "+d_remote.toStringWithPort()); + } + + int res = waitForData(d_sock, timeout, 0); + + if(!res) + throw ResolverException("Timeout waiting for answer from "+d_remote.toStringWithPort()+" during AXFR"); + if(res<0) + throw ResolverException("Error waiting for answer from "+d_remote.toStringWithPort()+": "+stringerror()); + } + catch(...) { + if(d_sock >= 0) + close(d_sock); + d_sock = -1; + throw; + } +} + +AXFRRetriever::~AXFRRetriever() +{ + close(d_sock); +} + + + +int AXFRRetriever::getChunk(Resolver::res_t &res, vector* records, uint16_t timeout) // Implementation is making sure RFC2845 4.4 is followed. +{ + if(d_soacount > 1) + return false; + + // d_sock is connected and is about to spit out a packet + int len=getLength(timeout); + if(len<0) + throw ResolverException("EOF trying to read axfr chunk from remote TCP client"); + + if (d_maxReceivedBytes > 0 && (d_maxReceivedBytes - d_receivedBytes) < (size_t) len) + throw ResolverException("Reached the maximum number of received bytes during AXFR"); + + timeoutReadn(len, timeout); + + d_receivedBytes += (uint16_t) len; + + MOADNSParser mdp(false, d_buf.get(), len); + + int err = mdp.d_header.rcode; + + if(err) { + throw ResolverException("AXFR chunk error: " + RCode::to_s(err)); + } + + try { + d_tsigVerifier.check(std::string(d_buf.get(), len), mdp); + } + catch(const std::runtime_error& re) { + throw ResolverException(re.what()); + } + + if(!records) { + err = parseResult(mdp, DNSName(), 0, 0, &res); + + if (!err) { + for(const auto& answer : mdp.d_answers) + if (answer.first.d_type == QType::SOA) + d_soacount++; + } + } + else { + records->clear(); + records->reserve(mdp.d_answers.size()); + + for(auto& r: mdp.d_answers) { + if (r.first.d_type == QType::SOA) { + d_soacount++; + } + + records->push_back(std::move(r.first)); + } + } + + return true; +} + +void AXFRRetriever::timeoutReadn(uint16_t bytes, uint16_t timeoutsec) +{ + time_t start=time(nullptr); + int n=0; + int numread; + while(n +#include +#include +#include "iputils.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#undef res_mkquery + +#include "pdnsexception.hh" +#include "dns.hh" +#include "namespaces.hh" +#include "dnsrecords.hh" +#include "dnssecinfra.hh" +#include "tsigverifier.hh" + +class ResolverException : public PDNSException +{ +public: + ResolverException(const string &reason_) : PDNSException(reason_){} +}; + +// make an IPv4 or IPv6 query socket +int makeQuerySocket(const ComboAddress& local, bool udpOrTCP, bool nonLocalBind=false); +//! Resolver class. Can be used synchronously and asynchronously, over IPv4 and over IPv6 (simultaneously) +class Resolver : public boost::noncopyable +{ +public: + Resolver(); + ~Resolver(); + + typedef vector res_t; + //! synchronously resolve domain|type at IP, store result in result, rcode in ret + int resolve(const ComboAddress &ip, const DNSName &domain, int type, res_t* result, const ComboAddress& local); + + int resolve(const ComboAddress &ip, const DNSName &domain, int type, res_t* result); + + //! only send out a resolution request + uint16_t sendResolve(const ComboAddress& remote, const ComboAddress& local, const DNSName &domain, int type, int *localsock, bool dnssecOk=false, + const DNSName& tsigkeyname=DNSName(), const DNSName& tsigalgorithm=DNSName(), const string& tsigsecret=""); + + //! see if we got a SOA response from our sendResolve + bool tryGetSOASerial(DNSName *theirDomain, ComboAddress* remote, uint32_t* theirSerial, uint32_t* theirInception, uint32_t* theirExpire, uint16_t* id); + + //! convenience function that calls resolve above + void getSoaSerial(const ComboAddress&, const DNSName &, uint32_t *); + +private: + std::map locals; +}; + +class AXFRRetriever : public boost::noncopyable +{ + public: + AXFRRetriever(const ComboAddress& remote, + const DNSName& zone, + const TSIGTriplet& tt = TSIGTriplet(), + const ComboAddress* laddr = NULL, + size_t maxReceivedBytes=0, + uint16_t timeout=10); + ~AXFRRetriever(); + int getChunk(Resolver::res_t &res, vector* records=0, uint16_t timeout=10); + + private: + void connect(uint16_t timeout); + int getLength(uint16_t timeout); + void timeoutReadn(uint16_t bytes, uint16_t timeoutsec=10); + + shared_array d_buf; + string d_domain; + int d_sock; + int d_soacount; + ComboAddress d_remote; + TSIGTCPVerifier d_tsigVerifier; + + size_t d_receivedBytes; + size_t d_maxReceivedBytes; + TSIGRecordContent d_trc; +}; + + +#endif /* PDNS_RESOLVER_HH */ diff --git a/pdns/responsestats-auth.cc b/pdns/responsestats-auth.cc new file mode 100644 index 0000000..ac4f75a --- /dev/null +++ b/pdns/responsestats-auth.cc @@ -0,0 +1,56 @@ +#include "responsestats.hh" +#include "dnspacket.hh" +#include "statbag.hh" + +extern StatBag S; +/** + * Function that creates all the stats + * when udpOrTCP is true, it is udp + */ +void ResponseStats::submitResponse(DNSPacket &p, bool udpOrTCP) { + const string& buf=p.getString(); + static AtomicCounter &udpnumanswered=*S.getPointer("udp-answers"); + static AtomicCounter &udpnumanswered4=*S.getPointer("udp4-answers"); + static AtomicCounter &udpnumanswered6=*S.getPointer("udp6-answers"); + static AtomicCounter &udpbytesanswered=*S.getPointer("udp-answers-bytes"); + static AtomicCounter &udpbytesanswered4=*S.getPointer("udp4-answers-bytes"); + static AtomicCounter &udpbytesanswered6=*S.getPointer("udp6-answers-bytes"); + static AtomicCounter &tcpnumanswered=*S.getPointer("tcp-answers"); + static AtomicCounter &tcpnumanswered4=*S.getPointer("tcp4-answers"); + static AtomicCounter &tcpnumanswered6=*S.getPointer("tcp6-answers"); + static AtomicCounter &tcpbytesanswered=*S.getPointer("tcp-answers-bytes"); + static AtomicCounter &tcpbytesanswered4=*S.getPointer("tcp4-answers-bytes"); + static AtomicCounter &tcpbytesanswered6=*S.getPointer("tcp6-answers-bytes"); + + if(p.d.aa) { + if (p.d.rcode==RCode::NXDomain) + S.ringAccount("nxdomain-queries", p.qdomain, p.qtype); + } else if (p.d.rcode == RCode::Refused) { + S.ringAccount("unauth-queries", p.qdomain, p.qtype); + S.ringAccount("remotes-unauth",p.d_remote); + } + + if (udpOrTCP) { // udp + udpnumanswered++; + udpbytesanswered+=buf.length(); + if(p.d_remote.sin4.sin_family==AF_INET) { + udpnumanswered4++; + udpbytesanswered4+=buf.length(); + } else { + udpnumanswered6++; + udpbytesanswered6+=buf.length(); + } + } else { //tcp + tcpnumanswered++; + tcpbytesanswered+=buf.length(); + if(p.d_remote.sin4.sin_family==AF_INET) { + tcpnumanswered4++; + tcpbytesanswered4+=buf.length(); + } else { + tcpnumanswered6++; + tcpbytesanswered6+=buf.length(); + } + } + + submitResponse(p.qtype.getCode(), buf.length(), p.d.rcode, udpOrTCP); +} diff --git a/pdns/responsestats.cc b/pdns/responsestats.cc new file mode 100644 index 0000000..93b2fca --- /dev/null +++ b/pdns/responsestats.cc @@ -0,0 +1,96 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "responsestats.hh" +#include +#include "namespaces.hh" +#include "logger.hh" + +#include "dnsparser.hh" + +ResponseStats::ResponseStats() : d_qtypecounters(new std::atomic[65536]), d_rcodecounters(new std::atomic[256]) +{ + d_sizecounters.push_back(make_pair(20,0)); + d_sizecounters.push_back(make_pair(40,0)); + d_sizecounters.push_back(make_pair(60,0)); + d_sizecounters.push_back(make_pair(80,0)); + d_sizecounters.push_back(make_pair(100,0)); + d_sizecounters.push_back(make_pair(150,0)); + for(int n=200; n < 65000 ; n+=200) + d_sizecounters.push_back(make_pair(n,0)); + d_sizecounters.push_back(make_pair(std::numeric_limits::max(),0)); + for(unsigned int n =0 ; n < 65535; ++n) + d_qtypecounters[n] = 0; + for(unsigned int n =0 ; n < 256; ++n) + d_rcodecounters[n] = 0; +} + +ResponseStats g_rs; + +static bool pcomp(const pair&a , const pair&b) +{ + return a.first < b.first; +} + +void ResponseStats::submitResponse(uint16_t qtype,uint16_t respsize, uint8_t rcode, bool udpOrTCP) +{ + d_rcodecounters[rcode]++; + submitResponse(qtype, respsize, udpOrTCP); +} + +void ResponseStats::submitResponse(uint16_t qtype,uint16_t respsize, bool udpOrTCP) +{ + d_qtypecounters[qtype]++; + pair s(respsize, 0); + sizecounters_t::iterator iter = std::upper_bound(d_sizecounters.begin(), d_sizecounters.end(), s, pcomp); + if(iter!= d_sizecounters.begin()) + --iter; + iter->second++; +} + +map ResponseStats::getQTypeResponseCounts() +{ + map ret; + uint64_t count; + for(unsigned int i = 0 ; i < 65535 ; ++i) { + count= d_qtypecounters[i]; + if(count) + ret[i]=count; + } + return ret; +} + +map ResponseStats::getSizeResponseCounts() +{ + map ret; + for(sizecounters_t::const_iterator iter = d_sizecounters.begin(); + iter != d_sizecounters.end(); + ++iter) { + ret[iter->first]=iter->second; + } + return ret; +} + +map ResponseStats::getRCodeResponseCounts() +{ + map ret; + uint64_t count; + for(unsigned int i = 0 ; i < 256 ; ++i) { + count= d_rcodecounters[i]; + if(count) + ret[i]=count; + } + return ret; +} + +string ResponseStats::getQTypeReport() +{ + typedef map qtypenums_t; + qtypenums_t qtypenums = getQTypeResponseCounts(); + ostringstream os; + boost::format fmt("%s\t%d\n"); + for(const qtypenums_t::value_type& val : qtypenums) { + os << (fmt %DNSRecordContent::NumberToType( val.first) % val.second).str(); + } + return os.str(); +} diff --git a/pdns/responsestats.hh b/pdns/responsestats.hh new file mode 100644 index 0000000..884d49d --- /dev/null +++ b/pdns/responsestats.hh @@ -0,0 +1,46 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include "misc.hh" +#include "dnspacket.hh" + +class ResponseStats +{ +public: + ResponseStats(); + + void submitResponse(DNSPacket &p, bool udpOrTCP); + void submitResponse(uint16_t qtype, uint16_t respsize, bool udpOrTCP); + void submitResponse(uint16_t qtype, uint16_t respsize, uint8_t rcode, bool udpOrTCP); + map getQTypeResponseCounts(); + map getSizeResponseCounts(); + map getRCodeResponseCounts(); + string getQTypeReport(); + +private: + boost::scoped_array> d_qtypecounters; + boost::scoped_array> d_rcodecounters; + typedef vector > sizecounters_t; + sizecounters_t d_sizecounters; +}; + +extern ResponseStats g_rs; diff --git a/pdns/rfc2136handler.cc b/pdns/rfc2136handler.cc new file mode 100644 index 0000000..d8bc77a --- /dev/null +++ b/pdns/rfc2136handler.cc @@ -0,0 +1,1121 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "packethandler.hh" +#include "qtype.hh" +#include "dnspacket.hh" +#include "auth-caches.hh" +#include "statbag.hh" +#include "dnsseckeeper.hh" +#include "base64.hh" +#include "base32.hh" + +#include "misc.hh" +#include "arguments.hh" +#include "resolver.hh" +#include "dns_random.hh" +#include "backends/gsql/ssql.hh" +#include "communicator.hh" + +extern StatBag S; +extern CommunicatorClass Communicator; + +pthread_mutex_t PacketHandler::s_rfc2136lock=PTHREAD_MUTEX_INITIALIZER; + +// Implement section 3.2.1 and 3.2.2 of RFC2136 +int PacketHandler::checkUpdatePrerequisites(const DNSRecord *rr, DomainInfo *di) { + if (rr->d_ttl != 0) + return RCode::FormErr; + + // 3.2.1 and 3.2.2 check content length. + if ( (rr->d_class == QClass::NONE || rr->d_class == QClass::ANY) && rr->d_clen != 0) + return RCode::FormErr; + + bool foundRecord=false; + DNSResourceRecord rec; + di->backend->lookup(QType(QType::ANY), rr->d_name, nullptr, di->id); + while(di->backend->get(rec)) { + if (!rec.qtype.getCode()) + continue; + if ((rr->d_type != QType::ANY && rec.qtype == rr->d_type) || rr->d_type == QType::ANY) + foundRecord=true; + } + + // Section 3.2.1 + if (rr->d_class == QClass::ANY && !foundRecord) { + if (rr->d_type == QType::ANY) + return RCode::NXDomain; + if (rr->d_type != QType::ANY) + return RCode::NXRRSet; + } + + // Section 3.2.2 + if (rr->d_class == QClass::NONE && foundRecord) { + if (rr->d_type == QType::ANY) + return RCode::YXDomain; + if (rr->d_type != QType::ANY) + return RCode::YXRRSet; + } + + return RCode::NoError; +} + + +// Method implements section 3.4.1 of RFC2136 +int PacketHandler::checkUpdatePrescan(const DNSRecord *rr) { + // The RFC stats that d_class != ZCLASS, but we only support the IN class. + if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY) + return RCode::FormErr; + + QType qtype = QType(rr->d_type); + + if (! qtype.isSupportedType()) + return RCode::FormErr; + + if ((rr->d_class == QClass::NONE || rr->d_class == QClass::ANY) && rr->d_ttl != 0) + return RCode::FormErr; + + if (rr->d_class == QClass::ANY && rr->d_clen != 0) + return RCode::FormErr; + + if (qtype.isMetadataType()) + return RCode::FormErr; + + if (rr->d_class != QClass::ANY && qtype.getCode() == QType::ANY) + return RCode::FormErr; + + return RCode::NoError; +} + + +// Implements section 3.4.2 of RFC2136 +uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool isPresigned, bool* narrow, bool* haveNSEC3, NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial) { + + QType rrType = QType(rr->d_type); + + if (rrType == QType::NSEC || rrType == QType::NSEC3) { + g_log<d_name<<"|"<d_name<<"|"<d_name != di->zone) { + g_log<d_name<<"|"< rrset, recordsToDelete; + set delnonterm, insnonterm; // used to (at the end) fix ENT records. + + + if (rr->d_class == QClass::IN) { // 3.4.2.2 QClass::IN means insert or update + DLOG(g_log<d_name<<"|"<d_content->getZoneRepresentation(), di->zone.toString() /* FIXME400 huh */); + *narrow = false; // adding a NSEC3 will cause narrow mode to be dropped, as you cannot specify that in a NSEC3PARAM record + d_dk.setNSEC3PARAM(di->zone, nsec3param, (*narrow)); + + *haveNSEC3 = d_dk.getNSEC3PARAM(di->zone, ns3pr, narrow); + + vector rrs; + set qnames, nssets, dssets; + di->backend->list(di->zone, di->id); + while (di->backend->get(rec)) { + qnames.insert(rec.qname); + if(rec.qtype.getCode() == QType::NS && rec.qname != di->zone) + nssets.insert(rec.qname); + if(rec.qtype.getCode() == QType::DS) + dssets.insert(rec.qname); + } + + DNSName shorter; + for(const auto& qname: qnames) { + shorter = qname; + int ddepth = 0; + do { + if(qname == di->zone) + break; + if(nssets.count(shorter)) + ++ddepth; + } while(shorter.chopOff()); + + DNSName ordername = DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, qname))); + if (! *narrow && (ddepth == 0 || (ddepth == 1 && nssets.count(qname)))) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, ordername, (ddepth == 0 )); + + if (nssets.count(qname)) { + if (ns3pr->d_flags) + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), false, QType::NS ); + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), false, QType::AAAA); + } + } else { + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), (ddepth == 0)); + } + if (ddepth == 1 || dssets.count(qname)) // FIXME400 && ? + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, ordername, false, QType::DS); + } + return 1; + } + + + + bool foundRecord = false; + di->backend->lookup(rrType, rr->d_name, nullptr, di->id); + while (di->backend->get(rec)) { + rrset.push_back(rec); + foundRecord = true; + } + + if (foundRecord) { + + if (rrType == QType::SOA) { // SOA updates require the serial to be higher than the current + SOAData sdOld, sdUpdate; + DNSResourceRecord *oldRec = &rrset.front(); + fillSOAData(oldRec->content, sdOld); + oldRec->setContent(rr->d_content->getZoneRepresentation()); + fillSOAData(oldRec->content, sdUpdate); + if (rfc1982LessThan(sdOld.serial, sdUpdate.serial)) { + di->backend->replaceRRSet(di->id, oldRec->qname, oldRec->qtype, rrset); + *updatedSerial = true; + changedRecords++; + g_log<d_name<<"|"<d_ttl || i.content != rr->d_content->getZoneRepresentation()) { + i.ttl = rr->d_ttl; + i.setContent(rr->d_content->getZoneRepresentation()); + changedCNames++; + } + } + if (changedCNames > 0) { + di->backend->replaceRRSet(di->id, rr->d_name, rrType, rrset); + g_log<d_name<<"|"<d_name<<"|"<d_content->getZoneRepresentation(); + if (lowerCase) content = toLower(content); + for (auto& i : rrset) { + string icontent = i.getZoneRepresentation(); + if (lowerCase) icontent = toLower(icontent); + if (rrType == i.qtype.getCode() && icontent == content) { + foundRecord=true; + if (i.ttl != rr->d_ttl) { + i.ttl = rr->d_ttl; + updateTTL++; + } + } + } + if (updateTTL > 0) { + di->backend->replaceRRSet(di->id, rr->d_name, rrType, rrset); + g_log<d_name<<"|"<d_name<<"|"< 0) { + bool auth = rrset.front().auth; + + if(*haveNSEC3) { + DNSName ordername; + if(! *narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, rr->d_name))); + + if (*narrow) + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), auth); + else + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, ordername, auth); + if(!auth || rrType == QType::DS) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::NS); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::AAAA); + } + + } else { // NSEC + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, rr->d_name.makeRelative(di->zone), auth); + if(!auth || rrType == QType::DS) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::AAAA); + } + } + } + + } // if (foundRecord) + + // If we haven't found a record that matches, we must add it. + if (! foundRecord) { + g_log<d_name<<"|"<d_name); // always remove any ENT's in the place where we're going to add a record. + auto newRec = DNSResourceRecord::fromWire(*rr); + newRec.domain_id = di->id; + newRec.auth = (rr->d_name == di->zone || rrType.getCode() != QType::NS); + di->backend->feedRecord(newRec, DNSName()); + changedRecords++; + + + // because we added a record, we need to fix DNSSEC data. + DNSName shorter(rr->d_name); + bool auth=newRec.auth; + bool fixDS = (rrType == QType::DS); + + if (di->zone != shorter) { // Everything at APEX is auth=1 && no ENT's + do { + + if (di->zone == shorter) + break; + + bool foundShorter = false; + di->backend->lookup(QType(QType::ANY), shorter, nullptr, di->id); + while (di->backend->get(rec)) { + if (rec.qname == rr->d_name && rec.qtype == QType::DS) + fixDS = true; + if (shorter != rr->d_name) + foundShorter = true; + if (rec.qtype == QType::NS) // are we inserting below a delegate? + auth=false; + } + + if (!foundShorter && auth && shorter != rr->d_name) // haven't found any record at current level, insert ENT. + insnonterm.insert(shorter); + if (foundShorter) + break; // if we find a shorter record, we can stop searching + } while(shorter.chopOff()); + } + + if(*haveNSEC3) + { + DNSName ordername; + if(! *narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, rr->d_name))); + + if (*narrow) + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), auth); + else + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, ordername, auth); + + if (fixDS) + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, ordername, true, QType::DS); + + if(!auth) + { + if (ns3pr->d_flags) + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::NS); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::AAAA); + } + } + else // NSEC + { + DNSName ordername=rr->d_name.makeRelative(di->zone); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, ordername, auth); + if (fixDS) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, ordername, true, QType::DS); + } + if(!auth) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), false, QType::AAAA); + } + } + + + // If we insert an NS, all the records below it become non auth - so, we're inserting a delegate. + // Auth can only be false when the rr->d_name is not the zone + if (auth == false && rrType == QType::NS) { + DLOG(g_log<d_name< qnames; + di->backend->listSubZone(rr->d_name, di->id); + while(di->backend->get(rec)) { + if (rec.qtype.getCode() && rec.qtype.getCode() != QType::DS && rr->d_name != rec.qname) // Skip ENT, DS and our already corrected record. + qnames.push_back(rec.qname); + } + for(vector::const_iterator qname=qnames.begin(); qname != qnames.end(); ++qname) { + if(*haveNSEC3) { + DNSName ordername; + if(! *narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, *qname))); + + if (*narrow) + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr->d_name, DNSName(), auth); // FIXME400 no *qname here? + else + di->backend->updateDNSSECOrderNameAndAuth(di->id, *qname, ordername, auth); + + if (ns3pr->d_flags) + di->backend->updateDNSSECOrderNameAndAuth(di->id, *qname, DNSName(), false, QType::NS); + } + else { // NSEC + DNSName ordername=DNSName(*qname).makeRelative(di->zone); + di->backend->updateDNSSECOrderNameAndAuth(di->id, *qname, ordername, false, QType::NS); + } + + di->backend->updateDNSSECOrderNameAndAuth(di->id, *qname, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, *qname, DNSName(), false, QType::AAAA); + } + } + } + } // rr->d_class == QClass::IN + + + // Delete records - section 3.4.2.3 and 3.4.2.4 with the exception of the 'always leave 1 NS rule' as that's handled by + // the code that calls this performUpdate(). + if ((rr->d_class == QClass::ANY || rr->d_class == QClass::NONE) && rrType != QType::SOA) { // never delete a SOA. + DLOG(g_log<d_name<<"; QClass:"<d_class<<"; rrType: "<d_class == QClass::ANY) + d_dk.unsetNSEC3PARAM(rr->d_name); + else if (rr->d_class == QClass::NONE) { + NSEC3PARAMRecordContent nsec3rr(rr->d_content->getZoneRepresentation(), di->zone.toString() /* FIXME400 huh */); + if (ns3pr->getZoneRepresentation() == nsec3rr.getZoneRepresentation()) + d_dk.unsetNSEC3PARAM(rr->d_name); + else + return 0; + } else + return 0; + + // We retrieve new values, other RR's in this update package might need it as well. + *haveNSEC3 = d_dk.getNSEC3PARAM(di->zone, ns3pr, narrow); + + vector rrs; + set qnames, nssets, dssets, ents; + di->backend->list(di->zone, di->id); + while (di->backend->get(rec)) { + qnames.insert(rec.qname); + if(rec.qtype.getCode() == QType::NS && rec.qname != di->zone) + nssets.insert(rec.qname); + if(rec.qtype.getCode() == QType::DS) + dssets.insert(rec.qname); + if(!rec.qtype.getCode()) + ents.insert(rec.qname); + } + + DNSName shorter; + string hashed; + for(const DNSName& qname : qnames) { + shorter = qname; + int ddepth = 0; + do { + if(qname == di->zone) + break; + if(nssets.count(shorter)) + ++ddepth; + } while(shorter.chopOff()); + + DNSName ordername=qname.makeRelative(di->zone); + if (!ents.count(qname) && (ddepth == 0 || (ddepth == 1 && nssets.count(qname)))) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, ordername, (ddepth == 0)); + + if (nssets.count(qname)) { + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), false, QType::A); + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), false, QType::AAAA); + } + } else { + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, DNSName(), (ddepth == 0)); + } + if (ddepth == 1 || dssets.count(qname)) + di->backend->updateDNSSECOrderNameAndAuth(di->id, qname, ordername, true, QType::DS); + } + return 1; + } // end of NSEC3PARAM delete block + + + di->backend->lookup(rrType, rr->d_name, nullptr, di->id); + while(di->backend->get(rec)) { + if (rr->d_class == QClass::ANY) { // 3.4.2.3 + if (rec.qname == di->zone && (rec.qtype == QType::NS || rec.qtype == QType::SOA)) // Never delete all SOA and NS's + rrset.push_back(rec); + else + recordsToDelete.push_back(rec); + } + if (rr->d_class == QClass::NONE) { // 3.4.2.4 + if (rrType == rec.qtype && rec.getZoneRepresentation() == rr->d_content->getZoneRepresentation()) + recordsToDelete.push_back(rec); + else + rrset.push_back(rec); + } + } + + if (recordsToDelete.size()) { + di->backend->replaceRRSet(di->id, rr->d_name, rrType, rrset); + g_log<d_name<<"|"<d_name != di->zone) { + vector belowOldDelegate, nsRecs, updateAuthFlag; + di->backend->listSubZone(rr->d_name, di->id); + while (di->backend->get(rec)) { + if (rec.qtype.getCode()) // skip ENT records, they are always auth=false + belowOldDelegate.push_back(rec.qname); + if (rec.qtype.getCode() == QType::NS && rec.qname != rr->d_name) + nsRecs.push_back(rec.qname); + } + + for(auto &belowOldDel: belowOldDelegate) + { + bool isBelowDelegate = false; + for(const auto & ns: nsRecs) { + if (ns.isPartOf(belowOldDel)) { + isBelowDelegate=true; + break; + } + } + if (!isBelowDelegate) + updateAuthFlag.push_back(belowOldDel); + } + + for (const auto &changeRec:updateAuthFlag) { + if(*haveNSEC3) { + DNSName ordername; + if(! *narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, changeRec))); + + di->backend->updateDNSSECOrderNameAndAuth(di->id, changeRec, ordername, true); + } + else { // NSEC + DNSName ordername=changeRec.makeRelative(di->zone); + di->backend->updateDNSSECOrderNameAndAuth(di->id, changeRec, ordername, true); + } + } + } + + // Fix ENT records. + // We must check if we have a record below the current level and if we removed the 'last' record + // on that level. If so, we must insert an ENT record. + // We take extra care here to not 'include' the record that we just deleted. Some backends will still return it as they only reload on a commit. + bool foundDeeper = false, foundOtherWithSameName = false; + di->backend->listSubZone(rr->d_name, di->id); + while (di->backend->get(rec)) { + if (rec.qname == rr->d_name && !count(recordsToDelete.begin(), recordsToDelete.end(), rec)) + foundOtherWithSameName = true; + if (rec.qname != rr->d_name && rec.qtype.getCode() != QType::NS) //Skip NS records, as this would be a delegate that we can ignore as this does not require us to create a ENT + foundDeeper = true; + } + + if (foundDeeper && !foundOtherWithSameName) { + insnonterm.insert(rr->d_name); + } else if (!foundOtherWithSameName) { + // If we didn't have to insert an ENT, we might have deleted a record at very deep level + // and we must then clean up the ENT's above the deleted record. + DNSName shorter(rr->d_name); + while (shorter != di->zone) { + shorter.chopOff(); + bool foundRealRR = false; + bool foundEnt = false; + + // The reason for a listSubZone here is because might go up the tree and find the ENT of another branch + // consider these non ENT-records: + // b.c.d.e.test.com + // b.d.e.test.com + // if we delete b.c.d.e.test.com, we go up to d.e.test.com and then find b.d.e.test.com because that's below d.e.test.com. + // At that point we can stop deleting ENT's because the tree is in tact again. + di->backend->listSubZone(shorter, di->id); + + while (di->backend->get(rec)) { + if (rec.qtype.getCode()) + foundRealRR = true; + else + foundEnt = true; + } + if (!foundRealRR) { + if (foundEnt) // only delete the ENT if we actually found one. + delnonterm.insert(shorter); + } else + break; + } + } + } else { // if (recordsToDelete.size()) + g_log<d_name<<"|"< 0 || delnonterm.size() > 0) { + DLOG(g_log<backend->updateEmptyNonTerminals(di->id, insnonterm, delnonterm, false); + for (const auto &i: insnonterm) { + string hashed; + if(*haveNSEC3) + { + DNSName ordername; + if(! *narrow) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, i))); + di->backend->updateDNSSECOrderNameAndAuth(di->id, i, ordername, true); + } + } + } + + return changedRecords; +} + +int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainInfo *di) { + vector forward; + B.getDomainMetadata(p->qdomain, "FORWARD-DNSUPDATE", forward); + + if (forward.size() == 0 && ! ::arg().mustDo("forward-dnsupdate")) { + g_log<masters) { + g_log<(recvRes) < sizeof(lenBuf)) { + g_log<(recvRes)); + g_log<d.id) + ") from " + p->getRemote().toString() + " for " + p->qdomain.toLogString() + ": "; + g_log<d_update_policy_lua == NULL) { + + // Check permissions - IP based + vector allowedRanges; + B.getDomainMetadata(p->qdomain, "ALLOW-DNSUPDATE-FROM", allowedRanges); + if (! ::arg()["allow-dnsupdate-from"].empty()) + stringtok(allowedRanges, ::arg()["allow-dnsupdate-from"], ", \t" ); + + NetmaskGroup ng; + for(const auto& i: allowedRanges) { + ng.addMask(i); + } + + if ( ! ng.match(&p->d_remote)) { + g_log< tsigKeys; + B.getDomainMetadata(p->qdomain, "TSIG-ALLOW-DNSUPDATE", tsigKeys); + if (tsigKeys.size() > 0) { + bool validKey = false; + + TSIGRecordContent trc; + DNSName inputkey; + string message; + if (! p->getTSIGDetails(&trc, &inputkey)) { + g_log<d_tsig_algo == TSIG_GSS) { + GssName inputname(p->d_peer_principal); // match against principal since GSS + for(const auto& key: tsigKeys) { + if (inputname.match(key)) { + validKey = true; + break; + } + } + } else { + for(const auto& key: tsigKeys) { + if (inputkey == DNSName(key)) { // because checkForCorrectTSIG has already been performed earlier on, if the names of the ky match with the domain given. THis is valid. + validKey=true; + break; + } + } + } + + if (!validKey) { + g_log<d_havetsig) + g_log<getString()); + if (mdp.d_header.qdcount != 1) { + g_log<qtype.getCode() != QType::SOA) { // RFC2136 2.3 - ZTYPE must be SOA + g_log<qclass != QClass::IN) { + g_log<qdomain, di) || !di.backend) { + g_log<qdomain<<"' (or backend does not support DNS update operation)"<first; + // Skip this check for other field types (like the TSIG - which is in the additional section) + // For a TSIG, the label is the dnskey, so it does not pass the endOn validation. + if (! (rr->d_place == DNSResourceRecord::ANSWER || rr->d_place == DNSResourceRecord::AUTHORITY)) + continue; + + if (!rr->d_name.isPartOf(di.zone)) { + g_log<startTransaction(p->qdomain, -1)) { // Not giving the domain_id means that we do not delete the existing records. + g_log<qdomain<<" does not support transaction. Can't do Update packet."<first; + if (rr->d_place == DNSResourceRecord::ANSWER) { + int res = checkUpdatePrerequisites(rr, &di); + if (res>0) { + g_log<d_name.toLogString()<<", returning "<abortTransaction(); + return res; + } + } + } + + // 3.2.3 - Prerequisite check - this is outside of updatePrerequisitesCheck because we check an RRSet and not the RR. + typedef pair rrSetKey_t; + typedef vector rrVector_t; + typedef std::map RRsetMap_t; + RRsetMap_t preReqRRsets; + for(const auto& i: mdp.d_answers) { + const DNSRecord* rr = &i.first; + if (rr->d_place == DNSResourceRecord::ANSWER) { + // Last line of 3.2.3 + if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY) + return RCode::FormErr; + + if (rr->d_class == QClass::IN) { + rrSetKey_t key = make_pair(rr->d_name, QType(rr->d_type)); + rrVector_t *vec = &preReqRRsets[key]; + vec->push_back(DNSResourceRecord::fromWire(*rr)); + } + } + } + + if (preReqRRsets.size() > 0) { + RRsetMap_t zoneRRsets; + for (RRsetMap_t::iterator preRRSet = preReqRRsets.begin(); preRRSet != preReqRRsets.end(); ++preRRSet) { + rrSetKey_t rrSet=preRRSet->first; + rrVector_t *vec = &preRRSet->second; + + DNSResourceRecord rec; + di.backend->lookup(QType(QType::ANY), rrSet.first, nullptr, di.id); + uint16_t foundRR=0, matchRR=0; + while (di.backend->get(rec)) { + if (rec.qtype == rrSet.second) { + foundRR++; + for(rrVector_t::iterator rrItem=vec->begin(); rrItem != vec->end(); ++rrItem) { + rrItem->ttl = rec.ttl; // The compare one line below also compares TTL, so we make them equal because TTL is not user within prerequisite checks. + if (*rrItem == rec) + matchRR++; + } + } + } + if (matchRR != foundRR || foundRR != vec->size()) { + g_log<abortTransaction(); + return RCode::NXRRSet; + } + } + } + + + + // 3.4 - Prescan & Add/Update/Delete records - is all done within a try block. + try { + uint changedRecords = 0; + // 3.4.1 - Prescan section + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) { + const DNSRecord *rr = &i->first; + if (rr->d_place == DNSResourceRecord::AUTHORITY) { + int res = checkUpdatePrescan(rr); + if (res>0) { + g_log<abortTransaction(); + return res; + } + } + } + + bool updatedSerial=false; + NSEC3PARAMRecordContent ns3pr; + bool narrow=false; + bool haveNSEC3 = d_dk.getNSEC3PARAM(di.zone, &ns3pr, &narrow); + bool isPresigned = d_dk.isPresigned(di.zone); + + // 3.4.2 - Perform the updates. + // There's a special condition where deleting the last NS record at zone apex is never deleted (3.4.2.4) + // This means we must do it outside the normal performUpdate() because that focusses only on a separate RR. + vector nsRRtoDelete; + + // Another special case is the addition of both a CNAME and a non-CNAME for the same name (#6270) + set cn, nocn; + for (const auto &rr : mdp.d_answers) { + if (rr.first.d_place == DNSResourceRecord::AUTHORITY && rr.first.d_class == QClass::IN && rr.first.d_ttl > 0) { + // Addition + if (rr.first.d_type == QType::CNAME) { + cn.insert(rr.first.d_name); + } else if (rr.first.d_type != QType::RRSIG) { + nocn.insert(rr.first.d_name); + } + } + } + for (auto const &n : cn) { + if (nocn.count(n) > 0) { + g_log<abortTransaction(); + return RCode::FormErr; + } + } + + vector cnamesToAdd, nonCnamesToAdd; + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) { + const DNSRecord *rr = &i->first; + if (rr->d_place == DNSResourceRecord::AUTHORITY) { + /* see if it's permitted by policy */ + if (this->d_update_policy_lua != NULL) { + if (this->d_update_policy_lua->updatePolicy(rr->d_name, QType(rr->d_type), di.zone, p) == false) { + g_log<d_name << "/" << QType(rr->d_type).getName() << ": Not permitted by policy"<d_name << "/" << QType(rr->d_type).getName() << ": Permitted by policy"<d_class == QClass::NONE && rr->d_type == QType::NS && rr->d_name == di.zone) + nsRRtoDelete.push_back(rr); + else if (rr->d_class == QClass::IN && rr->d_ttl > 0) { + if (rr->d_type == QType::CNAME) { + cnamesToAdd.push_back(rr); + } else { + nonCnamesToAdd.push_back(rr); + } + } + else + changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial); + } + } + for (const auto &rr : cnamesToAdd) { + DNSResourceRecord rec; + di.backend->lookup(QType(QType::ANY), rr->d_name, nullptr, di.id); + while (di.backend->get(rec)) { + if (rec.qtype != QType::CNAME && rec.qtype != QType::ENT && rec.qtype != QType::RRSIG) { + // leave database handle in a consistent state + while (di.backend->get(rec)) + ; + g_log<d_name << "/" << QType(rr->d_type).getName() << ": Data other than CNAME exists for the same name"<abortTransaction(); + return RCode::Refused; + } + } + changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial); + } + for (const auto &rr : nonCnamesToAdd) { + DNSResourceRecord rec; + di.backend->lookup(QType(QType::CNAME), rr->d_name, nullptr, di.id); + while (di.backend->get(rec)) { + if (rec.qtype == QType::CNAME && rr->d_type != QType::RRSIG) { + // leave database handle in a consistent state + while (di.backend->get(rec)) + ; + g_log<d_name << "/" << QType(rr->d_type).getName() << ": CNAME exists for the same name"<abortTransaction(); + return RCode::Refused; + } + } + changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial); + } + if (nsRRtoDelete.size()) { + vector nsRRInZone; + DNSResourceRecord rec; + di.backend->lookup(QType(QType::NS), di.zone, nullptr, di.id); + while (di.backend->get(rec)) { + nsRRInZone.push_back(rec); + } + if (nsRRInZone.size() > nsRRtoDelete.size()) { // only delete if the NS's we delete are less then what we have in the zone (3.4.2.4) + for (auto& inZone: nsRRInZone) { + for (auto& rr: nsRRtoDelete) { + if (inZone.getZoneRepresentation() == (rr)->d_content->getZoneRepresentation()) + changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial); + } + } + } + } + + // Section 3.6 - Update the SOA serial - outside of performUpdate because we do a SOA update for the complete update message + if (changedRecords > 0 && !updatedSerial) { + increaseSerial(msgPrefix, &di, haveNSEC3, narrow, &ns3pr); + changedRecords++; + } + + if (changedRecords > 0) { + if (!di.backend->commitTransaction()) { + g_log< notify; + B.getDomainMetadata(p->qdomain, "NOTIFY-DNSUPDATE", notify); + if (!notify.empty() && notify.front() == "1") { + Communicator.notifyDomain(di.zone, &B); + } + } + + g_log<abortTransaction(); + } + return RCode::NoError; //rfc 2136 3.4.2.5 + } + catch (SSqlException &e) { + g_log<abortTransaction(); + return RCode::ServFail; + } + catch (DBException &e) { + g_log<abortTransaction(); + return RCode::ServFail; + } + catch (PDNSException &e) { + g_log<abortTransaction(); + return RCode::ServFail; + } + catch(std::exception &e) { + g_log<abortTransaction(); + return RCode::ServFail; + } + catch (...) { + g_log<abortTransaction(); + return RCode::ServFail; + } +} + +void PacketHandler::increaseSerial(const string &msgPrefix, const DomainInfo *di, bool haveNSEC3, bool narrow, const NSEC3PARAMRecordContent *ns3pr) { + SOAData sd; + if (!di->backend->getSOA(di->zone, sd)) { + throw PDNSException("SOA-Serial update failed because there was no SOA. Wowie."); + } + + uint32_t oldSerial = sd.serial; + + vector soaEdit2136Setting; + B.getDomainMetadata(di->zone, "SOA-EDIT-DNSUPDATE", soaEdit2136Setting); + string soaEdit2136 = "DEFAULT"; + string soaEdit; + if (!soaEdit2136Setting.empty()) { + soaEdit2136 = soaEdit2136Setting[0]; + if (pdns_iequals(soaEdit2136, "SOA-EDIT") || pdns_iequals(soaEdit2136,"SOA-EDIT-INCREASE") ){ + string soaEditSetting; + d_dk.getSoaEdit(di->zone, soaEditSetting); + if (soaEditSetting.empty()) { + g_log<zone.toLogString() <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<backend->replaceRRSet(di->id, rr.qname, rr.qtype, vector(1, rr)); + g_log << Logger::Notice << msgPrefix << "Increasing SOA serial (" << oldSerial << " -> " << sd.serial << ")" << endl; + + //Correct ordername + auth flag + if (haveNSEC3) { + DNSName ordername; + if (!narrow) + ordername = DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, rr.qname))); + + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr.qname, ordername, true); + } else { // NSEC + DNSName ordername = rr.qname.makeRelative(di->zone); + di->backend->updateDNSSECOrderNameAndAuth(di->id, rr.qname, ordername, true); + } + } +} diff --git a/pdns/root-dnssec.hh b/pdns/root-dnssec.hh new file mode 100644 index 0000000..3ee5e9b --- /dev/null +++ b/pdns/root-dnssec.hh @@ -0,0 +1,25 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +static const char* const rootDSs[]={"20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d"}; diff --git a/pdns/saxfr.cc b/pdns/saxfr.cc new file mode 100644 index 0000000..6410085 --- /dev/null +++ b/pdns/saxfr.cc @@ -0,0 +1,308 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "base64.hh" +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "base32.hh" +#include "dnssecinfra.hh" + +#include "dns_random.hh" +#include "gss_context.hh" + +StatBag S; + +int main(int argc, char** argv) +try +{ + if(argc < 4) { + cerr<<"Syntax: saxfr IP-address port zone [showdetails] [showflags] [unhash] [gss:remote-principal] [tsig:keyname:algo:secret]"< 4) { + for(int i=4; i parts; + tsig=true; + stringtok(parts, argv[i], ":"); + if (parts.size()!=4) { + cerr<<"Invalid syntax for tsig"< packet; + uint16_t len; + ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2])); + Socket sock(dest.sin4.sin_family, SOCK_STREAM); + sock.connect(dest); + + if (gss) { +#ifndef ENABLE_GSS_TSIG + cerr<<"No GSS support compiled in"<id = dns_random(0xffff); + pwtkey.startRecord(gssctx.getLabel(), QType::TKEY, 3600, QClass::ANY, DNSResourceRecord::ADDITIONAL, false); + tkrc.toPacket(pwtkey); + pwtkey.commit(); + for(const string& msg : gssctx.getErrorStrings()) { + cerr<first.d_type != QType::TKEY) continue; + // recover TKEY record + tkrc = TKEYRecordContent(i->first.d_content->getZoneRepresentation()); + input = tkrc.d_key; + } + } + + if (gssctx.valid() == false) { + cerr<<"Could not create GSS context"<id = dns_random(0xffff); + + if (tsig) { + TSIGRecordContent trc; + trc.d_algoName = getTSIGAlgoName(tsig_algo); + trc.d_time = time((time_t*)NULL); + trc.d_fudge = 300; + trc.d_origID=ntohs(pw.getHeader()->id); + trc.d_eRcode=0; + addTSIG(pw, trc, tsig_key, tsig_secret, "", false); + } + + len = htons(packet.size()); + if(sock.write((char *) &len, 2) != 2) + throw PDNSException("tcp write failed"); + + sock.writen(string(packet.begin(), packet.end())); + + bool isNSEC3 = false; + int soacount=0; + vector > records; + set labels; + map hashes; + NSEC3PARAMRecordContent ns3pr; + + while(soacount<2) { + TSIGRecordContent trc; + + if(sock.read((char *) &len, 2) != 2) + throw PDNSException("tcp read failed"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(nfirst.d_type == QType::TSIG) { + string message; + if (!tsig) { + std::cerr<<"Unexpected TSIG signature in data"<first.d_content->getZoneRepresentation()); + continue; + } + if(i->first.d_type == QType::SOA) + { + ++soacount; + } + else if (i->first.d_type == QType::NSEC3PARAM) { + ns3pr = NSEC3PARAMRecordContent(i->first.d_content->getZoneRepresentation()); + isNSEC3 = true; + } + + ostringstream o; + o<<"\t"<first.d_ttl<<"\tIN\t"<first.d_type); + if(showdetails) + { + o<<"\t"<first.d_content->getZoneRepresentation(); + } + else if(i->first.d_type == QType::RRSIG) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + o<<"\t"<first.d_type == QType::NSEC3) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + o<<"\t"<::iterator iter = parts.begin()+5; iter != parts.end(); ++iter) + o<<" "<<*iter; + } + else if(i->first.d_type == QType::DNSKEY) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + o<<"\t"<first.d_content->getZoneRepresentation(); + } + + records.push_back(make_pair(i->first.d_name,o.str())); + + DNSName shorter(i->first.d_name); + do { + labels.insert(shorter); + if (shorter == DNSName(argv[3])) + break; + }while(shorter.chopOff()); + + } + + delete[] creply; + } + + if (isNSEC3 && unhash) + { + string hashed; + for(const auto &label: labels) { + hashed=toBase32Hex(hashQNameWithSalt(ns3pr, label)); + hashes.insert(pair(hashed, label)); + } + } + + for(auto &record: records) { + DNSName label /* FIXME400 rename */=record.first; + if (isNSEC3 && unhash) + { + auto i = hashes.find(label.makeRelative(DNSName(argv[3])).toStringNoDot()); + if (i != hashes.end()) + label=i->second; + } + cout< +#include "ednssubnet.hh" + +#ifdef HAVE_LIBCURL +#include "minicurl.hh" +#endif + +StatBag S; + +bool hidettl=false; + +string ttl(uint32_t ttl) +{ + if(hidettl) + return "[ttl]"; + else + return std::to_string(ttl); +} + +void usage() { + cerr<<"sdig"< ednsnm; + uint16_t xpfcode = 0, xpfversion = 0, xpfproto = 0; + char *xpfsrc = NULL, *xpfdst = NULL; + + for(int i=1; i 5) { + for(int i=5; i packet; + + DNSPacketWriter pw(packet, DNSName(argv[3]), DNSRecordContent::TypeToNumber(argv[4])); + + if(dnssec || ednsnm || getenv("SDIGBUFSIZE")) + { + char *sbuf=getenv("SDIGBUFSIZE"); + int bufsize; + if(sbuf) + bufsize=atoi(sbuf); + else + bufsize=2800; + DNSPacketWriter::optvect_t opts; + if(ednsnm) { + EDNSSubnetOpts eo; + eo.source = *ednsnm; + opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(eo))); + } + + pw.addOpt(bufsize, 0, dnssec ? EDNSOpts::DNSSECOK : 0, opts); + pw.commit(); + } + + if(xpfcode) + { + ComboAddress src(xpfsrc), dst(xpfdst); + pw.startRecord(DNSName("."), xpfcode, 0, 1, DNSResourceRecord::ADDITIONAL); + // xpf->toPacket(pw); + pw.xfr8BitInt(xpfversion); + pw.xfr8BitInt(xpfproto); + pw.xfrCAWithoutPort(xpfversion, src); + pw.xfrCAWithoutPort(xpfversion, dst); + pw.xfrCAPort(src); + pw.xfrCAPort(dst); + pw.commit(); + } + + if(recurse) + { + pw.getHeader()->rd=true; + } + + string reply; + string question(packet.begin(), packet.end()); + ComboAddress dest; + if(*argv[1]=='h') { + doh = true; + } + else { + dest = ComboAddress(argv[1] + (*argv[1]=='@'), atoi(argv[2])); + } + + if(doh) { +#ifdef HAVE_LIBCURL + MiniCurl mc; + MiniCurl::MiniCurlHeaders mch; + mch.insert(std::make_pair("Content-Type", "application/dns-message")); + mch.insert(std::make_pair("Accept", "application/dns-message")); + reply = mc.postURL(argv[1], question, mch); +#else + throw PDNSException("please link sdig against libcurl for DoH support"); +#endif + } + else if(tcp) { + Socket sock(dest.sin4.sin_family, SOCK_STREAM); + sock.connect(dest); + uint16_t len; + len = htons(packet.size()); + if(sock.write((char *) &len, 2) != 2) + throw PDNSException("tcp write failed"); + + sock.writen(question); + + if(sock.read((char *) &len, 2) != 2) + throw PDNSException("tcp read failed"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(nfirst.d_place-1<<"\t"<first.d_name.toString()<<"\t"<first.d_class, i->first.d_type)<<"\t"<first.d_type); + if(i->first.d_class == QClass::IN) + { + if(i->first.d_type == QType::RRSIG) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + cout<<"\t"<first.d_ttl)<<"\t"<< parts[0]<<" "<first.d_type == QType::NSEC3) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + cout<<"\t"<first.d_ttl)<<"\t"<< parts[0]<<" [flags] "<::iterator iter = parts.begin()+5; iter != parts.end(); ++iter) + cout<<" "<<*iter; + cout<<"\n"; + continue; + } + if(i->first.d_type == QType::DNSKEY) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + cout<<"\t"<first.d_ttl)<<"\t"<< parts[0]<<" "<first.d_type == QType::SOA && hidesoadetails) + { + string zoneRep = i->first.d_content->getZoneRepresentation(); + vector parts; + stringtok(parts, zoneRep); + cout<<"\t"<first.d_ttl)<<"\t"<first.d_ttl)<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n"; + } + + EDNSOpts edo; + if(getEDNSOpts(mdp, &edo)) { +// cerr<<"Have "< >::const_iterator iter = edo.d_options.begin(); + iter != edo.d_options.end(); + ++iter) { + if(iter->first == EDNSOptionCode::ECS) {// 'EDNS subnet' + EDNSSubnetOpts reso; + if(getEDNSSubnetOptsFromString(iter->second, &reso)) { + cerr<<"EDNS Subnet response: "<second.size())<first< +#ifndef PACKAGEVERSION +#define PACKAGEVERSION getPDNSVersion() +#endif + +string g_security_message; + +extern StatBag S; + +/** Do an actual secpoll for the current version + * @param first bool that tells if this is the first secpoll run since startup + */ +void doSecPoll(bool first) +{ + if(::arg()["security-poll-suffix"].empty()) + return; + + struct timeval now; + gettimeofday(&now, 0); + + string version = "auth-" + string(PACKAGEVERSION); + string query = version.substr(0, 63) +".security-status."+::arg()["security-poll-suffix"]; + + if(*query.rbegin()!='.') + query+='.'; + + boost::replace_all(query, "+", "_"); + boost::replace_all(query, "~", "_"); + + vector ret; + + int res=stubDoResolve(DNSName(query), QType::TXT, ret); + + int security_status=0; + + if(!res && !ret.empty()) { + string content=getRR(ret.begin()->dr)->d_text; + + pair split = splitField(unquotify(content), ' '); + + security_status = std::stoi(split.first); + g_security_message = split.second; + + } + else { + string pkgv(PACKAGEVERSION); + if(pkgv.find("0.0.") != 0) + g_log< +#include "namespaces.hh" +#include "stubresolver.hh" + +void doSecPoll(bool first); +extern std::string g_security_message; + +#endif diff --git a/pdns/serialtweaker.cc b/pdns/serialtweaker.cc new file mode 100644 index 0000000..3ec6fe7 --- /dev/null +++ b/pdns/serialtweaker.cc @@ -0,0 +1,182 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002-2011 PowerDNS.COM BV + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation + + Additionally, the license of this program contains a special + exception which allows to distribute the program in binary form when + it is linked against OpenSSL. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnsseckeeper.hh" +#include "dnspacket.hh" +#include "namespaces.hh" + +uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq) +{ + struct tm tm; + localtime_r(&t, &tm); + return + (uint32_t)(tm.tm_year+1900) * 1000000u + + (uint32_t)(tm.tm_mon + 1) * 10000u + + (uint32_t)tm.tm_mday * 100u + + seq; +} + +uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename) +{ + if(pdns_iequals(kind,"INCEPTION-INCREMENT")) { + time_t inception = getStartOfWeek(); + uint32_t inception_serial = localtime_format_YYYYMMDDSS(inception, 1); + uint32_t dont_increment_after = localtime_format_YYYYMMDDSS(inception + 2*86400, 99); + + if(old_serial < inception_serial - 1) { /* less than 00 */ + return inception_serial; /* return 01 (skipping 00 as possible value) */ + } else if (old_serial < inception_serial+1) { + /* "00" and "01" are reserved for inception increasing, so jump to "02" */ + return inception_serial+1; + } else if(old_serial <= dont_increment_after) { /* >= 00 but <= 99 */ + return old_serial + 1; + } + } + else if(pdns_iequals(kind,"INCREMENT-WEEKS")) { + time_t inception = getStartOfWeek(); + return (old_serial + (inception / (7*86400))); + } + else if(pdns_iequals(kind,"EPOCH")) { + return time(0); + } + else if(pdns_iequals(kind,"INCEPTION-EPOCH")) { + uint32_t inception = getStartOfWeek(); + if (old_serial < inception) + return inception; + } + else if(pdns_iequals(kind,"NONE")) { + // do nothing to serial. needed because a metadata of "" will use the default-soa-edit setting instead. + } + else if(!kind.empty()) { + g_log<getZoneRepresentation(true); + return true; +} + +/** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API. + * Makes a mostly reset DNSResourceRecord for you in @param rrout. + * Content in rrout is suitable for writing into a backend. + * + * @return true if rrout is now valid + */ +bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout) { + if (increaseKind.empty()) + return false; + + sd.serial = calculateIncreaseSOA(sd.serial, increaseKind, editKind, sd.qname); + rrout.qname = sd.qname; + rrout.content = makeSOAContent(sd)->getZoneRepresentation(true); + rrout.qtype = QType::SOA; + rrout.domain_id = sd.domain_id; + rrout.auth = 1; + rrout.ttl = sd.ttl; + + return true; +} + +DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DNSResourceRecord::Place place) { + SOAData edited = sd; + edited.serial = calculateEditSOA(sd.serial, dk, sd.qname); + + DNSRecord soa; + soa.d_name = sd.qname; + soa.d_type = QType::SOA; + soa.d_ttl = sd.ttl; + soa.d_place = place; + soa.d_content = makeSOAContent(edited); + + DNSZoneRecord dzr; + dzr.domain_id = sd.domain_id; + dzr.signttl = sd.ttl; + dzr.auth = true; + dzr.dr = soa; + + return dzr; +} diff --git a/pdns/sha.hh b/pdns/sha.hh new file mode 100644 index 0000000..19363ce --- /dev/null +++ b/pdns/sha.hh @@ -0,0 +1,57 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef _SHA_HH +#define _SHA_HH + +#include +#include +#include + +inline std::string pdns_sha1sum(const std::string& input) +{ + unsigned char result[20] = {0}; + SHA1(reinterpret_cast(input.c_str()), input.length(), result); + return std::string(result, result + sizeof result); +} + +inline std::string pdns_sha256sum(const std::string& input) +{ + unsigned char result[32] = {0}; + SHA256(reinterpret_cast(input.c_str()), input.length(), result); + return std::string(result, result + sizeof result); +} + +inline std::string pdns_sha384sum(const std::string& input) +{ + unsigned char result[48] = {0}; + SHA384(reinterpret_cast(input.c_str()), input.length(), result); + return std::string(result, result + sizeof result); +} + +inline std::string pdns_sha512sum(const std::string& input) +{ + unsigned char result[64] = {0}; + SHA512(reinterpret_cast(input.c_str()), input.length(), result); + return std::string(result, result + sizeof result); +} + +#endif /* sha.hh */ diff --git a/pdns/sholder.hh b/pdns/sholder.hh new file mode 100644 index 0000000..75837c3 --- /dev/null +++ b/pdns/sholder.hh @@ -0,0 +1,138 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include +#include +#include +/** This is sort of a light-weight RCU idea. + Suitable for when you frequently consult some "readonly" state, which infrequently + gets changed. One way of dealing with this is fully locking access to the state, but + this is rather wasteful. + + Instead, in the code below, the frequent users of the state get a "readonly" copy of it, + which they can consult. On access, we atomically compare if the local copy is still current + with the global one. If it isn't we do the lock thing, and create a new local copy. + + Meanwhile, to upgrade the global state, methods are offered that do appropriate locking + and upgrade the 'generation' counter, signaling to the local copies that they need to be + refreshed on the next access. + + Two ways to change the global copy are available: + getCopy(), which delivers a deep copy of the current state, followed by setState() + modify(), which accepts a (lambda)function that modifies the state + + NOTE: The actual destruction of the 'old' state happens when the last local state + relinquishes its access to the state. + + "read-only" + Sometimes, a 'state' can contain parts that can safely be modified by multiple users, for + example, atomic counters. In such cases, it may be useful to explicitly declare such counters + as mutable. */ + +template class GlobalStateHolder; + +template +class LocalStateHolder +{ +public: + explicit LocalStateHolder(GlobalStateHolder* source) : d_source(source) + {} + + const T* operator->() // fast const-only access, but see "read-only" above + { + if(d_source->getGeneration() != d_generation) { + d_source->getState(&d_state, & d_generation); + } + + return d_state.get(); + } + const T& operator*() // fast const-only access, but see "read-only" above + { + return *operator->(); + } + + void reset() + { + d_generation=0; + d_state.reset(); + } +private: + std::shared_ptr d_state; + unsigned int d_generation{0}; + const GlobalStateHolder* d_source; +}; + +template +class GlobalStateHolder +{ +public: + GlobalStateHolder() : d_state(std::make_shared()) + {} + LocalStateHolder getLocal() + { + return LocalStateHolder(this); + } + + void setState(T state) //!< Safely & slowly change the global state + { + std::shared_ptr newState = std::make_shared(state); + { + std::lock_guard l(d_lock); + d_state = newState; + d_generation++; + } + } + + T getCopy() const //!< Safely & slowly get a copy of the global state + { + std::lock_guard l(d_lock); + return *d_state; + } + + //! Safely & slowly modify the global state + template + void modify(F act) { + std::lock_guard l(d_lock); + auto state=*d_state; // and yes, these three steps are necessary, can't ever modify state in place, even when locked! + act(state); + d_state = std::make_shared(state); + ++d_generation; + } + + + typedef T value_type; +private: + unsigned int getGeneration() const + { + return d_generation; + } + void getState(std::shared_ptr* state, unsigned int* generation) const + { + std::lock_guard l(d_lock); + *state=d_state; + *generation = d_generation; + } + friend class LocalStateHolder; + mutable std::mutex d_lock; + std::shared_ptr d_state; + std::atomic d_generation{1}; +}; diff --git a/pdns/signingpipe.cc b/pdns/signingpipe.cc new file mode 100644 index 0000000..6c98dd5 --- /dev/null +++ b/pdns/signingpipe.cc @@ -0,0 +1,344 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "signingpipe.hh" +#include "misc.hh" +#include + +#include +#include +#include +#include + +// deal with partial reads +namespace { +int readn(int fd, void* buffer, unsigned int len) +{ + unsigned int pos=0; + int res; + for(;;) { + res = read(fd, (char*)buffer + pos, len - pos); + if(res == 0) { + if(pos) + throw runtime_error("Signing Pipe remote shut down in the middle of a message"); + else { + //cerr<<"Got decent EOF on "<worker(fd); + return nullptr; +} +catch(...) { + g_log<()); // load an empty chunk + + if(!d_mustSign) + return; + + int fds[2]; + + for(unsigned int n=0; n < d_numworkers; ++n) { + if(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) + throw runtime_error("Unable to create communication socket in for ChunkedSigningPipe"); + setCloseOnExec(fds[0]); + setCloseOnExec(fds[1]); + d_threads[n] = std::thread(helperWorker, this, fds[1]); + setNonBlocking(fds[0]); + d_sockets.push_back(fds[0]); + d_outstandings[fds[0]] = 0; + } +} + +ChunkedSigningPipe::~ChunkedSigningPipe() +{ + delete d_rrsetToSign; + + if(!d_mustSign) + return; + + for(int fd : d_sockets) { + close(fd); // this will trigger all threads to exit + } + + for(auto& thread : d_threads) { + thread.join(); + } + //cout<<"Did: "<getZoneRepresentation(), a.dr.d_ttl) < make_tuple(b.dr.d_content->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW +} + +bool dedupEqual(const DNSZoneRecord& a, const DNSZoneRecord &b) +{ + return make_tuple(a.dr.d_content->getZoneRepresentation(), a.dr.d_ttl) == make_tuple(b.dr.d_content->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW +} +} + +void ChunkedSigningPipe::dedupRRSet() +{ + // our set contains contains records for one type and one name, but might not be sorted otherwise + sort(d_rrsetToSign->begin(), d_rrsetToSign->end(), dedupLessThan); + d_rrsetToSign->erase(unique(d_rrsetToSign->begin(), d_rrsetToSign->end(), dedupEqual), d_rrsetToSign->end()); +} + +bool ChunkedSigningPipe::submit(const DNSZoneRecord& rr) +{ + ++d_submitted; + // check if we have a full RRSET to sign + if(!d_rrsetToSign->empty() && (d_rrsetToSign->begin()->dr.d_type != rr.dr.d_type || d_rrsetToSign->begin()->dr.d_name != rr.dr.d_name)) + { + dedupRRSet(); + sendRRSetToWorker(); + } + d_rrsetToSign->push_back(rr); + return !d_chunks.empty() && d_chunks.front().size() >= d_maxchunkrecords; // "you can send more" +} + +pair, vector > ChunkedSigningPipe::waitForRW(bool rd, bool wr, int seconds) +{ + vector pfds; + + for(unsigned int n = 0; n < d_sockets.size(); ++n) { + if(d_eof.count(d_sockets[n])) + continue; + struct pollfd pfd; + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = d_sockets[n]; + if(rd) + pfd.events |= POLLIN; + if(wr) + pfd.events |= POLLOUT; + pfds.push_back(pfd); + } + + int res = poll(&pfds[0], pfds.size(), (seconds < 0) ? -1 : (seconds * 1000)); // -1 = infinite + if(res < 0) + unixDie("polling for activity from signers, "+std::to_string(d_sockets.size())); + pair, vector > vects; + for(unsigned int n = 0; n < pfds.size(); ++n) + if(pfds[n].revents & POLLIN) + vects.first.push_back(pfds[n].fd); + else if(pfds[n].revents & POLLOUT) + vects.second.push_back(pfds[n].fd); + + return vects; +} + +void ChunkedSigningPipe::addSignedToChunks(chunk_t* signedChunk) +{ + chunk_t::const_iterator from = signedChunk->begin(); + + while(from != signedChunk->end()) { + chunk_t& fillChunk = d_chunks.back(); + + chunk_t::size_type room = d_maxchunkrecords - fillChunk.size(); + + unsigned int fit = std::min(room, (chunk_t::size_type)(signedChunk->end() - from)); + + d_chunks.back().insert(fillChunk.end(), from , from + fit); + from+=fit; + + if(from != signedChunk->end()) // it didn't fit, so add a new chunk + d_chunks.push_back(chunk_t()); + } +} + +void ChunkedSigningPipe::sendRRSetToWorker() // it sounds so socialist! +{ + if(!d_mustSign) { + addSignedToChunks(d_rrsetToSign); + d_rrsetToSign->clear(); + return; + } + + if(d_final && !d_outstanding) // nothing to do! + return; + + bool wantRead, wantWrite; + + wantWrite = !d_rrsetToSign->empty(); + wantRead = d_outstanding || wantWrite; // if we wrote, we want to read + + pair, vector > rwVect; + + rwVect = waitForRW(wantRead, wantWrite, -1); // wait for something to happen + + if(wantWrite && !rwVect.second.empty()) { + random_shuffle(rwVect.second.begin(), rwVect.second.end()); // pick random available worker + writen2(*rwVect.second.begin(), &d_rrsetToSign, sizeof(d_rrsetToSign)); + d_rrsetToSign = new rrset_t; + d_outstandings[*rwVect.second.begin()]++; + d_outstanding++; + d_queued++; + wantWrite=false; + } + + if(wantRead) { + while(d_outstanding) { + chunk_t* chunk; + + for(int fd : rwVect.first) { + if(d_eof.count(fd)) + continue; + + while(d_outstanding) { + int res = readn(fd, &chunk, sizeof(chunk)); + if(!res) { + if (d_outstandings[fd] > 0) { + throw std::runtime_error("A signing pipe worker died while we were waiting for its result"); + } + d_eof.insert(fd); + break; + } + if(res < 0) { + if(errno != EAGAIN && errno != EINTR) + unixDie("Error reading signed chunk from thread"); + else + break; + } + + --d_outstanding; + d_outstandings[fd]--; + + addSignedToChunks(chunk); + + delete chunk; + } + } + if(!d_outstanding || !d_final) + break; + rwVect = waitForRW(true, false, -1); // wait for something to happen + } + } + + if(wantWrite) { // our optimization above failed, we now wait synchronously + rwVect = waitForRW(false, wantWrite, -1); // wait for something to happen + random_shuffle(rwVect.second.begin(), rwVect.second.end()); // pick random available worker + writen2(*rwVect.second.begin(), &d_rrsetToSign, sizeof(d_rrsetToSign)); + d_rrsetToSign = new rrset_t; + d_outstandings[*rwVect.second.begin()]++; + d_outstanding++; + d_queued++; + } + +} + +unsigned int ChunkedSigningPipe::getReady() const +{ + unsigned int sum=0; + for(const auto& v : d_chunks) { + sum += v.size(); + } + return sum; +} + +void ChunkedSigningPipe::worker(int fd) +try +{ + UeberBackend db("key-only"); + DNSSECKeeper dk(&db); + + chunk_t* chunk = nullptr; + int res; + for(;;) { + res = readn(fd, &chunk, sizeof(chunk)); + if(!res) + break; + if(res < 0) + unixDie("reading object pointer to sign from pdns"); + try { + set authSet; + authSet.insert(d_signer); + addRRSigs(dk, db, authSet, *chunk); + ++d_signed; + + writen2(fd, &chunk, sizeof(chunk)); + chunk = nullptr; + } + catch(const PDNSException& pe) { + delete chunk; + throw; + } + catch(const std::exception& e) { + delete chunk; + throw; + } + } + close(fd); +} +catch(const PDNSException& pe) +{ + g_log<clear(); +} + +vector ChunkedSigningPipe::getChunk(bool final) +{ + if(final && !d_final) { + // this means we should keep on reading until d_outstanding == 0 + d_final = true; + flushToSign(); + + for(int fd : d_sockets) { + shutdown(fd, SHUT_WR); // perhaps this transmits EOF the other side + //cerr<<"shutdown of "< front=d_chunks.front(); + d_chunks.pop_front(); + if(d_chunks.empty()) + d_chunks.push_back(vector()); +/* if(d_final && front.empty()) + cerr<<"getChunk returning empty in final"< +#include +#include + +#include "dnsseckeeper.hh" +#include "dns.hh" + +void writeLStringToSocket(int fd, const string& msg); +bool readLStringFromSocket(int fd, string& msg); + +/** input: DNSZoneRecords ordered in qname,qtype (we emit a signature chunk on a break) + * output: "chunks" of those very same DNSZoneRecords, interleaved with signatures + */ + +class ChunkedSigningPipe +{ +public: + typedef vector rrset_t; + typedef rrset_t chunk_t; // for now + + ChunkedSigningPipe(const ChunkedSigningPipe&) = delete; + void operator=(const ChunkedSigningPipe&) = delete; + ChunkedSigningPipe(const DNSName& signerName, bool mustSign, unsigned int numWorkers=3); + ~ChunkedSigningPipe(); + bool submit(const DNSZoneRecord& rr); + chunk_t getChunk(bool final=false); + unsigned int getReady() const; + + std::atomic d_signed; + unsigned int d_queued; + unsigned int d_outstanding; + +private: + void flushToSign(); + void dedupRRSet(); + void sendRRSetToWorker(); // dispatch RRSET to worker + void addSignedToChunks(chunk_t* signedChunk); + pair, vector > waitForRW(bool rd, bool wr, int seconds); + + static void* helperWorker(ChunkedSigningPipe* csp, int fd); + void worker(int fd); + + unsigned int d_numworkers; + unsigned int d_submitted; + + rrset_t* d_rrsetToSign; + std::deque< std::vector > d_chunks; + DNSName d_signer; + + chunk_t::size_type d_maxchunkrecords; + + std::vector d_sockets; + std::set d_eof; + std::map d_outstandings; + + vector d_threads; + bool d_mustSign; + bool d_final; +}; + +#endif diff --git a/pdns/sillyrecords.cc b/pdns/sillyrecords.cc new file mode 100644 index 0000000..334e3e1 --- /dev/null +++ b/pdns/sillyrecords.cc @@ -0,0 +1,334 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include +#include +#include +#include +#include +#include +#include "dnsrecords.hh" + +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/ +static uint8_t precsize_aton(const char **strptr) +{ + unsigned int mval = 0, cmval = 0; + uint8_t retval = 0; + const char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit(*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit(*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/* converts ascii lat/lon to unsigned encoded 32-bit number. + * moves pointer. */ +static uint32_t +latlon2ul(const char **latlonstrptr, int *which) +{ + const char *cp; + uint32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit(*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (*cp && !(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit(*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (*cp && !isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /* invalid value -- indicates error */ + break; + } + + switch (*cp) { + case 'N': case 'n': + case 'S': case 's': + *which = 1; /* latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /* longitude */ + break; + default: + *which = 0; /* error */ + break; + } + + if (!*cp) + return 0; + + cp++; /* skip the hemisphere */ + + while (*cp && !isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) /* move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +void LOCRecordContent::report(void) +{ + regist(1, QType::LOC, &make, &make, "LOC"); + regist(254, QType::LOC, &make, &make, "LOC"); +} + +std::shared_ptr LOCRecordContent::make(const string& content) +{ + return std::make_shared(content); +} + + +void LOCRecordContent::toPacket(DNSPacketWriter& pw) +{ + pw.xfr8BitInt(d_version); + pw.xfr8BitInt(d_size); + pw.xfr8BitInt(d_horizpre); + pw.xfr8BitInt(d_vertpre); + + pw.xfr32BitInt(d_latitude); + pw.xfr32BitInt(d_longitude); + pw.xfr32BitInt(d_altitude); +} + +std::shared_ptr LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr) +{ + auto ret=std::make_shared(); + pr.xfr8BitInt(ret->d_version); + pr.xfr8BitInt(ret->d_size); + pr.xfr8BitInt(ret->d_horizpre); + pr.xfr8BitInt(ret->d_vertpre); + + pr.xfr32BitInt(ret->d_latitude); + pr.xfr32BitInt(ret->d_longitude); + pr.xfr32BitInt(ret->d_altitude); + + return ret; +} + +LOCRecordContent::LOCRecordContent(const string& content, const string& zone) +{ + // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m + // convert this to d_version, d_size, d_horiz/vertpre, d_latitude, d_longitude, d_altitude + d_version = 0; + + const char *cp, *maxcp; + + uint32_t lltemp1 = 0, lltemp2 = 0; + int altmeters = 0, altfrac = 0, altsign = 1; + d_horizpre = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ + d_vertpre = 0x13; /* default = 1e3 cm = 10.00m */ + d_size = 0x12; /* default = 1e2 cm = 1.00m */ + int which1 = 0, which2 = 0; + + cp = content.c_str(); + maxcp = cp + strlen(content.c_str()); + + lltemp1 = latlon2ul(&cp, &which1); + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /* 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /* normal case */ + d_latitude = lltemp1; + d_longitude = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/ + d_latitude = lltemp1; + d_longitude = lltemp2; + } else { /* some kind of brokenness */ + return; + } + break; + default: /* we didn't get one of each */ + throw MOADNSException("Error decoding LOC content"); + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit(*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit(*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + d_altitude = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace(*cp) && (cp < maxcp)) + /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + + if (cp >= maxcp) + goto defaults; + + d_size = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + d_horizpre = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + d_vertpre = precsize_aton(&cp); + + defaults: + ; +} + + +string LOCRecordContent::getZoneRepresentation(bool noDot) const +{ + // convert d_version, d_size, d_horiz/vertpre, d_latitude, d_longitude, d_altitude to: + // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m + + double latitude= ((int32_t)d_latitude - (1<<31))/3600000.0; + double longitude=((int32_t)d_longitude - (1<<31))/3600000.0; + double altitude= ((int32_t)d_altitude )/100.0 - 100000; + + double size=0.01*((d_size>>4)&0xf); + int count=d_size & 0xf; + while(count--) + size*=10; + + double horizpre=0.01*((d_horizpre>>4) & 0xf); + count=d_horizpre&0xf; + while(count--) + horizpre*=10; + + double vertpre=0.01*((d_vertpre>>4)&0xf); + count=d_vertpre&0xf; + while(count--) + vertpre*=10; + + double remlat=60.0*(latitude-(int)latitude); + double remlong=60.0*(longitude-(int)longitude); + static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm"); + std::string ret = boost::str( + boost::format(fmt) + % abs((int)latitude) % abs((int) ((latitude-(int)latitude)*60)) + % fabs((double)((remlat-(int)remlat)*60.0)) % (latitude>0 ? 'N' : 'S') + % abs((int)longitude) % abs((int) ((longitude-(int)longitude)*60)) + % fabs((double)((remlong-(int)remlong)*60.0)) % (longitude>0 ? 'E' : 'W') + % altitude % size + % horizpre % vertpre + ); + + return ret; +} diff --git a/pdns/slavecommunicator.cc b/pdns/slavecommunicator.cc new file mode 100644 index 0000000..9f45fde --- /dev/null +++ b/pdns/slavecommunicator.cc @@ -0,0 +1,1008 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "utility.hh" +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include "base32.hh" +#include +#include "communicator.hh" +#include +#include +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "packethandler.hh" +#include "resolver.hh" +#include "logger.hh" +#include "dns.hh" +#include "arguments.hh" +#include "auth-caches.hh" + +#include "base64.hh" +#include "inflighter.cc" +#include "namespaces.hh" +#include "common_startup.hh" + +#include "ixfr.hh" +using boost::scoped_ptr; + + +void CommunicatorClass::addSuckRequest(const DNSName &domain, const ComboAddress& master) +{ + Lock l(&d_lock); + SuckRequest sr; + sr.domain = domain; + sr.master = master; + pair res; + + res=d_suckdomains.push_back(sr); + if(res.second) { + d_suck_sem.post(); + } + +} + +struct ZoneStatus +{ + bool isDnssecZone{false}; + bool isPresigned{false}; + bool isNSEC3 {false}; + bool optOutFlag {false}; + NSEC3PARAMRecordContent ns3pr; + + bool isNarrow{false}; + unsigned int soa_serial{0}; + set nsset, qnames, secured; + uint32_t domain_id; + int numDeltas{0}; +}; + + +void CommunicatorClass::ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, scoped_ptr& pdl, + ZoneStatus& zs, vector* axfr) +{ + UeberBackend B; // fresh UeberBackend + + DomainInfo di; + di.backend=0; + // bool transaction=false; + try { + DNSSECKeeper dk (&B); // reuse our UeberBackend copy for DNSSECKeeper + + bool wrongDomainKind = false; + // this checks three error conditions, and sets wrongDomainKind if we hit the third & had an error + if(!B.getDomainInfo(domain, di) || !di.backend || (wrongDomainKind = true, di.kind != DomainInfo::Slave)) { // di.backend and B are mostly identical + if(wrongDomainKind) + g_log<(g_rootdnsname, g_rootdnsname, st); + auto deltas = getIXFRDeltas(remote, domain, drsoa, tt, laddr.sin4.sin_family ? &laddr : 0, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024); + zs.numDeltas=deltas.size(); + // cout<<"Got "<& rrset) + // which thinks in terms of RRSETs + // however, IXFR does not, and removes and adds *records* (bummer) + // this means that we must group updates by {qname,qtype}, retrieve the RRSET, apply + // the add/remove updates, and replaceRRSet the whole thing. + + + map, pair, vector > > grouped; + + for(const auto& x: remove) + grouped[{x.d_name, x.d_type}].first.push_back(x); + for(const auto& x: add) + grouped[{x.d_name, x.d_type}].second.push_back(x); + + di.backend->startTransaction(domain, -1); + for(const auto g : grouped) { + vector rrset; + { + DNSZoneRecord zrr; + B.lookup(QType(g.first.second), g.first.first+domain, 0, di.id); + while(B.get(zrr)) { + zrr.dr.d_name.makeUsRelative(domain); + rrset.push_back(zrr.dr); + } + } + // O(N^2)! + rrset.erase(remove_if(rrset.begin(), rrset.end(), + [&g](const DNSRecord& dr) { + return count(g.second.first.cbegin(), + g.second.first.cend(), dr); + }), rrset.end()); + // the DNSRecord== operator compares on name, type, class and lowercase content representation + + for(const auto& x : g.second.second) { + rrset.push_back(x); + } + + vector replacement; + for(const auto& dr : rrset) { + auto rr = DNSResourceRecord::fromWire(dr); + rr.qname += domain; + rr.domain_id = di.id; + if(dr.d_type == QType::SOA) { + // cout<<"New SOA: "<getZoneRepresentation()<(dr); + zs.soa_serial=sr->d_st.serial; + } + + replacement.push_back(rr); + } + + di.backend->replaceRRSet(di.id, g.first.first+domain, QType(g.first.second), replacement); + } + di.backend->commitTransaction(); + } + } + catch(std::exception& p) { + g_log< doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr, scoped_ptr& pdl, ZoneStatus& zs) +{ + uint16_t axfr_timeout=::arg().asNum("axfr-fetch-timeout"); + vector rrs; + AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024, axfr_timeout); + Resolver::res_t recs; + bool first=true; + bool firstNSEC3{true}; + bool soa_received {false}; + while(retriever.getChunk(recs, nullptr, axfr_timeout)) { + if(first) { + g_log<qname.makeUsLowerCase(); + if(i->qtype.getCode() == QType::OPT || i->qtype.getCode() == QType::TSIG) // ignore EDNS0 & TSIG + continue; + + if(!i->qname.isPartOf(domain)) { + g_log<qname<<"'|"<qtype.getName()<<" during AXFR of zone '"< out; + if(!pdl || !pdl->axfrfilter(raddr, domain, *i, out)) { + out.push_back(*i); // if axfrfilter didn't do anything, we put our record in 'out' ourselves + } + + for(DNSResourceRecord& rr : out) { + if(!rr.qname.isPartOf(domain)) { + g_log<qname<<"'|"<qtype.getName()<<" during AXFR of zone '"< pdl; + vector scripts; + string script=::arg()["lua-axfr-script"]; + if(B.getDomainMetadata(domain, "LUA-AXFR-SCRIPT", scripts) && !scripts.empty()) { + if (pdns_iequals(scripts[0], "NONE")) { + script.clear(); + } else { + script=scripts[0]; + } + } + if(!script.empty()){ + try { + pdl.reset(new AuthLua4()); + pdl->loadFile(script); + g_log< localaddr; + ComboAddress laddr; + + if(B.getDomainMetadata(domain, "AXFR-SOURCE", localaddr) && !localaddr.empty()) { + try { + laddr = ComboAddress(localaddr[0]); + g_log< rrs; + if(dk.isSecuredZone(domain)) { + hadDnssecZone=true; + hadPresigned=dk.isPresigned(domain); + if (dk.getNSEC3PARAM(domain, &zs.ns3pr, &zs.isNarrow)) { + hadNSEC3 = true; + hadNs3pr = zs.ns3pr; + hadNarrow = zs.isNarrow; + } + } + else if(di.serial) { + vector meta; + B.getDomainMetadata(domain, "IXFR", meta); + if(!meta.empty() && meta[0]=="1") { + vector axfr; + g_log<(dr); + zs.soa_serial = sd->d_st.serial; + } + rrs.push_back(rr); + } + } + else { + g_log<startTransaction(domain, zs.domain_id); + g_log< rrterm; + map nonterm; + + + for(DNSResourceRecord& rr : rrs) { + if(!zs.isPresigned) { + if (rr.qtype.getCode() == QType::RRSIG) + continue; + if(zs.isDnssecZone && rr.qtype.getCode() == QType::DNSKEY && !::arg().mustDo("direct-dnskey")) + continue; + } + + // Figure out auth and ents + rr.auth=true; + shorter=rr.qname; + rrterm.clear(); + do { + if(doent) { + if (!zs.qnames.count(shorter)) + rrterm.insert(shorter); + } + if(zs.nsset.count(shorter) && rr.qtype.getCode() != QType::DS) + rr.auth=false; + + if (shorter==domain) // stop at apex + break; + }while(shorter.chopOff()); + + // Insert ents + if(doent && !rrterm.empty()) { + bool auth; + if (!rr.auth && rr.qtype.getCode() == QType::NS) { + if (zs.isNSEC3) + ordername=DNSName(toBase32Hex(hashQNameWithSalt(zs.ns3pr, rr.qname))); + auth=(!zs.isNSEC3 || !zs.optOutFlag || zs.secured.count(ordername)); + } else + auth=rr.auth; + + for(const auto &nt: rrterm){ + if (!nonterm.count(nt)) + nonterm.insert(pair(nt, auth)); + else if (auth) + nonterm[nt]=true; + } + + if(nonterm.size() > maxent) { + g_log<feedRecord(rr, ordername, true); + } else + di.backend->feedRecord(rr, DNSName()); + } else { + // NSEC + if (rr.auth || rr.qtype.getCode() == QType::NS) { + ordername=rr.qname.makeRelative(domain); + di.backend->feedRecord(rr, ordername); + } else + di.backend->feedRecord(rr, DNSName()); + } + } else + di.backend->feedRecord(rr, DNSName()); + } + + // Insert empty non-terminals + if(doent && !nonterm.empty()) { + if (zs.isNSEC3) { + di.backend->feedEnts3(zs.domain_id, domain, nonterm, zs.ns3pr, zs.isNarrow); + } else + di.backend->feedEnts(zs.domain_id, nonterm); + } + + di.backend->commitTransaction(); + transaction = false; + di.backend->setFresh(zs.domain_id); + purgeAuthCaches(domain.toString()+"$"); + + + g_log< meta; + if (B.getDomainMetadata(domain, "SLAVE-RENOTIFY", meta) && meta.size() > 0) { + if (meta[0] == "1") { + renotify = true; + } else { + renotify = false; + } + } + if(renotify) + notifyDomain(domain, &B); + } + catch(DBException &re) { + g_log<abortTransaction(); + } + } + catch(const MOADNSException &mde) { + g_log<abortTransaction(); + } + } + catch(std::exception &re) { + g_log<abortTransaction(); + } + } + catch(ResolverException &re) { + { + Lock l(&d_lock); + // The AXFR probably failed due to a problem on the master server. If SOA-checks against this master + // still succeed, we would constantly try to AXFR the zone. To avoid this, we add the zone to the list of + // failed slave-checks. This will suspend slave-checks (and subsequent AXFR) for this zone for some time. + uint64_t newCount = 1; + time_t now = time(0); + const auto failedEntry = d_failedSlaveRefresh.find(domain); + if (failedEntry != d_failedSlaveRefresh.end()) + newCount = d_failedSlaveRefresh[domain].first + 1; + time_t nextCheck = now + std::min(newCount * d_tickinterval, (uint64_t)::arg().asNum("soa-retry-default")); + d_failedSlaveRefresh[domain] = {newCount, nextCheck}; + g_log<abortTransaction(); + } + } + catch(PDNSException &ae) { + g_log<abortTransaction(); + } + } +} +namespace { +struct DomainNotificationInfo +{ + DomainInfo di; + bool dnssecOk; + ComboAddress localaddr; + DNSName tsigkeyname, tsigalgname; + string tsigsecret; +}; +} + + +struct SlaveSenderReceiver +{ + typedef std::tuple Identifier; + + struct Answer { + uint32_t theirSerial; + uint32_t theirInception; + uint32_t theirExpire; + }; + + map d_freshness; + + SlaveSenderReceiver() + { + } + + void deliverTimeout(const Identifier& i) + { + } + + Identifier send(DomainNotificationInfo& dni) + { + random_shuffle(dni.di.masters.begin(), dni.di.masters.end()); + try { + return std::make_tuple(dni.di.zone, + *dni.di.masters.begin(), + d_resolver.sendResolve(*dni.di.masters.begin(), + dni.localaddr, + dni.di.zone, + QType::SOA, + nullptr, + dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret) + ); + } + catch(PDNSException& e) { + throw runtime_error("While attempting to query freshness of '"+dni.di.zone.toLogString()+"': "+e.reason); + } + } + + bool receive(Identifier& id, Answer& a) + { + if(d_resolver.tryGetSOASerial(&(std::get<0>(id)), &(std::get<1>(id)), &a.theirSerial, &a.theirInception, &a.theirExpire, &(std::get<2>(id)))) { + return 1; + } + return 0; + } + + void deliverAnswer(DomainNotificationInfo& dni, const Answer& a, unsigned int usec) + { + d_freshness[dni.di.id]=a; + } + + Resolver d_resolver; +}; + +void CommunicatorClass::addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote) +{ + Lock l(&d_lock); + DomainInfo ours = di; + ours.backend = 0; + + // When adding a check, if the remote addr from which notification was + // received is a master, clear all other masters so we can be sure the + // query goes to that one. + for (const auto& master : di.masters) { + if (ComboAddress::addressOnlyEqual()(remote, master)) { + ours.masters.clear(); + ours.masters.push_back(master); + break; + } + } + d_tocheck.erase(di); + d_tocheck.insert(ours); + d_any_sem.post(); // kick the loop! +} + +void CommunicatorClass::addTrySuperMasterRequest(DNSPacket *p) +{ + Lock l(&d_lock); + DNSPacket ours = *p; + if(d_potentialsupermasters.insert(ours).second) + d_any_sem.post(); // kick the loop! +} + +void CommunicatorClass::slaveRefresh(PacketHandler *P) +{ + // not unless we are slave + if (!::arg().mustDo("slave")) return; + + UeberBackend *B=P->getBackend(); + vector rdomains; + vector sdomains; + set trysuperdomains; + { + Lock l(&d_lock); + set requeue; + for(const auto& di: d_tocheck) { + if(d_inprogress.count(di.zone)) { + g_log<trySuperMasterSynchronous(&dp, tsigkeyname); // FIXME could use some error loging + } + if(rdomains.empty()) { // if we have priority domains, check them first + B->getUnfreshSlaveInfos(&rdomains); + } + DNSSECKeeper dk(B); // NOW HEAR THIS! This DK uses our B backend, so no interleaved access! + { + Lock l(&d_lock); + domains_by_name_t& nameindex=boost::multi_index::get(d_suckdomains); + time_t now = time(0); + + for(DomainInfo& di : rdomains) { + const auto failed = d_failedSlaveRefresh.find(di.zone); + if (failed != d_failedSlaveRefresh.end() && now < failed->second.second ) { + // If the domain has failed before and the time before the next check has not expired, skip this domain + g_log<second.second< localaddr; + SuckRequest sr; + sr.domain=di.zone; + if(di.masters.empty()) // slave domains w/o masters are ignored + continue; + // remove unfresh domains already queued for AXFR, no sense polling them again + sr.master=*di.masters.begin(); + if(nameindex.count(sr)) { // this does NOT however protect us against AXFRs already in progress! + continue; + } + if(d_inprogress.count(sr.domain)) // this does + continue; + + DomainNotificationInfo dni; + dni.di=di; + dni.dnssecOk = dk.doesDNSSEC(); + + if(dk.getTSIGForAccess(di.zone, sr.master, &dni.tsigkeyname)) { + string secret64; + if(!B->getTSIGKey(dni.tsigkeyname, &dni.tsigalgname, &secret64)) { + g_log<getDomainMetadata(di.zone, "AXFR-SOURCE", localaddr) && !localaddr.empty()) { + try { + dni.localaddr = ComboAddress(localaddr[0]); + g_log<1 ? "s" : "")<<" need"<< + (sdomains.size()>1 ? "" : "s")<< + " checking, "<, SlaveSenderReceiver> ifl(sdomains, ssr); + + ifl.d_maxInFlight = 200; + + for(;;) { + try { + ifl.run(); + break; + } + catch(std::exception& e) { + g_log<getDomainInfo(di.zone, tempdi)) { + g_log<getSOA(di.zone, sd); + } + catch(...) {} + + uint32_t theirserial = ssr.d_freshness[di.id].theirSerial, ourserial = sd.serial; + + if(rfc1982LessThan(theirserial, ourserial) && ourserial != 0 && !::arg().mustDo("axfr-lower-serial")) { + g_log< their serial "<< theirserial << endl; + di.backend->setFresh(di.id); + } + else if(hasSOA && theirserial == ourserial) { + uint32_t maxExpire=0, maxInception=0; + if(dk.isPresigned(di.zone)) { + B->lookup(QType(QType::RRSIG), di.zone, nullptr, di.id); // can't use DK before we are done with this lookup! + DNSZoneRecord zr; + while(B->get(zr)) { + auto rrsig = getRR(zr.dr); + if(rrsig->d_type == QType::SOA) { + maxInception = std::max(maxInception, rrsig->d_siginception); + maxExpire = std::max(maxExpire, rrsig->d_sigexpire); + } + } + } + if(! maxInception && ! ssr.d_freshness[di.id].theirInception) { + g_log<setFresh(di.id); + } + else if(maxInception == ssr.d_freshness[di.id].theirInception && maxExpire == ssr.d_freshness[di.id].theirExpire) { + g_log<setFresh(di.id); + } + else if(maxExpire >= now && ! ssr.d_freshness[di.id].theirInception ) { + g_log<setFresh(di.id); + } + else if(maxInception && ! ssr.d_freshness[di.id].theirInception ) { + g_log< +} +#include "dnssecinfra.hh" + +class SodiumED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine +{ +public: + explicit SodiumED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo) + {} + string getName() const override { return "Sodium ED25519"; } + void create(unsigned int bits) override; + storvector_t convertToISCVector() const override; + std::string getPubKeyHash() const override; + std::string sign(const std::string& msg) const override; + bool verify(const std::string& msg, const std::string& signature) const override; + std::string getPublicKeyString() const override; + int getBits() const override; + void fromISCMap(DNSKEYRecordContent& drc, std::map& stormap) override; + void fromPublicKeyString(const std::string& content) override; + void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override + {} + + static std::shared_ptr maker(unsigned int algorithm) + { + return std::make_shared(algorithm); + } + +private: + unsigned char d_pubkey[crypto_sign_ed25519_PUBLICKEYBYTES]; + unsigned char d_seckey[crypto_sign_ed25519_SECRETKEYBYTES]; +}; + +void SodiumED25519DNSCryptoKeyEngine::create(unsigned int bits) +{ + if(bits != crypto_sign_ed25519_SEEDBYTES * 8) { + throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, SodiumED25519 class"); + } + crypto_sign_ed25519_keypair(d_pubkey, d_seckey); +} + +int SodiumED25519DNSCryptoKeyEngine::getBits() const +{ + return crypto_sign_ed25519_SEEDBYTES * 8; +} + +DNSCryptoKeyEngine::storvector_t SodiumED25519DNSCryptoKeyEngine::convertToISCVector() const +{ + /* + Private-key-format: v1.2 + Algorithm: 15 (ED25519) + PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= + */ + + storvector_t storvector; + string algorithm = "15 (ED25519)"; + + storvector.push_back(make_pair("Algorithm", algorithm)); + + vector buffer; + storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, crypto_sign_ed25519_SEEDBYTES))); + return storvector; +} + +void SodiumED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map& stormap ) +{ + /* + Private-key-format: v1.2 + Algorithm: 15 (ED25519) + PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= + */ + + drc.d_algorithm = pdns_stou(stormap["algorithm"]); + string privateKey = stormap["privatekey"]; + + if (privateKey.length() != crypto_sign_ed25519_SEEDBYTES) + throw runtime_error("Seed size mismatch in ISCMap, SodiumED25519 class"); + + std::unique_ptr seed(new unsigned char[crypto_sign_ed25519_SEEDBYTES]); + + memcpy(seed.get(), privateKey.c_str(), crypto_sign_ed25519_SEEDBYTES); + crypto_sign_ed25519_seed_keypair(d_pubkey, d_seckey, seed.get()); +} + +std::string SodiumED25519DNSCryptoKeyEngine::getPubKeyHash() const +{ + return this->getPublicKeyString(); +} + +std::string SodiumED25519DNSCryptoKeyEngine::getPublicKeyString() const +{ + return string((char*)d_pubkey, crypto_sign_ed25519_PUBLICKEYBYTES); +} + +void SodiumED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) +{ + if (input.length() != crypto_sign_ed25519_PUBLICKEYBYTES) + throw runtime_error("Public key size mismatch, SodiumED25519 class"); + + memcpy(d_pubkey, input.c_str(), crypto_sign_ed25519_PUBLICKEYBYTES); +} + +std::string SodiumED25519DNSCryptoKeyEngine::sign(const std::string& msg) const +{ + unsigned long long smlen = msg.length() + crypto_sign_ed25519_BYTES; + std::unique_ptr sm(new unsigned char[smlen]); + + crypto_sign_ed25519(sm.get(), &smlen, (const unsigned char*)msg.c_str(), msg.length(), d_seckey); + + return string((const char*)sm.get(), crypto_sign_ed25519_BYTES); +} + +bool SodiumED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const +{ + if (signature.length() != crypto_sign_ed25519_BYTES) + return false; + + unsigned long long smlen = msg.length() + crypto_sign_ed25519_BYTES; + std::unique_ptr sm(new unsigned char[smlen]); + + memcpy(sm.get(), signature.c_str(), crypto_sign_ed25519_BYTES); + memcpy(sm.get() + crypto_sign_ed25519_BYTES, msg.c_str(), msg.length()); + + std::unique_ptr m(new unsigned char[smlen]); + + return crypto_sign_ed25519_open(m.get(), &smlen, sm.get(), smlen, d_pubkey) == 0; +} + +namespace { +struct LoaderSodiumStruct +{ + LoaderSodiumStruct() + { + DNSCryptoKeyEngine::report(15, &SodiumED25519DNSCryptoKeyEngine::maker); + } +} loadersodium; +} diff --git a/pdns/sortlist.hh b/pdns/sortlist.hh new file mode 100644 index 0000000..cd04329 --- /dev/null +++ b/pdns/sortlist.hh @@ -0,0 +1,48 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once +#include "iputils.hh" +#include "dnsrecords.hh" + +struct SortListOrder +{ + NetmaskTree d_orders; +}; + + +struct SortListOrderCmp +{ + SortListOrderCmp(const SortListOrder& slo) : d_slo(slo) {} + bool operator()(const DNSRecord& a, const DNSRecord& b) const; + const SortListOrder d_slo; +}; + +class SortList { +public: + void clear(); + void addEntry(const Netmask& covers, const Netmask& answermask, int order=-1); + int getMaxOrder(const Netmask& formask) const; + std::unique_ptr getOrderCmp(const ComboAddress& who) const; +private: + + NetmaskTree d_sortlist; +}; diff --git a/pdns/speedtest.cc b/pdns/speedtest.cc new file mode 100644 index 0000000..381c373 --- /dev/null +++ b/pdns/speedtest.cc @@ -0,0 +1,939 @@ +#include "config.h" +#include +#include +#include "dnsparser.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "iputils.hh" +#include + +#ifndef RECURSOR +#include "statbag.hh" +#include "base64.hh" +StatBag S; +#endif + +volatile bool g_ret; // make sure the optimizer does not get too smart +uint64_t g_totalRuns; +volatile bool g_stop; + +void alarmHandler(int) +{ + g_stop=true; +} + +template void doRun(const C& cmd, int mseconds=100) +{ + struct itimerval it; + it.it_value.tv_sec=mseconds/1000; + it.it_value.tv_usec = 1000* (mseconds%1000); + it.it_interval.tv_sec=0; + it.it_interval.tv_usec=0; + + signal(SIGVTALRM, alarmHandler); + setitimer(ITIMER_VIRTUAL, &it, 0); + + unsigned int runs=0; + g_stop=false; + CPUTime dt; + dt.start(); + while(runs++, !g_stop) { + cmd(); + } + double delta=dt.ndiff()/1000000000.0; + boost::format fmt("'%s' %.02f seconds: %.1f runs/s, %.02f usec/run"); + + cerr<< (fmt % cmd.getName() % delta % (runs/delta) % (delta* 1000000.0/runs)) << endl; + g_totalRuns += runs; +} + +struct ARecordTest +{ + explicit ARecordTest(int records) : d_records(records) {} + + string getName() const + { + return (boost::format("%d a records") % d_records).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); + for(int records = 0; records < d_records; records++) { + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::A); + ARecordContent arc("1.2.3.4"); + arc.toPacket(pw); + } + pw.commit(); + } + int d_records; +}; + + +struct MakeStringFromCharStarTest +{ + MakeStringFromCharStarTest() : d_size(0){} + string getName() const + { + return (boost::format("make a std::string")).str(); + } + + void operator()() const + { + string name("outpost.ds9a.nl"); + d_size += name.length(); + + } + mutable int d_size; +}; + + +struct GetTimeTest +{ + string getName() const + { + return "gettimeofday-test"; + } + + void operator()() const + { + struct timeval tv; + gettimeofday(&tv, 0); + } +}; + +pthread_mutex_t s_testlock=PTHREAD_MUTEX_INITIALIZER; + +struct GetLockUncontendedTest +{ + string getName() const + { + return "getlock-uncontended-test"; + } + + void operator()() const + { + pthread_mutex_lock(&s_testlock); + pthread_mutex_unlock(&s_testlock); + } +}; + + +struct StaticMemberTest +{ + string getName() const + { + return "static-member-test"; + } + + void operator()() const + { + static string* s_ptr; + if(!s_ptr) + s_ptr = new string(); + } +}; + +struct StringtokTest +{ + string getName() const + { + return "stringtok"; + } + + void operator()() const + { + string str("the quick brown fox jumped"); + vector parts; + stringtok(parts, str); + } +}; + +struct VStringtokTest +{ + string getName() const + { + return "vstringtok"; + } + + void operator()() const + { + string str("the quick brown fox jumped"); + vector > parts; + vstringtok(parts, str); + } +}; + +struct StringAppendTest +{ + string getName() const + { + return "stringappend"; + } + + void operator()() const + { + string str; + static char i; + for(int n=0; n < 1000; ++n) + str.append(1, i); + i++; + } +}; + + +struct BoostStringAppendTest +{ + string getName() const + { + return "booststringappend"; + } + + void operator()() const + { + boost::container::string str; + static char i; + for(int n=0; n < 1000; ++n) + str.append(1, i); + i++; + } +}; + + + +struct MakeARecordTest +{ + string getName() const + { + return (boost::format("make a-record")).str(); + } + + void operator()() const + { + static string src("1.2.3.4"); + ARecordContent arc(src); + //ARecordContent arc(0x01020304); + + } +}; + +vector makeBigReferral() +{ + + vector packet; + DNSPacketWriter pw(packet, DNSName("www.google.com"), QType::A); + + string gtld="x.gtld-servers.net"; + for(char c='a'; c<= 'm';++c) { + pw.startRecord(DNSName("com"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY); + gtld[0]=c; + auto drc = DNSRecordContent::mastermake(QType::NS, 1, gtld); + drc->toPacket(pw); + } + + for(char c='a'; c<= 'k';++c) { + gtld[0]=c; + pw.startRecord(DNSName(gtld), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL); + auto drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4"); + drc->toPacket(pw); + } + + + pw.startRecord(DNSName("a.gtld-servers.net"), QType::AAAA, 3600, 1, DNSResourceRecord::ADDITIONAL); + auto aaaarc = DNSRecordContent::mastermake(QType::AAAA, 1, "2001:503:a83e::2:30"); + aaaarc->toPacket(pw); + + pw.startRecord(DNSName("b.gtld-servers.net"), QType::AAAA, 3600, 1, DNSResourceRecord::ADDITIONAL); + aaaarc = DNSRecordContent::mastermake(QType::AAAA, 1, "2001:503:231d::2:30"); + aaaarc->toPacket(pw); + + + pw.commit(); + return packet; +} + +vector makeBigDNSPacketReferral() +{ + vector records; + DNSResourceRecord rr; + rr.qtype = QType::NS; + rr.ttl=3600; + rr.qname=DNSName("com"); + + string gtld="x.gtld-servers.net"; + for(char c='a'; c<= 'm';++c) { + gtld[0]=c; + rr.content = gtld; + records.push_back(rr); + } + + rr.qtype = QType::A; + for(char c='a'; c<= 'k';++c) { + gtld[0]=c; + rr.qname=DNSName(gtld); + rr.content="1.2.3.4"; + records.push_back(rr); + } + + rr.qname=DNSName("a.gtld-servers.net"); + rr.qtype=QType::AAAA; + rr.content="2001:503:a83e::2:30"; + records.push_back(rr); + + rr.qname=DNSName("b.gtld-servers.net"); + rr.qtype=QType::AAAA; + rr.content="2001:503:231d::2:30"; + records.push_back(rr); + + + vector packet; + DNSPacketWriter pw(packet, DNSName("www.google.com"), QType::A); + // shuffle(records); + for(const auto& rec : records) { + pw.startRecord(rec.qname, rec.qtype.getCode(), rec.ttl, 1, DNSResourceRecord::ADDITIONAL); + auto drc = DNSRecordContent::mastermake(rec.qtype.getCode(), 1, rec.content); + drc->toPacket(pw); + } + + pw.commit(); + return packet; +} + + + +struct MakeARecordTestMM +{ + string getName() const + { + return (boost::format("make a-record (mm)")).str(); + } + + void operator()() const + { + auto drc = DNSRecordContent::mastermake(QType::A, 1, + "1.2.3.4"); + } +}; + + +struct A2RecordTest +{ + explicit A2RecordTest(int records) : d_records(records) {} + + string getName() const + { + return (boost::format("%d a records") % d_records).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); + ARecordContent arc("1.2.3.4"); + DNSName name("outpost.ds9a.nl"); + for(int records = 0; records < d_records; records++) { + pw.startRecord(name, QType::A); + + arc.toPacket(pw); + } + pw.commit(); + } + int d_records; +}; + + +struct TXTRecordTest +{ + explicit TXTRecordTest(int records) : d_records(records) {} + + string getName() const + { + return (boost::format("%d TXT records") % d_records).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::TXT); + for(int records = 0; records < d_records; records++) { + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::TXT); + TXTRecordContent arc("\"een leuk verhaaltje in een TXT\""); + arc.toPacket(pw); + } + pw.commit(); + } + int d_records; +}; + + +struct GenericRecordTest +{ + explicit GenericRecordTest(int records, uint16_t type, const std::string& content) + : d_records(records), d_type(type), d_content(content) {} + + string getName() const + { + return (boost::format("%d %s records") % d_records % + DNSRecordContent::NumberToType(d_type)).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), d_type); + for(int records = 0; records < d_records; records++) { + pw.startRecord(DNSName("outpost.ds9a.nl"), d_type); + auto drc = DNSRecordContent::mastermake(d_type, 1, + d_content); + drc->toPacket(pw); + } + pw.commit(); + } + int d_records; + uint16_t d_type; + string d_content; +}; + + +struct AAAARecordTest +{ + explicit AAAARecordTest(int records) : d_records(records) {} + + string getName() const + { + return (boost::format("%d aaaa records (mm)") % d_records).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::AAAA); + for(int records = 0; records < d_records; records++) { + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::AAAA); + auto drc = DNSRecordContent::mastermake(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441"); + drc->toPacket(pw); + } + pw.commit(); + } + int d_records; +}; + +struct SOARecordTest +{ + explicit SOARecordTest(int records) : d_records(records) {} + + string getName() const + { + return (boost::format("%d soa records (mm)") % d_records).str(); + } + + void operator()() const + { + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA); + + for(int records = 0; records < d_records; records++) { + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::SOA); + auto drc = DNSRecordContent::mastermake(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400"); + drc->toPacket(pw); + } + pw.commit(); + } + int d_records; +}; + +vector makeEmptyQuery() +{ + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA); + return packet; +} + +vector makeTypicalReferral() +{ + vector packet; + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); + + pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY); + auto drc = DNSRecordContent::mastermake(QType::NS, 1, "ns1.ds9a.nl"); + drc->toPacket(pw); + + pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY); + drc = DNSRecordContent::mastermake(QType::NS, 1, "ns2.ds9a.nl"); + drc->toPacket(pw); + + + pw.startRecord(DNSName("ns1.ds9a.nl"), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL); + drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4"); + drc->toPacket(pw); + + pw.startRecord(DNSName("ns2.ds9a.nl"), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL); + drc = DNSRecordContent::mastermake(QType::A, 1, "4.3.2.1"); + drc->toPacket(pw); + + pw.commit(); + return packet; +} + +struct StackMallocTest +{ + string getName() const + { + return "stack allocation"; + } + + void operator()() const + { + char *buffer= new char[200000]; + delete[] buffer; + } + +}; + + +struct EmptyQueryTest +{ + string getName() const + { + return "write empty query"; + } + + void operator()() const + { + vector packet=makeEmptyQuery(); + } + +}; + +struct TypicalRefTest +{ + string getName() const + { + return "write typical referral"; + } + + void operator()() const + { + vector packet=makeTypicalReferral(); + } + +}; + +struct BigRefTest +{ + string getName() const + { + return "write big referral"; + } + + void operator()() const + { + vector packet=makeBigReferral(); + } + +}; + +struct BigDNSPacketRefTest +{ + string getName() const + { + return "write big dnspacket referral"; + } + + void operator()() const + { + vector packet=makeBigDNSPacketReferral(); + } + +}; + + +struct TCacheComp +{ + bool operator()(const pair& a, const pair& b) const + { + if(a.first < b.first) + return true; + if(b.first < a.first) + return false; + + return a.second < b.second; + } +}; + +struct NegCacheEntry +{ + DNSName d_name; + QType d_qtype; + DNSName d_qname; + uint32_t d_ttd; +}; + +struct timeval d_now; + + + +struct ParsePacketTest +{ + explicit ParsePacketTest(const vector& packet, const std::string& name) + : d_packet(packet), d_name(name) + {} + + string getName() const + { + return "parse '"+d_name+"'"; + } + + void operator()() const + { + MOADNSParser mdp(false, (const char*)&*d_packet.begin(), d_packet.size()); + typedef map, set, TCacheComp > tcache_t; + tcache_t tcache; + + struct { + vector d_result; + bool d_aabit; + int d_rcode; + } lwr; + DNSResourceRecord rr; + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + DNSResourceRecord rr; + rr.qtype=i->first.d_type; + rr.qname=i->first.d_name; + + rr.ttl=i->first.d_ttl; + rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form + lwr.d_result.push_back(rr); + } + + + } + const vector& d_packet; + std::string d_name; +}; + +struct ParsePacketBareTest +{ + explicit ParsePacketBareTest(const vector& packet, const std::string& name) + : d_packet(packet), d_name(name) + {} + + string getName() const + { + return "parse '"+d_name+"' bare"; + } + + void operator()() const + { + MOADNSParser mdp(false, (const char*)&*d_packet.begin(), d_packet.size()); + } + const vector& d_packet; + std::string d_name; +}; + + +struct SimpleCompressTest +{ + explicit SimpleCompressTest(const std::string& name) + : d_name(name) + {} + + string getName() const + { + return "compress '"+d_name+"'"; + } + + void operator()() const + { + simpleCompress(d_name); + } + std::string d_name; +}; + +struct VectorExpandTest +{ + string getName() const + { + return "vector expand"; + } + + void operator()() const + { + vector d_record; + d_record.resize(12); + + string out="\x03www\x04ds9a\x02nl"; + string::size_type len = d_record.size(); + d_record.resize(len + out.length()); + memcpy(&d_record[len], out.c_str(), out.length()); + } + +}; + +struct DNSNameParseTest +{ + string getName() const + { + return "DNSName parse"; + } + + void operator()() const + { + DNSName name("www.powerdns.com"); + } + +}; + +struct DNSNameRootTest +{ + string getName() const + { + return "DNSName root"; + } + + void operator()() const + { + DNSName name("."); + } + +}; + + + +struct IEqualsTest +{ + string getName() const + { + return "iequals test"; + } + + void operator()() const + { + static string a("www.ds9a.nl"), b("www.lwn.net"); + g_ret = boost::iequals(a, b); + } + +}; + +struct MyIEqualsTest +{ + string getName() const + { + return "pdns_iequals test"; + } + + void operator()() const + { + static string a("www.ds9a.nl"), b("www.lwn.net"); + g_ret = pdns_iequals(a, b); + } + +}; + + +struct StrcasecmpTest +{ + string getName() const + { + return "strcasecmp test"; + } + + void operator()() const + { + static string a("www.ds9a.nl"), b("www.lwn.net"); + g_ret = strcasecmp(a.c_str(), b.c_str()); + } +}; + + +struct Base64EncodeTest +{ + string getName() const + { + return "Bas64Encode test"; + } + + void operator()() const + { + static string a("dq4KydZjmcoQQ45VYBP2EDR8FqKaMul0eSHBt7Xx5F7A4HFtabXEzDLD01bnSiGK"); + Base64Encode(a); + } +}; + + +struct B64DecodeTest +{ + string getName() const + { + return "B64Decode test"; + } + + void operator()() const + { + static string a("ZHE0S3lkWmptY29RUTQ1VllCUDJFRFI4RnFLYU11bDBlU0hCdDdYeDVGN0E0SEZ0YWJYRXpETEQwMWJuU2lHSw=="), b; + g_ret = B64Decode(a,b); + } +}; + + +struct NOPTest +{ + string getName() const + { + return "null test"; + } + + void operator()() const + { + } + +}; + +struct StatRingDNSNameQTypeToStringTest +{ + explicit StatRingDNSNameQTypeToStringTest(const DNSName &name, const QType type) : d_name(name), d_type(type) {} + + string getName() const { return "StatRing test with DNSName and QType to string"; } + + void operator()() const { + S.ringAccount("testring", d_name.toLogString()+"/"+d_type.getName()); + }; + + DNSName d_name; + QType d_type; +}; + +struct StatRingDNSNameQTypeTest +{ + explicit StatRingDNSNameQTypeTest(const DNSName &name, const QType type) : d_name(name), d_type(type) {} + + string getName() const { return "StatRing test with DNSName and QType"; } + + void operator()() const { + S.ringAccount("testringdnsname", d_name, d_type); + }; + + DNSName d_name; + QType d_type; +}; + + +struct NetmaskTreeTest +{ + string getName() const { return "NetmaskTreeTest"; } + + void operator()() const { + Netmask nm("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/64"); + NetmaskTree tree; + + for (int i = 0; i < 100; i++) + tree.insert_or_assign(nm, true); + } +}; + +int main(int argc, char** argv) +try +{ + reportAllTypes(); + + doRun(NOPTest()); + + doRun(IEqualsTest()); + doRun(MyIEqualsTest()); + doRun(StrcasecmpTest()); + doRun(Base64EncodeTest()); + doRun(B64DecodeTest()); + + doRun(StackMallocTest()); + + doRun(EmptyQueryTest()); + doRun(TypicalRefTest()); + doRun(BigRefTest()); + doRun(BigDNSPacketRefTest()); + + auto packet = makeEmptyQuery(); + doRun(ParsePacketTest(packet, "empty-query")); + + packet = makeTypicalReferral(); + cerr<<"typical referral size: "< + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * Additionally, the license of this program contains a special + * exception which allows to distribute the program in binary form when + * it is linked against OpenSSL. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "ssqlite3.hh" +#include +#include +#include "pdns/logger.hh" +#include "misc.hh" +#include "utility.hh" +#include + +/* +** Set all the parameters in the compiled SQL statement to NULL. +* +* copied from sqlite 3.3.6 // cmouse +*/ +int pdns_sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + return rc; +} + +static string SSQLite3ErrorString(sqlite3 *db) +{ + return string(sqlite3_errmsg(db)+string(" (")+std::to_string(sqlite3_extended_errcode(db))+string(")")); +} + +class SSQLite3Statement: public SSqlStatement +{ +public: + SSQLite3Statement(SSQLite3 *db, bool dolog, const string& query) : + d_query(query), + d_db(db), + d_dolog(dolog) + { + } + + int name2idx(const string& name) { + string zName = string(":")+name; + prepareStatement(); + return sqlite3_bind_parameter_index(d_stmt, zName.c_str()); + // XXX: support @ and $? + } + + SSqlStatement* bind(const string& name, bool value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int(d_stmt, idx, value ? 1 : 0); }; return this; } + SSqlStatement* bind(const string& name, int value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int(d_stmt, idx, value); }; return this; } + SSqlStatement* bind(const string& name, uint32_t value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int64(d_stmt, idx, value); }; return this; } + SSqlStatement* bind(const string& name, long value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int64(d_stmt, idx, value); }; return this; } + SSqlStatement* bind(const string& name, unsigned long value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int64(d_stmt, idx, value); }; return this; } + SSqlStatement* bind(const string& name, long long value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int64(d_stmt, idx, value); }; return this; }; + SSqlStatement* bind(const string& name, unsigned long long value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_int64(d_stmt, idx, value); }; return this; } + SSqlStatement* bind(const string& name, const std::string& value) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_text(d_stmt, idx, value.c_str(), value.size(), SQLITE_TRANSIENT); }; return this; } + SSqlStatement* bindNull(const string& name) { int idx = name2idx(name); if (idx>0) { sqlite3_bind_null(d_stmt, idx); }; return this; } + + SSqlStatement* execute() { + prepareStatement(); + if (d_dolog) { + g_log<inTransaction(); // try only once + while(attempts < 2 && (d_rc = sqlite3_step(d_stmt)) == SQLITE_BUSY) attempts++; + + if (d_rc != SQLITE_ROW && d_rc != SQLITE_DONE) { + // failed. + releaseStatement(); + if (d_rc == SQLITE_CANTOPEN) + throw SSqlException(string("CANTOPEN error in sqlite3, often caused by unwritable sqlite3 db *directory*: ")+SSQLite3ErrorString(d_db->db())); + throw SSqlException(string("Error while retrieving SQLite query results: ")+SSQLite3ErrorString(d_db->db())); + } + if(d_dolog) + g_log<= 3003009 + sqlite3_clear_bindings(d_stmt); +#else + pdns_sqlite3_clear_bindings(d_stmt); +#endif + return this; + } + + ~SSQLite3Statement() { + // deallocate if necessary + releaseStatement(); + } + + const string& getQuery() { return d_query; }; +private: + string d_query; + DTime d_dtime; + sqlite3_stmt* d_stmt{nullptr}; + SSQLite3* d_db{nullptr}; + int d_rc{0}; + bool d_dolog; + bool d_prepared{false}; + + void prepareStatement() { + const char *pTail; + + if (d_prepared) return; +#if SQLITE_VERSION_NUMBER >= 3003009 + if (sqlite3_prepare_v2(d_db->db(), d_query.c_str(), -1, &d_stmt, &pTail ) != SQLITE_OK) +#else + if (sqlite3_prepare(d_db->db(), d_query.c_str(), -1, &d_stmt, &pTail ) != SQLITE_OK) +#endif + { + releaseStatement(); + throw SSqlException(string("Unable to compile SQLite statement : '")+d_query+"': "+SSQLite3ErrorString(d_db->db())); + } + if (pTail && strlen(pTail)>0) + g_log< SSQLite3::prepare(const string& query, int nparams __attribute__((unused))) { + return std::unique_ptr(new SSQLite3Statement(this, m_dolog, query)); +} + +void SSQLite3::execute(const string& query) { + char *errmsg; + int rc; + if (sqlite3_exec(m_pDB, query.c_str(), NULL, NULL, &errmsg) == SQLITE_BUSY) { + if (m_in_transaction) { + std::string errstr(errmsg); + sqlite3_free(errmsg); + throw("Failed to execute query: " + errstr); + } else { + if ((rc = sqlite3_exec(m_pDB, query.c_str(), NULL, NULL, &errmsg) != SQLITE_OK) && rc != SQLITE_DONE && rc != SQLITE_ROW) { + std::string errstr(errmsg); + sqlite3_free(errmsg); + throw("Failed to execute query: " + errstr); + } + } + } +} + +int SSQLite3::busyHandler(void*, int) +{ + Utility::usleep(1000); + return 1; +} + +void SSQLite3::startTransaction() { + execute("begin"); + m_in_transaction = true; +} + +void SSQLite3::rollback() { + execute("rollback"); + m_in_transaction = false; +} + +void SSQLite3::commit() { + execute("commit"); + m_in_transaction = false; +} + +// Constructs a SSqlException object. +SSqlException SSQLite3::sPerrorException( const std::string & reason ) +{ + return SSqlException( reason ); +} diff --git a/pdns/ssqlite3.hh b/pdns/ssqlite3.hh new file mode 100644 index 0000000..5768337 --- /dev/null +++ b/pdns/ssqlite3.hh @@ -0,0 +1,62 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef SSQLITE3_HH +#define SSQLITE3_HH + +#include +#include "pdns/backends/gsql/ssql.hh" + +class SSQLite3 : public SSql +{ +private: + //! Pointer to the SQLite database instance. + sqlite3 *m_pDB{nullptr}; + + bool m_dolog; + bool m_in_transaction; + static int busyHandler(void*, int); +protected: +public: + //! Constructor. + SSQLite3( const std::string & database, const std::string & journalmode, bool creat=false); + + //! Destructor. + ~SSQLite3(); + + std::unique_ptr prepare(const string& query, int nparams) override; + void execute(const string& query) override; + void setLog(bool state) override; + + void startTransaction() override; + void commit() override; + void rollback() override; + + sqlite3 *db() { return this->m_pDB; }; + + bool inTransaction() { return m_in_transaction; }; + + //! Used to create an backend specific exception message. + SSqlException sPerrorException( const std::string & reason ) override; +}; + +#endif // SSQLITE3_HH + diff --git a/pdns/sstuff.hh b/pdns/sstuff.hh new file mode 100644 index 0000000..922315a --- /dev/null +++ b/pdns/sstuff.hh @@ -0,0 +1,365 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef SSTUFF_HH +#define SSTUFF_HH + +#include +#include +#include +#include "iputils.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "namespaces.hh" +#include "namespaces.hh" + + +typedef int ProtocolType; //!< Supported protocol types + +//! Representation of a Socket and many of the Berkeley functions available +class Socket : public boost::noncopyable +{ + Socket(int fd): d_socket(fd) + { + } + +public: + //! Construct a socket of specified address family and socket type. + Socket(int af, int st, ProtocolType pt=0) + { + if((d_socket=socket(af, st, pt))<0) + throw NetworkError(strerror(errno)); + setCloseOnExec(d_socket); + } + + Socket(Socket&& rhs): d_buffer(std::move(rhs.d_buffer)), d_socket(rhs.d_socket) + { + rhs.d_socket = -1; + } + + ~Socket() + { + try { + if (d_socket != -1) { + closesocket(d_socket); + } + } + catch(const PDNSException& e) { + } + } + + //! If the socket is capable of doing so, this function will wait for a connection + std::unique_ptr accept() + { + struct sockaddr_in remote; + socklen_t remlen=sizeof(remote); + memset(&remote, 0, sizeof(remote)); + int s=::accept(d_socket, reinterpret_cast(&remote), &remlen); + if(s<0) { + if(errno==EAGAIN) + return nullptr; + + throw NetworkError("Accepting a connection: "+string(strerror(errno))); + } + + return std::unique_ptr(new Socket(s)); + } + + //! Get remote address + bool getRemote(ComboAddress &remote) { + socklen_t remotelen=sizeof(remote); + return (getpeername(d_socket, reinterpret_cast(&remote), &remotelen) >= 0); + } + + //! Check remote address against netmaskgroup ng + bool acl(const NetmaskGroup &ng) + { + ComboAddress remote; + if (getRemote(remote)) + return ng.match(remote); + + return false; + } + + //! Set the socket to non-blocking + void setNonBlocking() + { + ::setNonBlocking(d_socket); + } + + //! Set the socket to blocking + void setBlocking() + { + ::setBlocking(d_socket); + } + + void setReuseAddr() + { + try { + ::setReuseAddr(d_socket); + } catch (const PDNSException &e) { + throw NetworkError(e.reason); + } + } + + //! Bind the socket to a specified endpoint + void bind(const ComboAddress &local, bool reuseaddr=true) + { + int tmp=1; + if(reuseaddr && setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&tmp), sizeof tmp)<0) + throw NetworkError(string("Setsockopt failed: ")+strerror(errno)); + + if(::bind(d_socket, reinterpret_cast(&local), local.getSocklen())<0) + throw NetworkError("While binding: "+string(strerror(errno))); + } + + //! Connect the socket to a specified endpoint + void connect(const ComboAddress &ep, int timeout=0) + { + SConnectWithTimeout(d_socket, ep, timeout); + } + + + //! For datagram sockets, receive a datagram and learn where it came from + /** For datagram sockets, receive a datagram and learn where it came from + \param dgram Will be filled with the datagram + \param ep Will be filled with the origin of the datagram */ + void recvFrom(string &dgram, ComboAddress &ep) + { + socklen_t remlen = sizeof(ep); + ssize_t bytes; + d_buffer.resize(s_buflen); + if((bytes=recvfrom(d_socket, &d_buffer[0], s_buflen, 0, reinterpret_cast(&ep) , &remlen)) <0) + throw NetworkError("After recvfrom: "+string(strerror(errno))); + + dgram.assign(d_buffer, 0, static_cast(bytes)); + } + + bool recvFromAsync(string &dgram, ComboAddress &ep) + { + struct sockaddr_in remote; + socklen_t remlen = sizeof(remote); + ssize_t bytes; + d_buffer.resize(s_buflen); + if((bytes=recvfrom(d_socket, &d_buffer[0], s_buflen, 0, reinterpret_cast(&remote), &remlen))<0) { + if(errno!=EAGAIN) { + throw NetworkError("After async recvfrom: "+string(strerror(errno))); + } + else { + return false; + } + } + dgram.assign(d_buffer, 0, static_cast(bytes)); + return true; + } + + + //! For datagram sockets, send a datagram to a destination + void sendTo(const char* msg, size_t len, const ComboAddress &ep) + { + if(sendto(d_socket, msg, len, 0, reinterpret_cast(&ep), ep.getSocklen())<0) + throw NetworkError("After sendto: "+string(strerror(errno))); + } + + //! For connected datagram sockets, send a datagram + void send(const std::string& msg) + { + if(::send(d_socket, msg.c_str(), msg.size(), 0)<0) + throw NetworkError("After send: "+string(strerror(errno))); + } + + + /** For datagram sockets, send a datagram to a destination + \param dgram The datagram + \param ep The intended destination of the datagram */ + void sendTo(const string &dgram, const ComboAddress &ep) + { + sendTo(dgram.c_str(), dgram.length(), ep); + } + + + //! Write this data to the socket, taking care that all bytes are written out + void writen(const string &data) + { + if(data.empty()) + return; + + size_t toWrite=data.length(); + ssize_t res; + const char *ptr=data.c_str(); + + do { + res=::send(d_socket, ptr, toWrite, 0); + if(res<0) + throw NetworkError("Writing to a socket: "+string(strerror(errno))); + if(!res) + throw NetworkError("EOF on socket"); + toWrite -= static_cast(res); + ptr += static_cast(res); + } while(toWrite); + + } + + //! tries to write toWrite bytes from ptr to the socket + /** tries to write toWrite bytes from ptr to the socket, but does not make sure they al get written out + \param ptr Location to write from + \param toWrite number of bytes to try + */ + size_t tryWrite(const char *ptr, size_t toWrite) + { + ssize_t res; + res=::send(d_socket,ptr,toWrite,0); + if(res==0) + throw NetworkError("EOF on writing to a socket"); + + if(res>0) + return res; + + if(errno==EAGAIN) + return 0; + + throw NetworkError("Writing to a socket: "+string(strerror(errno))); + } + + //! Writes toWrite bytes from ptr to the socket + /** Writes toWrite bytes from ptr to the socket. Returns how many bytes were written */ + size_t write(const char *ptr, size_t toWrite) + { + ssize_t res; + res=::send(d_socket,ptr,toWrite,0); + if(res<0) { + throw NetworkError("Writing to a socket: "+string(strerror(errno))); + } + return res; + } + + void writenWithTimeout(const void *buffer, size_t n, int timeout) + { + size_t bytes=n; + const char *ptr = reinterpret_cast(buffer); + ssize_t ret; + while(bytes) { + ret=::write(d_socket, ptr, bytes); + if(ret < 0) { + if(errno==EAGAIN) { + ret=waitForRWData(d_socket, false, timeout, 0); + if(ret < 0) + throw NetworkError("Waiting for data write"); + if(!ret) + throw NetworkError("Timeout writing data"); + continue; + } + else + throw NetworkError("Writing data: "+stringerror()); + } + if(!ret) { + throw NetworkError("Did not fulfill TCP write due to EOF"); + } + + ptr += static_cast(ret); + bytes -= static_cast(ret); + } + } + + //! reads one character from the socket + int getChar() + { + char c; + + ssize_t res=::recv(d_socket,&c,1,0); + if(res) + return c; + return -1; + } + + void getline(string &data) + { + data=""; + int c; + while((c=getChar())!=-1) { + data+=(char)c; + if(c=='\n') + break; + } + } + + //! Reads a block of data from the socket to a string + void read(string &data) + { + d_buffer.resize(s_buflen); + ssize_t res=::recv(d_socket, &d_buffer[0], s_buflen, 0); + if(res<0) + throw NetworkError("Reading from a socket: "+string(strerror(errno))); + data.assign(d_buffer, 0, static_cast(res)); + } + + //! Reads a block of data from the socket to a block of memory + size_t read(char *buffer, size_t bytes) + { + ssize_t res=::recv(d_socket, buffer, bytes, 0); + if(res<0) + throw NetworkError("Reading from a socket: "+string(strerror(errno))); + return static_cast(res); + } + + ssize_t readWithTimeout(char* buffer, size_t n, int timeout) + { + int err = waitForRWData(d_socket, true, timeout, 0); + + if(err == 0) + throw NetworkError("timeout reading"); + if(err < 0) + throw NetworkError("nonblocking read failed: "+string(strerror(errno))); + + return read(buffer, n); + } + + //! Sets the socket to listen with a default listen backlog of 10 pending connections + void listen(unsigned int length=10) + { + if(::listen(d_socket,length)<0) + throw NetworkError("Setting socket to listen: "+string(strerror(errno))); + } + + //! Returns the internal file descriptor of the socket + int getHandle() const + { + return d_socket; + } + +private: + static const size_t s_buflen{4096}; + std::string d_buffer; + int d_socket; +}; + + +#endif diff --git a/pdns/statbag.cc b/pdns/statbag.cc new file mode 100644 index 0000000..83af32c --- /dev/null +++ b/pdns/statbag.cc @@ -0,0 +1,342 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include "statbag.hh" +#include "pdnsexception.hh" +#include +#include +#include +#include "arguments.hh" +#include "lock.hh" +#include "iputils.hh" + + +#include "namespaces.hh" + +StatBag::StatBag() +{ + d_doRings=false; +} + +void StatBag::exists(const string &key) +{ + if(!d_keyDescrips.count(key)) + { + throw PDNSException("Trying to deposit into unknown StatBag key '"+key+"'"); + } +} + +string StatBag::directory() +{ + string dir; + ostringstream o; + + for(const auto& i: d_stats) { + if (d_blacklist.find(i.first) != d_blacklist.end()) + continue; + o<StatBag::getEntries() +{ + vector ret; + + for(const auto& i: d_stats) { + if (d_blacklist.find(i.first) != d_blacklist.end()) + continue; + ret.push_back(i.first); + } + + for(const funcstats_t::value_type& val : d_funcstats) { + if (d_blacklist.find(val.first) != d_blacklist.end()) + continue; + ret.push_back(val.first); + } + + + return ret; + +} + +string StatBag::getDescrip(const string &item) +{ + exists(item); + return d_keyDescrips[item]; +} + +void StatBag::declare(const string &key, const string &descrip) +{ + AtomicCounter *i=new AtomicCounter(0); + d_stats[key]=i; + d_keyDescrips[key]=descrip; +} + +void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func) +{ + + d_funcstats[key]=func; + d_keyDescrips[key]=descrip; +} + + +void StatBag::set(const string &key, unsigned long value) +{ + exists(key); + d_stats[key]->store(value); +} + +unsigned long StatBag::read(const string &key) +{ + exists(key); + funcstats_t::const_iterator iter = d_funcstats.find(key); + if(iter != d_funcstats.end()) + return iter->second(iter->first); + return *d_stats[key]; +} + +unsigned long StatBag::readZero(const string &key) +{ + exists(key); + unsigned long tmp=*d_stats[key]; + d_stats[key]=0; + return tmp; +} + + +string StatBag::getValueStr(const string &key) +{ + ostringstream o; + o< +StatRing::StatRing(unsigned int size) +{ + d_items.set_capacity(size); + pthread_mutex_init(&d_lock, 0); +} + +template +void StatRing::account(const T& t) +{ + Lock l(&d_lock); + d_items.push_back(t); +} + +template +unsigned int StatRing::getSize() +{ + Lock l(&d_lock); + return d_items.capacity(); +} + +template +void StatRing::resize(unsigned int newsize) +{ + Lock l(&d_lock); + d_items.set_capacity(newsize); +} + + +template +void StatRing::setHelp(const string &str) +{ + d_help=str; +} + +template +string StatRing::getHelp() +{ + return d_help; +} + + +template +vector >StatRing::get() const +{ + Lock l(&d_lock); + map res; + for(typename boost::circular_buffer::const_iterator i=d_items.begin();i!=d_items.end();++i) { + res[*i]++; + } + + vector > tmp; + for(typename map::const_iterator i=res.begin();i!=res.end();++i) + tmp.push_back(*i); + + sort(tmp.begin(),tmp.end(),popisort); + + return tmp; +} + +void StatBag::declareRing(const string &name, const string &help, unsigned int size) +{ + d_rings[name]=StatRing(size); + d_rings[name].setHelp(help); +} + +void StatBag::declareComboRing(const string &name, const string &help, unsigned int size) +{ + d_comborings[name]=StatRing(size); + d_comborings[name].setHelp(help); +} + +void StatBag::declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size) +{ + d_dnsnameqtyperings[name] = StatRing >(size); + d_dnsnameqtyperings[name].setHelp(help); +} + + +vector > StatBag::getRing(const string &name) +{ + if(d_rings.count(name)) { + return d_rings[name].get(); + } + vector > ret; + + if (d_comborings.count(name)) { + typedef pair stor_t; + vector raw =d_comborings[name].get(); + for(const stor_t& stor : raw) { + ret.push_back(make_pair(stor.first.ca.toString(), stor.second)); + } + } else if(d_dnsnameqtyperings.count(name)) { + auto raw = d_dnsnameqtyperings[name].get(); + for (auto const &e : raw) { + ret.push_back(make_pair(std::get<0>(e.first).toLogString() + "/" + std::get<1>(e.first).getName(), e.second)); + } + } + return ret; +} + +template +void StatRing::reset() +{ + Lock l(&d_lock); + d_items.clear(); +} + +void StatBag::resetRing(const string &name) +{ + if(d_rings.count(name)) + d_rings[name].reset(); + if(d_comborings.count(name)) + d_comborings[name].reset(); + if(d_dnsnameqtyperings.count(name)) + d_dnsnameqtyperings[name].reset(); +} + +void StatBag::resizeRing(const string &name, unsigned int newsize) +{ + if(d_rings.count(name)) + d_rings[name].resize(newsize); + if(d_comborings.count(name)) + d_comborings[name].resize(newsize); + if(d_dnsnameqtyperings.count(name)) + return d_dnsnameqtyperings[name].resize(newsize); +} + + +unsigned int StatBag::getRingSize(const string &name) +{ + if(d_rings.count(name)) + return d_rings[name].getSize(); + if(d_comborings.count(name)) + return d_comborings[name].getSize(); + if(d_dnsnameqtyperings.count(name)) + return d_dnsnameqtyperings[name].getSize(); + return 0; +} + +string StatBag::getRingTitle(const string &name) +{ + if(d_rings.count(name)) + return d_rings[name].getHelp(); + if(d_comborings.count(name)) + return d_comborings[name].getHelp(); + if(d_dnsnameqtyperings.count(name)) + return d_dnsnameqtyperings[name].getHelp(); + return ""; +} + +vectorStatBag::listRings() +{ + vector ret; + for(auto i=d_rings.begin();i!=d_rings.end();++i) + ret.push_back(i->first); + for(auto i=d_comborings.begin();i!=d_comborings.end();++i) + ret.push_back(i->first); + for(const auto &i : d_dnsnameqtyperings) + ret.push_back(i.first); + + return ret; +} + +bool StatBag::ringExists(const string &name) +{ + return d_rings.count(name) || d_comborings.count(name) || d_dnsnameqtyperings.count(name); +} + +void StatBag::blacklist(const string& str) { + d_blacklist.insert(str); +} + +template class StatRing; +template class StatRing; +template class StatRing >; diff --git a/pdns/statbag.hh b/pdns/statbag.hh new file mode 100644 index 0000000..a983969 --- /dev/null +++ b/pdns/statbag.hh @@ -0,0 +1,152 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef STATBAG_HH +#define STATBAG_HH +#include +#include +#include +#include +#include +#include "lock.hh" +#include "namespaces.hh" +#include "iputils.hh" +#include "circular_buffer.hh" + + + +template > +class StatRing +{ +public: + StatRing(unsigned int size=10000); + void account(const T &item); + + unsigned int getSize(); + void resize(unsigned int newsize); + void reset(); + void setHelp(const string &str); + string getHelp(); + + vector > get() const; +private: + static bool popisort(const pair &a, const pair &b) + { + return (a.second > b.second); + } + + boost::circular_buffer d_items; + mutable pthread_mutex_t d_lock; + string d_help; +}; + + +//! use this to gather and query statistics +class StatBag +{ + map d_stats; + map d_keyDescrips; + map >d_rings; + map >d_comborings; + map > >d_dnsnameqtyperings; + typedef boost::function func_t; + typedef map funcstats_t; + funcstats_t d_funcstats; + bool d_doRings; + std::set d_blacklist; + +public: + StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful + ~StatBag(); + void declare(const string &key, const string &descrip=""); //!< Before you can store or access a key, you need to declare it + void declare(const string &key, const string &descrip, func_t func); //!< Before you can store or access a key, you need to declare it + + void declareRing(const string &name, const string &title, unsigned int size=10000); + void declareComboRing(const string &name, const string &help, unsigned int size=10000); + void declareDNSNameQTypeRing(const string &name, const string &help, unsigned int size=10000); + vector >getRing(const string &name); + string getRingTitle(const string &name); + void ringAccount(const char* name, const string &item) + { + if(d_doRings) { + if(!d_rings.count(name)) + throw runtime_error("Attempting to account to non-existent ring '"+std::string(name)+"'"); + + d_rings[name].account(item); + } + } + void ringAccount(const char* name, const ComboAddress &item) + { + if(d_doRings) { + if(!d_comborings.count(name)) + throw runtime_error("Attempting to account to non-existent comboring '"+std::string(name)+"'"); + d_comborings[name].account(item); + } + } + void ringAccount(const char* name, const DNSName &dnsname, const QType &qtype) + { + if(d_doRings) { + if(!d_dnsnameqtyperings.count(name)) + throw runtime_error("Attempting to account to non-existent dnsname+qtype ring '"+std::string(name)+"'"); + d_dnsnameqtyperings[name].account(std::make_tuple(dnsname, qtype)); + } + } + + void doRings() + { + d_doRings=true; + } + + vectorlistRings(); + bool ringExists(const string &name); + void resetRing(const string &name); + void resizeRing(const string &name, unsigned int newsize); + unsigned int getRingSize(const string &name); + + string directory(); //!< Returns a list of all data stored + vector getEntries(); //!< returns a vector with datums (items) + string getDescrip(const string &item); //!< Returns the description of this datum/item + void exists(const string &key); //!< call this function to throw an exception in case a key does not exist + inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount + inline void inc(const string &key); //!< increase this key's value by one + void set(const string &key, unsigned long value); //!< set this key's value + unsigned long read(const string &key); //!< read the value behind this key + unsigned long readZero(const string &key); //!< read the value behind this key, and zero it afterwards + AtomicCounter *getPointer(const string &key); //!< get a direct pointer to the value behind a key. Use this for high performance increments + string getValueStr(const string &key); //!< read a value behind a key, and return it as a string + string getValueStrZero(const string &key); //!< read a value behind a key, and return it as a string, and zero afterwards + void blacklist(const string &str); +}; + +inline void StatBag::deposit(const string &key, int value) +{ + exists(key); + + *d_stats[key]+=value; +} + +inline void StatBag::inc(const string &key) +{ + deposit(key,1); +} + + +#endif /* STATBAG_HH */ diff --git a/pdns/statnode.cc b/pdns/statnode.cc new file mode 100644 index 0000000..1557bbb --- /dev/null +++ b/pdns/statnode.cc @@ -0,0 +1,119 @@ +#include "statnode.hh" + +StatNode::Stat StatNode::print(unsigned int depth, Stat newstat, bool silent) const +{ + if(!silent) { + cout<1024 && !silent) { + cout<1024); + } + if(!silent || children.size()>1) + cout< remote) +{ + // cerr<<"FIRST submit called on '"< tmp = domain.getRawLabels(); + if(tmp.empty()) + return; + + auto last = tmp.end() - 1; + children[*last].submit(last, tmp.begin(), "", rcode, remote, 1); +} + +/* www.powerdns.com. -> + . <- fullnames + com. + powerdns.com + www.powerdns.com. +*/ + +void StatNode::submit(std::vector::const_iterator end, std::vector::const_iterator begin, const std::string& domain, int rcode, boost::optional remote, unsigned int count) +{ + // cerr<<"Submit called for domain='"< +#include +#include "iputils.hh" + +class StatNode +{ +public: + + struct Stat + { + Stat() : queries(0), noerrors(0), nxdomains(0), servfails(0), drops(0){} + uint64_t queries, noerrors, nxdomains, servfails, drops; + + Stat& operator+=(const Stat& rhs) { + queries+=rhs.queries; + noerrors+=rhs.noerrors; + nxdomains+=rhs.nxdomains; + servfails+=rhs.servfails; + drops+=rhs.drops; + + for(const remotes_t::value_type& rem : rhs.remotes) { + remotes[rem.first]+=rem.second; + } + return *this; + } + typedef std::map remotes_t; + remotes_t remotes; + }; + + Stat s; + std::string name; + std::string fullname; + unsigned int labelsCount{0}; + + void submit(const DNSName& domain, int rcode, boost::optional remote); + + Stat print(unsigned int depth=0, Stat newstat=Stat(), bool silent=false) const; + typedef boost::function visitor_t; + void visit(visitor_t visitor, Stat& newstat, unsigned int depth=0) const; + bool empty() const + { + return children.empty() && s.remotes.empty(); + } + typedef std::map children_t; + children_t children; + +private: + void submit(std::vector::const_iterator end, std::vector::const_iterator begin, const std::string& domain, int rcode, boost::optional remote, unsigned int count); +}; diff --git a/pdns/stubquery.cc b/pdns/stubquery.cc new file mode 100644 index 0000000..1da9644 --- /dev/null +++ b/pdns/stubquery.cc @@ -0,0 +1,69 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "arguments.hh" +#include "dnsrecords.hh" +#include "dns_random.hh" +#include "stubresolver.hh" +#include "statbag.hh" + +StatBag S; + +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} + +void usage() { + cerr<<"stubquery"< ret; + + int res=stubDoResolve(DNSName(argv[1]), DNSRecordContent::TypeToNumber(type), ret); + + cout<<"res: "<getZoneRepresentation()< + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "logger.hh" +#include "arguments.hh" +#include "version.hh" +#include "misc.hh" + +#include "sstuff.hh" +#include "dnswriter.hh" +#include "dns_random.hh" +#include "namespaces.hh" +#include "statbag.hh" +#include "stubresolver.hh" + +#define LOCAL_RESOLV_CONF_PATH "/etc/resolv.conf" +// don't stat() for local resolv.conf more than once every INTERVAL secs. +#define LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL 60 + +// s_resolversForStub contains the ComboAddresses that are used by +// stubDoResolve +static vector s_resolversForStub; +static pthread_rwlock_t s_resolversForStubLock = PTHREAD_RWLOCK_INITIALIZER; +static bool s_stubResolvConfigured = false; + +// /etc/resolv.conf last modification time +static time_t s_localResolvConfMtime = 0; +static time_t s_localResolvConfLastCheck = 0; + +/* + * Returns false if no resolvers are configured, while emitting a warning about this + */ +bool resolversDefined() +{ + ReadLock l(&s_resolversForStubLock); + if (s_resolversForStub.empty()) { + g_log< resolvers = getResolvers(LOCAL_RESOLV_CONF_PATH); + + s_localResolvConfMtime = st.st_mtime; + + if (resolvers.empty()) { + return; + } + + s_resolversForStub = std::move(resolvers); + } + } +} + +static void parseLocalResolvConf() +{ + const time_t now = time(nullptr); + if ((s_localResolvConfLastCheck + LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL) > now) + return ; + + WriteLock wl(&s_resolversForStubLock); + parseLocalResolvConf_locked(now); +} + + +/* + * Fill the s_resolversForStub vector with addresses for the upstream resolvers. + * First, parse the `resolver` configuration option for IP addresses to use. + * If that doesn't work, parse /etc/resolv.conf and add those nameservers to + * s_resolversForStub. + * + * mainthread() calls this so you don't have to. + */ +void stubParseResolveConf() +{ + if(::arg().mustDo("resolver")) { + WriteLock wl(&s_resolversForStubLock); + vector parts; + stringtok(parts, ::arg()["resolver"], " ,\t"); + for (const auto& addr : parts) + s_resolversForStub.push_back(ComboAddress(addr, 53)); + } + + if (s_resolversForStub.empty()) { + parseLocalResolvConf(); + } + // Emit a warning if there are no stubs. + resolversDefined(); + s_stubResolvConfigured = true; +} + +// s_resolversForStub contains the ComboAddresses that are used to resolve the +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret) +{ + // ensure resolver gets always configured + if (!s_stubResolvConfigured) { + stubParseResolveConf(); + } + // only check if resolvers come from local resolv.conf in the first place + if (s_localResolvConfMtime != 0) { + parseLocalResolvConf(); + } + if (!resolversDefined()) + return RCode::ServFail; + + ReadLock l(&s_resolversForStubLock); + vector packet; + + DNSPacketWriter pw(packet, qname, qtype); + pw.getHeader()->id=dns_random(0xffff); + pw.getHeader()->rd=1; + + string msg ="Doing stub resolving, using resolvers: "; + for (const auto& server : s_resolversForStub) { + msg += server.toString() + ", "; + } + g_log< sizeof(struct dnsheader)) { + struct dnsheader d; + memcpy(&d, reply.c_str(), sizeof(d)); + if(d.id != pw.getHeader()->id) + goto retry; + } + } + catch(...) { + continue; + } + MOADNSParser mdp(false, reply); + if(mdp.d_header.rcode == RCode::ServFail) + continue; + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_place == 1 && i->first.d_type==qtype) { + DNSZoneRecord zrr; + zrr.dr = i->first; + zrr.auth=true; + ret.push_back(zrr); + } + } + g_log<& ret); diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc new file mode 100644 index 0000000..c925766 --- /dev/null +++ b/pdns/tcpreceiver.cc @@ -0,0 +1,1397 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002-2012 PowerDNS.COM BV + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation + + Additionally, the license of this program contains a special + exception which allows to distribute the program in binary form when + it is linked against OpenSSL. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "auth-packetcache.hh" +#include "utility.hh" +#include "threadname.hh" +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include +#include "base32.hh" +#include +#include +#include +#include +#include +#include +#include "tcpreceiver.hh" +#include "sstuff.hh" + +#include +#include +#include "base64.hh" +#include "ueberbackend.hh" +#include "dnspacket.hh" +#include "nameserver.hh" +#include "distributor.hh" +#include "lock.hh" +#include "logger.hh" +#include "arguments.hh" + +#include "common_startup.hh" +#include "packethandler.hh" +#include "statbag.hh" +#include "resolver.hh" +#include "communicator.hh" +#include "namespaces.hh" +#include "signingpipe.hh" +#include "stubresolver.hh" +extern AuthPacketCache PC; +extern StatBag S; + +/** +\file tcpreceiver.cc +\brief This file implements the tcpreceiver that receives and answers questions over TCP/IP +*/ + +pthread_mutex_t TCPNameserver::s_plock = PTHREAD_MUTEX_INITIALIZER; +Semaphore *TCPNameserver::d_connectionroom_sem; +unsigned int TCPNameserver::d_maxTCPConnections = 0; +PacketHandler *TCPNameserver::s_P; +NetmaskGroup TCPNameserver::d_ng; +size_t TCPNameserver::d_maxTransactionsPerConn; +size_t TCPNameserver::d_maxConnectionsPerClient; +unsigned int TCPNameserver::d_idleTimeout; +unsigned int TCPNameserver::d_maxConnectionDuration; +std::mutex TCPNameserver::s_clientsCountMutex; +std::map TCPNameserver::s_clientsCount; + +void TCPNameserver::go() +{ + g_log<(this)); +} + +void *TCPNameserver::launcher(void *data) +{ + static_cast(data)->thread(); + return 0; +} + +// throws PDNSException if things didn't go according to plan, returns 0 if really 0 bytes were read +static int readnWithTimeout(int fd, void* buffer, unsigned int n, unsigned int idleTimeout, bool throwOnEOF=true, unsigned int totalTimeout=0) +{ + unsigned int bytes=n; + char *ptr = (char*)buffer; + int ret; + time_t start = 0; + unsigned int remainingTotal = totalTimeout; + if (totalTimeout) { + start = time(NULL); + } + while(bytes) { + ret=read(fd, ptr, bytes); + if(ret < 0) { + if(errno==EAGAIN) { + ret=waitForData(fd, (totalTimeout == 0 || idleTimeout <= remainingTotal) ? idleTimeout : remainingTotal); + if(ret < 0) + throw NetworkError("Waiting for data read"); + if(!ret) + throw NetworkError("Timeout reading data"); + continue; + } + else + throw NetworkError("Reading data: "+stringerror()); + } + if(!ret) { + if(!throwOnEOF && n == bytes) + return 0; + else + throw NetworkError("Did not fulfill read from TCP due to EOF"); + } + + ptr += ret; + bytes -= ret; + if (totalTimeout) { + time_t now = time(NULL); + unsigned int elapsed = now - start; + if (elapsed >= remainingTotal) { + throw NetworkError("Timeout while reading data"); + } + start = now; + remainingTotal -= elapsed; + } + } + return n; +} + +// ditto +static void writenWithTimeout(int fd, const void *buffer, unsigned int n, unsigned int idleTimeout) +{ + unsigned int bytes=n; + const char *ptr = (char*)buffer; + int ret; + while(bytes) { + ret=write(fd, ptr, bytes); + if(ret < 0) { + if(errno==EAGAIN) { + ret=waitForRWData(fd, false, idleTimeout, 0); + if(ret < 0) + throw NetworkError("Waiting for data write"); + if(!ret) + throw NetworkError("Timeout writing data"); + continue; + } + else + throw NetworkError("Writing data: "+stringerror()); + } + if(!ret) { + throw NetworkError("Did not fulfill TCP write due to EOF"); + } + + ptr += ret; + bytes -= ret; + } +} + +void connectWithTimeout(int fd, struct sockaddr* remote, size_t socklen) +{ + int err; + Utility::socklen_t len=sizeof(err); + + if((err=connect(fd, remote, socklen))<0 && errno!=EINPROGRESS) + throw NetworkError("connect: "+stringerror()); + + if(!err) + goto done; + + err=waitForRWData(fd, false, 5, 0); + if(err == 0) + throw NetworkError("Timeout connecting to remote"); + if(err < 0) + throw NetworkError("Error connecting to remote"); + + if(getsockopt(fd, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0) + throw NetworkError("Error connecting to remote: "+stringerror()); // Solaris + + if(err) + throw NetworkError("Error connecting to remote: "+string(strerror(err))); + + done: + ; +} + +void TCPNameserver::sendPacket(shared_ptr p, int outsock) +{ + g_rs.submitResponse(*p, false); + + uint16_t len=htons(p->getString().length()); + string buffer((const char*)&len, 2); + buffer.append(p->getString()); + writenWithTimeout(outsock, buffer.c_str(), buffer.length(), d_idleTimeout); +} + + +void TCPNameserver::getQuestion(int fd, char *mesg, int pktlen, const ComboAddress &remote, unsigned int totalTime) +try +{ + readnWithTimeout(fd, mesg, pktlen, d_idleTimeout, true, totalTime); +} +catch(NetworkError& ae) { + throw NetworkError("Error reading DNS data from TCP client "+remote.toString()+": "+ae.what()); +} + +static void incTCPAnswerCount(const ComboAddress& remote) +{ + S.inc("tcp-answers"); + if(remote.sin4.sin_family == AF_INET6) + S.inc("tcp6-answers"); + else + S.inc("tcp4-answers"); +} + +static bool maxConnectionDurationReached(unsigned int maxConnectionDuration, time_t start, unsigned int& remainingTime) +{ + if (maxConnectionDuration) { + time_t elapsed = time(NULL) - start; + if (elapsed >= maxConnectionDuration) { + return true; + } + remainingTime = maxConnectionDuration - elapsed; + } + return false; +} + +void TCPNameserver::decrementClientCount(const ComboAddress& remote) +{ + if (d_maxConnectionsPerClient) { + std::lock_guard lock(s_clientsCountMutex); + s_clientsCount[remote]--; + if (s_clientsCount[remote] == 0) { + s_clientsCount.erase(remote); + } + } +} + +void *TCPNameserver::doConnection(void *data) +{ + setThreadName("pdns/tcpConnect"); + shared_ptr packet; + // Fix gcc-4.0 error (on AMD64) + int fd=(int)(long)data; // gotta love C (generates a harmless warning on opteron) + ComboAddress remote; + socklen_t remotelen=sizeof(remote); + size_t transactions = 0; + time_t start = 0; + if (d_maxConnectionDuration) { + start = time(NULL); + } + + pthread_detach(pthread_self()); + if(getpeername(fd, (struct sockaddr *)&remote, &remotelen) < 0) { + g_log<post(); + try { + closesocket(fd); + } + catch(const PDNSException& e) { + g_log< mesg(new char[mesgsize]); + + DLOG(g_log<<"TCP Connection accepted on fd "< d_maxTransactionsPerConn) { + g_log << Logger::Notice<<"TCP Remote "<< remote <<" exceeded the number of transactions per connection, dropping."; + break; + } + if (maxConnectionDurationReached(d_maxConnectionDuration, start, remainingTime)) { + g_log << Logger::Notice<<"TCP Remote "<< remote <<" exceeded the maximum TCP connection duration, dropping."; + break; + } + + uint16_t pktlen; + if(!readnWithTimeout(fd, &pktlen, 2, d_idleTimeout, false, remainingTime)) + break; + else + pktlen=ntohs(pktlen); + + // this check will always be false *if* no one touches + // the mesg array. pktlen can be maximum of 65535 as + // it is 2 byte unsigned variable. In getQuestion, we + // write to 0 up to pktlen-1 so 65535 is just right. + + // do not remove this check as it will catch if someone + // decreases the mesg buffer size for some reason. + if(pktlen > mesgsize) { + g_log<(new DNSPacket(true)); + packet->setRemote(&remote); + packet->d_tcp=true; + packet->setSocket(fd); + if(packet->parse(mesg.get(), pktlen)<0) + break; + + if(packet->qtype.getCode()==QType::AXFR) { + if(doAXFR(packet->qdomain, packet, fd)) + incTCPAnswerCount(remote); + continue; + } + + if(packet->qtype.getCode()==QType::IXFR) { + if(doIXFR(packet, fd)) + incTCPAnswerCount(remote); + continue; + } + + shared_ptr reply; + shared_ptr cached= shared_ptr(new DNSPacket(false)); + if(logDNSQueries) { + string remote_text; + if(packet->hasEDNSSubnet()) + remote_text = packet->getRemote().toString() + "<-" + packet->getRealRemote().toString(); + else + remote_text = packet->getRemote().toString(); + g_log << Logger::Notice<<"TCP Remote "<< remote_text <<" wants '" << packet->qdomain<<"|"<qtype.getName() << + "', do = " <d_dnssecOk <<", bufsize = "<< packet->getMaxReplyLen()<<": "; + } + + if(PC.enabled()) { + if(packet->couldBeCached() && PC.get(packet.get(), cached.get())) { // short circuit - does the PacketCache recognize this question? + if(logDNSQueries) + g_log<<"packetcache HIT"<setRemote(&packet->d_remote); + cached->d.id=packet->d.id; + cached->d.rd=packet->d.rd; // copy in recursion desired bit + cached->commitD(); // commit d to the packet inlined + + sendPacket(cached, fd); // presigned, don't do it again + continue; + } + if(logDNSQueries) + g_log<<"packetcache MISS"<(s_P->doQuestion(packet.get())); // we really need to ask the backend :-) + } + + if(!reply) // unable to write an answer? + break; + + sendPacket(reply, fd); + } + } + catch(PDNSException &ae) { + Lock l(&s_plock); + delete s_P; + s_P = 0; // on next call, backend will be recycled + g_log<post(); + + try { + closesocket(fd); + } + catch(const PDNSException& e) { + g_log< q) +{ + if(::arg().mustDo("disable-axfr")) + return false; + + if(q->d_havetsig) { // if you have one, it must be good + TSIGRecordContent trc; + DNSName keyname; + string secret; + if(!q->checkForCorrectTSIG(s_P->getBackend(), &keyname, &secret, &trc)) { + return false; + } else { + getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo); + if (q->d_tsig_algo == TSIG_GSS) { + GssContext gssctx(keyname); + if (!gssctx.getPeerPrincipal(q->d_peer_principal)) { + g_log<getBackend()); + + if (q->d_tsig_algo == TSIG_GSS) { + vector princs; + s_P->getBackend()->getDomainMetadata(q->qdomain, "GSS-ALLOW-AXFR-PRINCIPAL", princs); + for(const std::string& princ : princs) { + if (q->d_peer_principal == princ) { + g_log<qdomain<<"' allowed: TSIG signed request with authorized principal '"<d_peer_principal<<"' and algorithm 'gss-tsig'"<qdomain<<"' denied: TSIG signed request with principal '"<d_peer_principal<<"' and algorithm 'gss-tsig' is not permitted"<qdomain, keyname)) { + g_log<qdomain<<"' denied: key with name '"<d_tsig_algo)<<"' does not grant access to zone"<qdomain<<"' allowed: TSIG signed request with authorized key '"<d_tsig_algo)<<"'"<d_remote )) { + g_log<qdomain<<"' allowed: client IP "<getRemote()<<" is in allow-axfr-ips"<getBackend()->getSOAUncached(q->qdomain,sd)) { + // cerr<<"got backend and SOA"< acl; + s_P->getBackend()->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl); + for (vector::const_iterator i = acl.begin(); i != acl.end(); ++i) { + // cerr<<"matching against "<<*i< nsset; + + B->lookup(QType(QType::NS),q->qdomain); + while(B->get(rr)) + nsset.insert(DNSName(rr.content)); + for(const auto & j: nsset) { + vector nsips=fns.lookup(j, s_P->getBackend()); + for(vector::const_iterator k=nsips.begin();k!=nsips.end();++k) { + // cerr<<"got "<<*k<<" from AUTO-NS"<getRemote().toString()) + { + // cerr<<"got AUTO-NS hit"<qdomain<<"' allowed: client IP "<getRemote()<<" is in NSset"<d_remote )) + { + g_log<qdomain<<"' allowed: client IP "<getRemote()<<" is in per-domain ACL"<qdomain, q->getRemote().toString())) { // we just notified this ip + g_log<qdomain<<"' from recently notified slave "<getRemote()<qdomain<<"' denied: client IP "<getRemote()<<" has no permission"< getFreshAXFRPacket(shared_ptr q) + { + shared_ptr ret = shared_ptr(q->replyPacket()); + ret->setCompress(false); + ret->d_dnssecOk=false; // RFC 5936, 2.2.5 + ret->d_tcp = true; + return ret; + } +} + + +/** do the actual zone transfer. Return 0 in case of error, 1 in case of success */ +int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int outsock) +{ + shared_ptr outpacket= getFreshAXFRPacket(q); + if(q->d_dnssecOk) + outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD' + + g_log<getRemote()<getRemote()<<" may not request AXFR"<setRcode(RCode::NotAuth); + sendPacket(outpacket,outsock); + return 0; + } + + if(!s_P->getBackend()->getSOAUncached(target, sd)) { + g_log<setRcode(RCode::NotAuth); + sendPacket(outpacket,outsock); + return 0; + } + } + + UeberBackend db; + if(!db.getSOAUncached(target, sd)) { + g_log<setRcode(RCode::NotAuth); + sendPacket(outpacket,outsock); + return 0; + } + + DNSSECKeeper dk(&db); + dk.clearCaches(target); + bool securedZone = dk.isSecuredZone(target); + bool presignedZone = dk.isPresigned(target); + + bool noAXFRBecauseOfNSEC3Narrow=false; + NSEC3PARAMRecordContent ns3pr; + bool narrow; + bool NSEC3Zone=false; + if(securedZone && dk.getNSEC3PARAM(target, &ns3pr, &narrow)) { + NSEC3Zone=true; + if(narrow) { + g_log<getRemote()<getRemote()<setRcode(RCode::Refused); + // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't + sendPacket(outpacket,outsock); + return 0; + } + + TSIGRecordContent trc; + DNSName tsigkeyname; + string tsigsecret; + + bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname); + + if(haveTSIGDetails && !tsigkeyname.empty()) { + string tsig64; + DNSName algorithm=trc.d_algoName; // FIXME400: check + if (algorithm == DNSName("hmac-md5.sig-alg.reg.int")) + algorithm = DNSName("hmac-md5"); + if (algorithm != DNSName("gss-tsig")) { + if(!db.getTSIGKey(tsigkeyname, &algorithm, &tsig64)) { + g_log<addRecord(soa); + if(securedZone && !presignedZone) { + set authSet; + authSet.insert(target); + addRRSigs(dk, db, authSet, outpacket->getRRS()); + } + + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal' + + sendPacket(outpacket, outsock); + + trc.d_mac = outpacket->d_trc.d_mac; + outpacket = getFreshAXFRPacket(q); + + ChunkedSigningPipe csp(target, (securedZone && !presignedZone), ::arg().asNum("signing-threads", 1)); + + typedef map nsecxrepo_t; + nsecxrepo_t nsecxrepo; + + // this is where the DNSKEYs go in + + DNSSECKeeper::keyset_t keys = dk.getKeys(target); + + DNSZoneRecord zrr; + + zrr.dr.d_name = target; + zrr.dr.d_ttl = sd.default_ttl; + zrr.auth = 1; // please sign! + + string publishCDNSKEY, publishCDS; + dk.getFromMeta(q->qdomain, "PUBLISH-CDNSKEY", publishCDNSKEY); + dk.getFromMeta(q->qdomain, "PUBLISH-CDS", publishCDS); + vector cds, cdnskey; + DNSSECKeeper::keyset_t entryPoints = dk.getEntryPoints(q->qdomain); + set entryPointIds; + for (auto const& value : entryPoints) + entryPointIds.insert(value.second.id); + + for(const DNSSECKeeper::keyset_t::value_type& value : keys) { + zrr.dr.d_type = QType::DNSKEY; + zrr.dr.d_content = std::make_shared(value.first.getDNSKEY()); + DNSName keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name))) : zrr.dr.d_name; + NSECXEntry& ne = nsecxrepo[keyname]; + + ne.d_set.set(zrr.dr.d_type); + ne.d_ttl = sd.default_ttl; + csp.submit(zrr); + + // generate CDS and CDNSKEY records + if(entryPointIds.count(value.second.id) > 0){ + if(publishCDNSKEY == "1") { + zrr.dr.d_type=QType::CDNSKEY; + zrr.dr.d_content = std::make_shared(value.first.getDNSKEY()); + cdnskey.push_back(zrr); + } + + if(!publishCDS.empty()){ + zrr.dr.d_type=QType::CDS; + vector digestAlgos; + stringtok(digestAlgos, publishCDS, ", "); + for(auto const &digestAlgo : digestAlgos) { + zrr.dr.d_content=std::make_shared(makeDSFromDNSKey(target, value.first.getDNSKEY(), pdns_stou(digestAlgo))); + cds.push_back(zrr); + } + } + } + } + + if(::arg().mustDo("direct-dnskey")) { + sd.db->lookup(QType(QType::DNSKEY), target, NULL, sd.domain_id); + while(sd.db->get(zrr)) { + zrr.dr.d_ttl = sd.default_ttl; + csp.submit(zrr); + } + } + + uint8_t flags; + + if(NSEC3Zone) { // now stuff in the NSEC3PARAM + flags = ns3pr.d_flags; + zrr.dr.d_type = QType::NSEC3PARAM; + ns3pr.d_flags = 0; + zrr.dr.d_content = std::make_shared(ns3pr); + ns3pr.d_flags = flags; + DNSName keyname = DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name))); + NSECXEntry& ne = nsecxrepo[keyname]; + + ne.d_set.set(zrr.dr.d_type); + csp.submit(zrr); + } + + // now start list zone + if(!(sd.db->list(target, sd.domain_id))) { + g_log<setRcode(RCode::ServFail); + sendPacket(outpacket,outsock); + return 0; + } + + + const bool rectify = !(presignedZone || ::arg().mustDo("disable-axfr-rectify")); + set qnames, nsset, terms; + vector zrrs; + + // Add the CDNSKEY and CDS records we created earlier + for (auto const &synth_zrr : cds) + zrrs.push_back(synth_zrr); + + for (auto const &synth_zrr : cdnskey) + zrrs.push_back(synth_zrr); + + while(sd.db->get(zrr)) { + zrr.dr.d_name.makeUsLowerCase(); + if(zrr.dr.d_name.isPartOf(target)) { + if (zrr.dr.d_type == QType::ALIAS && ::arg().mustDo("outgoing-axfr-expand-alias")) { + vector ips; + int ret1 = stubDoResolve(getRR(zrr.dr)->d_content, QType::A, ips); + int ret2 = stubDoResolve(getRR(zrr.dr)->d_content, QType::AAAA, ips); + if(ret1 != RCode::NoError || ret2 != RCode::NoError) { + g_log<getZoneRepresentation()<<", aborting AXFR"<setRcode(RCode::ServFail); + sendPacket(outpacket,outsock); + return 0; + } + for(const auto& ip: ips) { + zrr.dr.d_type = ip.dr.d_type; + zrr.dr.d_content = ip.dr.d_content; + zrrs.push_back(zrr); + } + continue; + } + + if (rectify) { + if (zrr.dr.d_type) { + qnames.insert(zrr.dr.d_name); + if(zrr.dr.d_type == QType::NS && zrr.dr.d_name!=target) + nsset.insert(zrr.dr.d_name); + } else { + // remove existing ents + continue; + } + } + zrrs.push_back(zrr); + } else { + if (zrr.dr.d_type) + g_log< nsec3set, nonterm; + for (auto &loopZRR: zrrs) { + bool skip=false; + DNSName shorter = loopZRR.dr.d_name; + if (shorter != target && shorter.chopOff() && shorter != target) { + do { + if(nsset.count(shorter)) { + skip=true; + break; + } + } while(shorter.chopOff() && shorter != target); + } + shorter = loopZRR.dr.d_name; + if(!skip && (loopZRR.dr.d_type != QType::NS || !ns3pr.d_flags)) { + do { + if(!nsec3set.count(shorter)) { + nsec3set.insert(shorter); + } + } while(shorter != target && shorter.chopOff()); + } + } + + for(DNSZoneRecord &loopZRR : zrrs) { + DNSName shorter(loopZRR.dr.d_name); + while(shorter != target && shorter.chopOff()) { + if(!qnames.count(shorter) && !nonterm.count(shorter) && nsec3set.count(shorter)) { + if(!(maxent)) { + g_log<(loopZRR.dr)->d_type == QType::NSEC3) { + keyname = loopZRR.dr.d_name.makeRelative(sd.qname); + } else { + keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, loopZRR.dr.d_name))) : loopZRR.dr.d_name; + } + NSECXEntry& ne = nsecxrepo[keyname]; + ne.d_ttl = sd.default_ttl; + ne.d_auth = (ne.d_auth || loopZRR.auth || (NSEC3Zone && (!ns3pr.d_flags))); + if (loopZRR.dr.d_type && loopZRR.dr.d_type != QType::RRSIG) { + ne.d_set.set(loopZRR.dr.d_type); + } + } + } + + if (!loopZRR.dr.d_type) + continue; // skip empty non-terminals + + if(loopZRR.dr.d_type == QType::SOA) + continue; // skip SOA - would indicate end of AXFR + + if(csp.submit(loopZRR)) { + for(;;) { + outpacket->getRRS() = csp.getChunk(); + if(!outpacket->getRRS().empty()) { + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); + sendPacket(outpacket, outsock); + trc.d_mac=outpacket->d_trc.d_mac; + outpacket=getFreshAXFRPacket(q); + } + else + break; + } + } + } + /* + udiff=dt.udiffNoReset(); + cerr<<"Starting NSEC: "<second.d_auth) { + NSEC3RecordContent n3rc; + n3rc.set(iter->second.d_set); + const auto numberOfTypesSet = n3rc.numberOfTypesSet(); + if (numberOfTypesSet != 0 && (numberOfTypesSet != 1 || !n3rc.isSet(QType::NS))) { + n3rc.set(QType::RRSIG); + } + n3rc.d_salt = ns3pr.d_salt; + n3rc.d_flags = ns3pr.d_flags; + n3rc.d_iterations = ns3pr.d_iterations; + n3rc.d_algorithm = DNSSECKeeper::SHA1; // SHA1, fixed in PowerDNS for now + nsecxrepo_t::const_iterator inext = iter; + ++inext; + if(inext == nsecxrepo.end()) + inext = nsecxrepo.begin(); + while(!inext->second.d_auth && inext != iter) + { + ++inext; + if(inext == nsecxrepo.end()) + inext = nsecxrepo.begin(); + } + n3rc.d_nexthash = fromBase32Hex(inext->first.toStringNoDot()); + zrr.dr.d_name = iter->first+sd.qname; + + zrr.dr.d_ttl = sd.default_ttl; + zrr.dr.d_content = std::make_shared(std::move(n3rc)); + zrr.dr.d_type = QType::NSEC3; + zrr.dr.d_place = DNSResourceRecord::ANSWER; + zrr.auth=true; + if(csp.submit(zrr)) { + for(;;) { + outpacket->getRRS() = csp.getChunk(); + if(!outpacket->getRRS().empty()) { + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); + sendPacket(outpacket, outsock); + trc.d_mac=outpacket->d_trc.d_mac; + outpacket=getFreshAXFRPacket(q); + } + else + break; + } + } + } + } + } + else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) { + NSECRecordContent nrc; + nrc.set(iter->second.d_set); + nrc.set(QType::RRSIG); + nrc.set(QType::NSEC); + + if(boost::next(iter) != nsecxrepo.end()) + nrc.d_next = boost::next(iter)->first; + else + nrc.d_next=nsecxrepo.begin()->first; + zrr.dr.d_name = iter->first; + + zrr.dr.d_ttl = sd.default_ttl; + zrr.dr.d_content = std::make_shared(std::move(nrc)); + zrr.dr.d_type = QType::NSEC; + zrr.dr.d_place = DNSResourceRecord::ANSWER; + zrr.auth=true; + if(csp.submit(zrr)) { + for(;;) { + outpacket->getRRS() = csp.getChunk(); + if(!outpacket->getRRS().empty()) { + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); + sendPacket(outpacket, outsock); + trc.d_mac=outpacket->d_trc.d_mac; + outpacket=getFreshAXFRPacket(q); + } + else + break; + } + } + } + } + /* + udiff=dt.udiffNoReset(); + cerr<<"Flushing pipe: "<getRRS() = csp.getChunk(true); // flush the pipe + if(!outpacket->getRRS().empty()) { + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); // first answer is 'normal' + sendPacket(outpacket, outsock); + trc.d_mac=outpacket->d_trc.d_mac; + outpacket=getFreshAXFRPacket(q); + } + else + break; + } + + udiff=dt.udiffNoReset(); + if(securedZone) + g_log<addRecord(soa); + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); + + sendPacket(outpacket, outsock); + + DLOG(g_log<<"last packet - close"<getRemote()<<" finished"< q, int outsock) +{ + shared_ptr outpacket=getFreshAXFRPacket(q); + if(q->d_dnssecOk) + outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD' + + uint32_t serial = 0; + MOADNSParser mdp(false, q->getString()); + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) { + const DNSRecord *rr = &i->first; + if (rr->d_type == QType::SOA && rr->d_place == DNSResourceRecord::AUTHORITY) { + vectorparts; + stringtok(parts, rr->d_content->getZoneRepresentation()); + if (parts.size() >= 3) { + try { + serial=pdns_stou(parts[2]); + } + catch(const std::out_of_range& oor) { + g_log<setRcode(RCode::FormErr); + sendPacket(outpacket,outsock); + return 0; + } + } else { + g_log<setRcode(RCode::FormErr); + sendPacket(outpacket,outsock); + return 0; + } + } else if (rr->d_type != QType::TSIG && rr->d_type != QType::OPT) { + g_log<d_type).getName()<setRcode(RCode::FormErr); + sendPacket(outpacket,outsock); + return 0; + } + } + + g_log<qdomain<<"' initiated by "<getRemote()<<" with serial "<getBackend()->getSOAUncached(q->qdomain, sd)) { + g_log<qdomain<<"' failed: not authoritative"<setRcode(RCode::NotAuth); + sendPacket(outpacket,outsock); + return 0; + } + } + + DNSSECKeeper dk; + NSEC3PARAMRecordContent ns3pr; + bool narrow; + + dk.clearCaches(q->qdomain); + bool securedZone = dk.isSecuredZone(q->qdomain); + if(dk.getNSEC3PARAM(q->qdomain, &ns3pr, &narrow)) { + if(narrow) { + g_log<qdomain<<"' denied to "<getRemote()<setRcode(RCode::Refused); + sendPacket(outpacket,outsock); + return 0; + } + } + + DNSName target = q->qdomain; + + UeberBackend db; + if(!db.getSOAUncached(target, sd)) { + g_log<setRcode(RCode::NotAuth); + sendPacket(outpacket,outsock); + return 0; + } + + if (!rfc1982LessThan(serial, calculateEditSOA(sd.serial, dk, sd.qname))) { + TSIGRecordContent trc; + DNSName tsigkeyname; + string tsigsecret; + + bool haveTSIGDetails = q->getTSIGDetails(&trc, &tsigkeyname); + + if(haveTSIGDetails && !tsigkeyname.empty()) { + string tsig64; + DNSName algorithm=trc.d_algoName; // FIXME400: was toLowerCanonic, compare output + if (algorithm == DNSName("hmac-md5.sig-alg.reg.int")) + algorithm = DNSName("hmac-md5"); + Lock l(&s_plock); + if(!s_P->getBackend()->getTSIGKey(tsigkeyname, &algorithm, &tsig64)) { + g_log<addRecord(soa); + if(securedZone) { + set authSet; + authSet.insert(target); + addRRSigs(dk, signatureDB, authSet, outpacket->getRRS()); + } + + if(haveTSIGDetails && !tsigkeyname.empty()) + outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal' + + sendPacket(outpacket, outsock); + + g_log<getRemote()<<" finished"<qdomain, q, outsock); +} + +TCPNameserver::~TCPNameserver() +{ + delete d_connectionroom_sem; +} + +TCPNameserver::TCPNameserver() +{ + d_maxTransactionsPerConn = ::arg().asNum("max-tcp-transactions-per-conn"); + d_idleTimeout = ::arg().asNum("tcp-idle-timeout"); + d_maxConnectionDuration = ::arg().asNum("max-tcp-connection-duration"); + d_maxConnectionsPerClient = ::arg().asNum("max-tcp-connections-per-client"); + +// sem_init(&d_connectionroom_sem,0,::arg().asNum("max-tcp-connections")); + d_connectionroom_sem = new Semaphore( ::arg().asNum( "max-tcp-connections" )); + d_maxTCPConnections = ::arg().asNum( "max-tcp-connections" ); + d_tid=0; + vectorlocals; + stringtok(locals,::arg()["local-address"]," ,"); + + vectorlocals6; + stringtok(locals6,::arg()["local-ipv6"]," ,"); + + if(locals.empty() && locals6.empty()) + throw PDNSException("No local address specified"); + + d_ng.toMasks(::arg()["allow-axfr-ips"] ); + + signal(SIGPIPE,SIG_IGN); + + for(vector::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) { + int s=socket(AF_INET,SOCK_STREAM,0); + + if(s<0) + throw PDNSException("Unable to acquire TCP socket: "+stringerror()); + + setCloseOnExec(s); + + ComboAddress local(*laddr, ::arg().asNum("local-port")); + + int tmp=1; + if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) { + g_log< 0) { +#ifdef TCP_FASTOPEN + int fastOpenQueueSize = ::arg().asNum("tcp-fast-open"); + if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) { + g_log<::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) { + int s=socket(AF_INET6,SOCK_STREAM,0); + + if(s<0) + throw PDNSException("Unable to acquire TCPv6 socket: "+stringerror()); + + setCloseOnExec(s); + + ComboAddress local(*laddr, ::arg().asNum("local-port")); + + int tmp=1; + if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) { + g_log< 0) { +#ifdef TCP_FASTOPEN + int fastOpenQueueSize = ::arg().asNum("tcp-fast-open"); + if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) { + g_log< lock(s_clientsCountMutex); + if (s_clientsCount[remote] >= d_maxConnectionsPerClient) { + g_log<wait(); // blocks if no connections are available + + int room; + d_connectionroom_sem->getValue( &room); + if(room<1) + g_log<(fd))) { + g_log<post(); + close(fd); + decrementClientCount(remote); + } + } + } + } + } + } + catch(PDNSException &AE) { + g_log<getValue( &room); + return d_maxTCPConnections - room; +} diff --git a/pdns/tcpreceiver.hh b/pdns/tcpreceiver.hh new file mode 100644 index 0000000..fd8b33c --- /dev/null +++ b/pdns/tcpreceiver.hh @@ -0,0 +1,80 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_TCPRECEIVER_HH +#define PDNS_TCPRECEIVER_HH + +#include "dns.hh" +#include "iputils.hh" +#include "dnsbackend.hh" +#include "packethandler.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" + +class TCPNameserver +{ +public: + TCPNameserver(); + ~TCPNameserver(); + void go(); + unsigned int numTCPConnections(); +private: + + static void sendPacket(std::shared_ptr p, int outsock); + static int readLength(int fd, ComboAddress *remote); + static void getQuestion(int fd, char *mesg, int pktlen, const ComboAddress& remote, unsigned int totalTime); + static int doAXFR(const DNSName &target, std::shared_ptr q, int outsock); + static int doIXFR(std::shared_ptr q, int outsock); + static bool canDoAXFR(std::shared_ptr q); + static void *doConnection(void *data); + static void *launcher(void *data); + static void decrementClientCount(const ComboAddress& remote); + void thread(void); + static pthread_mutex_t s_plock; + static std::mutex s_clientsCountMutex; + static std::map s_clientsCount; + static PacketHandler *s_P; + pthread_t d_tid; + static Semaphore *d_connectionroom_sem; + static unsigned int d_maxTCPConnections; + static NetmaskGroup d_ng; + static size_t d_maxTransactionsPerConn; + static size_t d_maxConnectionsPerClient; + static unsigned int d_idleTimeout; + static unsigned int d_maxConnectionDuration; + + vectord_sockets; + vector d_prfds; +}; + +#endif /* PDNS_TCPRECEIVER_HH */ diff --git a/pdns/test-arguments_cc.cc b/pdns/test-arguments_cc.cc new file mode 100644 index 0000000..70f04f3 --- /dev/null +++ b/pdns/test-arguments_cc.cc @@ -0,0 +1,61 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include "arguments.hh" +#include "namespaces.hh" + +BOOST_AUTO_TEST_SUITE(test_arguments_cc) + +BOOST_AUTO_TEST_CASE(test_file_parse) { + char path[]="/tmp/pdns-test-conf.XXXXXX"; + int fd=mkstemp(path); + if(fd < 0) + BOOST_FAIL("Unable to generate a temporary file"); + + string config= +R"(launch=launch=1234 +test=123\ +456 +test2=here # and here it stops +fail=no +success=on +really=yes)"; + + int len=write(fd, config.c_str(), config.size()); + + BOOST_CHECK_EQUAL(len, config.size()); + if(!len) + return; + close(fd); + + try { + ArgvMap arg; + for(auto& a : {"launch", "test", "test2", "fail", "success", "really"} ) + arg.set(a,a); + arg.set("default", "default")="no"; + arg.file(path); + unlink(path); + + BOOST_CHECK_EQUAL(arg["launch"], "launch=1234"); + BOOST_CHECK_EQUAL(arg["test"], "123456"); + BOOST_CHECK_EQUAL(arg.asNum("test"), 123456); + BOOST_CHECK_EQUAL(arg["test2"], "here"); + BOOST_CHECK_EQUAL(arg.mustDo("fail"), false); + BOOST_CHECK_EQUAL(arg.mustDo("success"), true); + BOOST_CHECK_EQUAL(arg.mustDo("really"), true); + BOOST_CHECK_EQUAL(arg["default"], "no"); + + } + catch(PDNSException& e) { + unlink(path); + cerr<<"Exception: "< +#include + +#include +#include "base32.hh" + +BOOST_AUTO_TEST_SUITE(test_base32_cc) + +BOOST_AUTO_TEST_CASE(test_base32_basic) { + typedef boost::tuple case_t; + typedef std::list cases_t; + + // RFC test vectors + cases_t cases = boost::assign::list_of + (case_t(std::string(""), std::string(""))) + (case_t(std::string("f"), std::string("co======"))) + (case_t(std::string("fo"), std::string("cpng===="))) + (case_t(std::string("foo"), std::string("cpnmu==="))) + (case_t(std::string("foob"), std::string("cpnmuog="))) + (case_t(std::string("fooba"), std::string("cpnmuoj1"))) + (case_t(std::string("foobar"), std::string("cpnmuoj1e8======"))) + ; + + for(const case_t& val : cases) { + std::string res; + res = toBase32Hex(val.get<0>()); + BOOST_CHECK_EQUAL(res, val.get<1>()); + res = fromBase32Hex(val.get<1>()); + BOOST_CHECK_EQUAL(res, val.get<0>()); + } +}; + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/pdns/test-base64_cc.cc b/pdns/test-base64_cc.cc new file mode 100644 index 0000000..2f694b1 --- /dev/null +++ b/pdns/test-base64_cc.cc @@ -0,0 +1,77 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "base64.hh" + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(test_base64_cc) + +BOOST_AUTO_TEST_CASE(test_Base64_Roundtrip) { + std::string before("Some Random String"), after; + std::string encoded = Base64Encode(before); + B64Decode(encoded, after); + BOOST_CHECK_EQUAL(before, after); +} + +/* for a in $(seq 1 32); + do + plain=$(pwgen -1 -s $a) + echo \(\"$plain\",\"$(echo -n $plain | openssl enc -base64)\"\) ; + done +*/ + +BOOST_AUTO_TEST_CASE(test_Base64_Encode) { + typedef std::map cases_t; + cases_t cases; + assign::insert(cases) + ("", "") + ("z","eg==") + ("x4","eDQ=") + ("J07","SjA3") + ("kl8F","a2w4Rg==") + ("2NUx9","Mk5VeDk=") + ("hwXQ8C","aHdYUThD") + ("V7ZHmlG","VjdaSG1sRw==") + ("FuNFLSd5","RnVORkxTZDU=") + ("YVGwy3Vbi","WVZHd3kzVmJp") + ("6ueW4V3oLG","NnVlVzRWM29MRw==") + ("d5zR7AWIBIQ","ZDV6UjdBV0lCSVE=") + ("WJjZ6xgpRMCD","V0pqWjZ4Z3BSTUNE") + ("e8I52L0vC9Kfq","ZThJNTJMMHZDOUtmcQ==") + ("ufxMi8EZgTDja8","dWZ4TWk4RVpnVERqYTg=") + ("MiNPxzxUkNXCFg1","TWlOUHh6eFVrTlhDRmcx") + ("abqIPosEky85gFVM","YWJxSVBvc0VreTg1Z0ZWTQ==") + ("Qccuox8igoyRKEeTo","UWNjdW94OGlnb3lSS0VlVG8=") + ("wbaw6g6WWo4iiYXosV","d2JhdzZnNldXbzRpaVlYb3NW") + ("ZIfJZIA3Kd0a6iIr0vc","WklmSlpJQTNLZDBhNmlJcjB2Yw==") + ("SUhE1RK7xrRfvYOiaPMQ","U1VoRTFSSzd4clJmdllPaWFQTVE=") + ("ZAWsEeB4bcTUzTr828VTd","WkFXc0VlQjRiY1RVelRyODI4VlRk") + ("xc9rpu0F5ztR7r3jElr2BS","eGM5cnB1MEY1enRSN3IzakVscjJCUw==") + ("xvEWPkZjqVjIZwsL5WhijES","eHZFV1BrWmpxVmpJWndzTDVXaGlqRVM=") + ("yy4yAmcBKCNF3hWriWbDnKmF","eXk0eUFtY0JLQ05GM2hXcmlXYkRuS21G") + ("9wKEMpl8OlFvnD10wwhoK7BjY","OXdLRU1wbDhPbEZ2bkQxMHd3aG9LN0JqWQ==") + ("SB6yLm39pDVIUiQ5g73BvyRzBs","U0I2eUxtMzlwRFZJVWlRNWc3M0J2eVJ6QnM=") + ("Acu4kk1puF98lIzd1b9bt8ha7Er","QWN1NGtrMXB1Rjk4bEl6ZDFiOWJ0OGhhN0Vy") + ("P4X6efItE6cn03ksLTvniqMQlel3","UDRYNmVmSXRFNmNuMDNrc0xUdm5pcU1RbGVsMw==") + ("RnQSvhIOz3ywuHCoSotJGKjBdCVbx","Um5RU3ZoSU96M3l3dUhDb1NvdEpHS2pCZENWYng=") + ("ykybXtN0lelsLSzyzd4DTP3sYp8YGu","eWt5Ylh0TjBsZWxzTFN6eXpkNERUUDNzWXA4WUd1") + ("eSHBt7Xx5F7A4HFtabXEzDLD01bnSiG","ZVNIQnQ3WHg1RjdBNEhGdGFiWEV6RExEMDFiblNpRw==") + ("dq4KydZjmcoQQ45VYBP2EDR8FqKaMul0","ZHE0S3lkWmptY29RUTQ1VllCUDJFRFI4RnFLYU11bDA="); + + for(const cases_t::value_type& val : cases) { + std::string encoded = Base64Encode(val.first), decoded; + BOOST_CHECK_EQUAL(encoded, val.second); + decoded.clear(); + B64Decode(val.second, decoded); + BOOST_CHECK_EQUAL(decoded, val.first); + } +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-bindparser_cc.cc b/pdns/test-bindparser_cc.cc new file mode 100644 index 0000000..a1ad7d1 --- /dev/null +++ b/pdns/test-bindparser_cc.cc @@ -0,0 +1,60 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "misc.hh" +#include "pdnsexception.hh" +#include + +#include +#include +#include "dnsname.hh" +#include "bindparserclasses.hh" +#include "iputils.hh" + +using std::string; + +BOOST_AUTO_TEST_SUITE(test_bindparser_cc) + +BOOST_AUTO_TEST_CASE(test_parser) { + const char *srcdir; + std::ostringstream pathbuf; + BindParser BP; + BOOST_CHECK_THROW( BP.parse("../regression-tests/named.confx"), PDNSException); + BP.setVerbose(true); + srcdir = std::getenv("SRCDIR"); + if(!srcdir) + srcdir="."; // assume no shenanigans + + pathbuf << srcdir << "/../pdns/named.conf.parsertest"; + BP.parse(pathbuf.str()); + + vector domains=BP.getDomains(); + BOOST_CHECK_EQUAL(domains.size(), 11); + +#define checkzone(i, dname, fname, ztype, nmasters) { \ + BOOST_CHECK(domains[i].name == DNSName(#dname)); \ + BOOST_CHECK_EQUAL(domains[i].filename, fname); \ + BOOST_CHECK_EQUAL(domains[i].type, #ztype); \ + BOOST_CHECK_EQUAL(domains[i].masters.size(), nmasters); \ + } + + checkzone(0, example.com, "./zones//example.com", master, 0); + checkzone(1, test.com, "./zones//test.com", slave, 1); + BOOST_CHECK_EQUAL(domains[1].masters[0].toString(), ComboAddress("1.2.3.4", 5678).toString()); + checkzone(2, test.dyndns, "./zones//test.dyndns", garblewarble, 0); + checkzone(3, wtest.com, "./zones//wtest.com", master, 0); + checkzone(4, nztest.com, "./zones//nztest.com", master, 0); + checkzone(5, dnssec-parent.com, "./zones//dnssec-parent.com", master, 0); + checkzone(6, delegated.dnssec-parent.com, "./zones//delegated.dnssec-parent.com", master, 0); + checkzone(7, secure-delegated.dnssec-parent.com, "./zones//secure-delegated.dnssec-parent.com", master, 0); + checkzone(8, minimal.com, "./zones//minimal.com", master, 0); + checkzone(9, tsig.com, "./zones//tsig.com", master, 0); + checkzone(10, stest.com, "./zones//stest.com", master, 0); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/pdns/test-common.hh b/pdns/test-common.hh new file mode 100644 index 0000000..50de3b7 --- /dev/null +++ b/pdns/test-common.hh @@ -0,0 +1,42 @@ + +#include "dnsrecords.hh" +#include "iputils.hh" + +static inline std::shared_ptr getRecordContent(uint16_t type, const std::string& content) +{ + std::shared_ptr result = nullptr; + + if (type == QType::NS) { + result = std::make_shared(DNSName(content)); + } + else if (type == QType::A) { + result = std::make_shared(ComboAddress(content)); + } + else if (type == QType::AAAA) { + result = std::make_shared(ComboAddress(content)); + } + else if (type == QType::CNAME) { + result = std::make_shared(DNSName(content)); + } + else if (type == QType::OPT) { + result = std::make_shared(); + } + else { + result = DNSRecordContent::mastermake(type, QClass::IN, content); + } + + return result; +} + +static inline void addRecordToList(std::vector& records, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=3600) +{ + DNSRecord rec; + rec.d_place = place; + rec.d_name = name; + rec.d_type = type; + rec.d_ttl = ttl; + + rec.d_content = getRecordContent(type, content); + + records.push_back(rec); +} diff --git a/pdns/test-digests_hh.cc b/pdns/test-digests_hh.cc new file mode 100644 index 0000000..c061a8c --- /dev/null +++ b/pdns/test-digests_hh.cc @@ -0,0 +1,32 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "digests.hh" +#include "misc.hh" + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(test_digests_hh) + +BOOST_AUTO_TEST_CASE(test_pdns_md5sum) +{ + std::string result = "a3 24 8c e3 1a 88 a6 40 e6 30 73 98 57 6d 06 9e "; + std::string sum = pdns_md5sum("a quick brown fox jumped over the lazy dog"); + + BOOST_CHECK_EQUAL(makeHexDump(sum), result); +} + +BOOST_AUTO_TEST_CASE(test_pdns_sha1sum) +{ + std::string result = "b9 37 10 0d c9 57 b3 86 d9 cb 77 fc 90 c0 18 22 fd eb 6e 7f "; + std::string sum = pdns_sha1sum("a quick brown fox jumped over the lazy dog"); + + BOOST_CHECK_EQUAL(makeHexDump(sum), result); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-distributor_hh.cc b/pdns/test-distributor_hh.cc new file mode 100644 index 0000000..5f12ecd --- /dev/null +++ b/pdns/test-distributor_hh.cc @@ -0,0 +1,163 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include "distributor.hh" +#include "dnspacket.hh" +#include "namespaces.hh" + +BOOST_AUTO_TEST_SUITE(test_distributor_hh) + +struct Question +{ + int q; + DTime d_dt; + DNSName qdomain; + QType qtype; + DNSPacket* replyPacket() + { + return new DNSPacket(false); + } +}; + +struct Backend +{ + DNSPacket* question(Question*) + { + return new DNSPacket(true); + } +}; + +static std::atomic g_receivedAnswers; +static void report(DNSPacket* A) +{ + delete A; + g_receivedAnswers++; +} + +BOOST_AUTO_TEST_CASE(test_distributor_basic) { + ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0"; + ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000"; + ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; + S.declare("servfail-packets","Number of times a server-failed packet was sent out"); + S.declare("timedout-packets", "timedout-packets"); + + auto d=Distributor::Create(2); + + int n; + for(n=0; n < 100; ++n) { + auto q = new Question(); + q->d_dt.set(); + d->question(q, report); + } + sleep(1); + BOOST_CHECK_EQUAL(n, g_receivedAnswers); +}; + +struct BackendSlow +{ + DNSPacket* question(Question*) + { + sleep(1); + return new DNSPacket(true); + } +}; + +static std::atomic g_receivedAnswers1; +static void report1(DNSPacket* A) +{ + delete A; + g_receivedAnswers1++; +} + +BOOST_AUTO_TEST_CASE(test_distributor_queue) { + ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0"; + ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="1000"; + ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; + S.declare("servfail-packets","Number of times a server-failed packet was sent out"); + S.declare("timedout-packets", "timedout-packets"); + + auto d=Distributor::Create(2); + + BOOST_CHECK_EXCEPTION( { + int n; + // bound should be higher than max-queue-length + for(n=0; n < 2000; ++n) { + auto q = new Question(); + q->d_dt.set(); + d->question(q, report1); + } + }, DistributorFatal, [](DistributorFatal) { return true; }); +}; + +struct BackendDies +{ + BackendDies() + { + d_ourcount=s_count++; + } + ~BackendDies() + { + } + DNSPacket* question(Question* q) + { + // cout<<"Q: "<qdomain< s_count; + int d_count{0}; + int d_ourcount; +}; + +std::atomic BackendDies::s_count; + +std::atomic g_receivedAnswers2; + +static void report2(DNSPacket* A) +{ + delete A; + g_receivedAnswers2++; +} + + +BOOST_AUTO_TEST_CASE(test_distributor_dies) { + ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0"; + ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000"; + ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; + S.declare("servfail-packets","Number of times a server-failed packet was sent out"); + S.declare("timedout-packets", "timedout-packets"); + + auto d=Distributor::Create(10); + + try { + for(int n=0; n < 100; ++n) { + auto q = new Question(); + q->d_dt.set(); + q->qdomain=DNSName(std::to_string(n)); + q->qtype = QType(QType::A); + d->question(q, report2); + } + + sleep(1); + cerr<<"Queued: "<getQueueSize()< 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 8) || !__GNUC__ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include +#include +#include + +#include "arguments.hh" +#include "dns_random.hh" +#include "namespaces.hh" + + +using namespace boost; +using namespace boost::accumulators; + +typedef accumulator_set< + double + , stats + > acc_t; + + + +BOOST_AUTO_TEST_SUITE(test_dns_random_hh) + +BOOST_AUTO_TEST_CASE(test_dns_random_auto_average) { + + ::arg().set("rng")="auto"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} + +BOOST_AUTO_TEST_CASE(test_dns_random_urandom_average) { + + ::arg().set("rng")="urandom"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} + +BOOST_AUTO_TEST_CASE(test_dns_random_garbage) { + + ::arg().set("rng")="garbage"; + ::arg().set("entropy-source")="/dev/urandom"; + + BOOST_CHECK_THROW(dns_random_init("", true), std::runtime_error); +} + +#if defined(HAVE_GETRANDOM) +BOOST_AUTO_TEST_CASE(test_dns_random_getrandom_average) { + + ::arg().set("rng")="getrandom"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_ARC4RANDOM) +BOOST_AUTO_TEST_CASE(test_dns_random_getrandom_average) { + + ::arg().set("rng")="arc4random"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_RANDOMBYTES_STIR) +BOOST_AUTO_TEST_CASE(test_dns_random_sodium_average) { + + ::arg().set("rng")="sodium"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_RAND_BYTES) +BOOST_AUTO_TEST_CASE(test_dns_random_openssl_average) { + + ::arg().set("rng")="openssl"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + +#if defined(HAVE_KISS_RNG) +BOOST_AUTO_TEST_CASE(test_dns_random_kiss_average) { + + ::arg().set("rng")="kiss"; + ::arg().set("entropy-source")="/dev/urandom"; + + dns_random_init("", true); + + acc_t acc; + + for(unsigned int n=0; n < 100000; ++n) { + acc(dns_random(100000)/100000.0); + } + BOOST_CHECK_CLOSE(0.5, median(acc), 2.0); // within 2% + BOOST_CHECK_CLOSE(0.5, mean(acc), 2.0); + + // please add covariance tests, chi-square, Kolmogorov-Smirnov +} +#endif + + +BOOST_AUTO_TEST_SUITE_END() + +#endif diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc new file mode 100644 index 0000000..833f2fc --- /dev/null +++ b/pdns/test-dnsname_cc.cc @@ -0,0 +1,967 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#include +#include +#include +#include +#include "dnsname.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include +using namespace boost; +using std::string; + +BOOST_AUTO_TEST_SUITE(test_dnsname_cc) + +BOOST_AUTO_TEST_CASE(test_basic) { + DNSName aroot("a.root-servers.net"), broot("b.root-servers.net"); + BOOST_CHECK(aroot < broot); + BOOST_CHECK(!(broot < aroot)); + BOOST_CHECK(aroot.canonCompare(broot)); + BOOST_CHECK(!broot.canonCompare(aroot)); + + + string before("www.ds9a.nl."); + DNSName b(before); + BOOST_CHECK_EQUAL(b.getRawLabels().size(), 3); + string after(b.toString()); + BOOST_CHECK_EQUAL(before, after); + + DNSName jpmens("ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test."); + + BOOST_CHECK_EQUAL(jpmens.toString(), "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test."); + + DNSName wwwds9anl("www.ds9a.nl."); + DNSName wwwds9anl1("www.ds9a\002nl."); + DNSName nl("nl."); + BOOST_CHECK(wwwds9anl.isPartOf(nl)); + BOOST_CHECK(!wwwds9anl1.isPartOf(nl)); + BOOST_CHECK(wwwds9anl.isPartOf(wwwds9anl)); + + BOOST_CHECK(!nl.isPartOf(wwwds9anl)); + + BOOST_CHECK(wwwds9anl == wwwds9anl); + + BOOST_CHECK(DNSName("wWw.ds9A.Nl.") == DNSName("www.ds9a.nl.")); + BOOST_CHECK(DNSName("www.ds9a.nl.") == DNSName("www.ds9a.nl.")); + + BOOST_CHECK(DNSName("www.ds9a.nl.").toString() == "www.ds9a.nl."); + + + { // Check root vs empty + DNSName name("."); // root + DNSName parent; // empty + BOOST_CHECK(name != parent); + } + + { // Check name part of root + DNSName name("a."); + DNSName parent("."); + BOOST_CHECK(name.isPartOf(parent)); + } + + { // Label boundary + DNSName name("a\002bb."); + DNSName parent("bb."); + BOOST_CHECK(!name.isPartOf(parent)); + } + + { // Multi label parent + DNSName name("a.bb.ccc.dddd."); + DNSName parent("ccc.dddd."); + BOOST_CHECK(name.isPartOf(parent)); + } + + { // Last char diff + DNSName name("a.bb.ccc.dddd."); + DNSName parent("ccc.dddx."); + BOOST_CHECK(!name.isPartOf(parent)); + } + + { // Equal length identical + DNSName name("aaaa.bbb.cc.d."); + DNSName parent("aaaa.bbb.cc.d."); + BOOST_CHECK(name.isPartOf(parent)); + } + + { // Equal length first char diff + DNSName name("xaaa.bbb.cc.d."); + DNSName parent("aaaa.bbb.cc.d."); + BOOST_CHECK(!name.isPartOf(parent)); + } + + { // Make relative + DNSName name("aaaa.bbb.cc.d."); + DNSName parent("cc.d."); + BOOST_CHECK_EQUAL( name.makeRelative(parent), DNSName("aaaa.bbb.")); + } + + { // Labelreverse + DNSName name("aaaa.bbb.cc.d."); + BOOST_CHECK( name.labelReverse() == DNSName("d.cc.bbb.aaaa.")); + } + + { // empty() empty + DNSName name; + BOOST_CHECK(name.empty()); + } + + { // empty() root + DNSName name("."); + BOOST_CHECK(!name.empty()); + + DNSName rootnodot(""); + BOOST_CHECK_EQUAL(name, rootnodot); + + string empty; + DNSName rootnodot2(empty); + BOOST_CHECK_EQUAL(rootnodot2, name); + } + + DNSName left("ds9a.nl."); + left.prependRawLabel("www"); + BOOST_CHECK( left == DNSName("WwW.Ds9A.Nl.")); + + left.appendRawLabel("com"); + + BOOST_CHECK( left == DNSName("WwW.Ds9A.Nl.com.")); + + DNSName unset; + + unset.appendRawLabel("www"); + unset.appendRawLabel("powerdns.com"); + unset.appendRawLabel("com"); + + BOOST_CHECK_EQUAL(unset.toString(), "www.powerdns\\.com.com."); + + DNSName rfc4343_2_1("~!.example."); + DNSName rfc4343_2_2(R"(Donald\032E\.\032Eastlake\0323rd.example.)"); + DNSName example("example."); + BOOST_CHECK(rfc4343_2_1.isPartOf(example)); + BOOST_CHECK(rfc4343_2_2.isPartOf(example)); + BOOST_CHECK_EQUAL(rfc4343_2_1.toString(), "~!.example."); + + auto labels=rfc4343_2_2.getRawLabels(); + BOOST_CHECK_EQUAL(*labels.begin(), "Donald E. Eastlake 3rd"); + BOOST_CHECK_EQUAL(*labels.rbegin(), "example"); + BOOST_CHECK_EQUAL(labels.size(), 2); + + DNSName build; + build.appendRawLabel("Donald E. Eastlake 3rd"); + build.appendRawLabel("example"); + BOOST_CHECK_EQUAL(build.toString(), R"(Donald\032E\.\032Eastlake\0323rd.example.)"); + BOOST_CHECK_THROW(DNSName broken("bert..hubert."), std::runtime_error); + + DNSName n; + n.appendRawLabel("powerdns.dnsmaster"); + n.appendRawLabel("powerdns"); + n.appendRawLabel("com"); + + BOOST_CHECK_EQUAL(n.toString(), "powerdns\\.dnsmaster.powerdns.com."); + + // BOOST_CHECK(DNSName().toString() != "."); + + DNSName p; + string label("power"); + label.append(1, (char)0); + label.append("dns"); + p.appendRawLabel(label); + p.appendRawLabel("com"); + + BOOST_CHECK_EQUAL(p.toString(), "power\\000dns.com."); +} + +BOOST_AUTO_TEST_CASE(test_trim) { + DNSName w("www.powerdns.com."); + BOOST_CHECK_EQUAL(w.countLabels(), 3); + w.trimToLabels(2); + BOOST_CHECK_EQUAL(w.toString(), "powerdns.com."); + DNSName w2("powerdns.com."); + BOOST_CHECK(w==w2); + + DNSName root("."); + BOOST_CHECK_EQUAL(root.countLabels(), 0); +} + +BOOST_AUTO_TEST_CASE(test_toolong) { + + BOOST_CHECK_THROW(DNSName w("1234567890123456789012345678901234567890123456789012345678901234567890.com."), std::range_error); + + BOOST_CHECK_THROW(DNSName w("12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.234567890.789012345678901.234567890.234567890.789012345678901.234567890.234567890.com."), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_dnsstrings) { + DNSName w("www.powerdns.com."); + BOOST_CHECK_EQUAL(w.toDNSString(), string("\003www\010powerdns\003com\000", 18)); +} + +BOOST_AUTO_TEST_CASE(test_empty) { + DNSName empty; + BOOST_CHECK_THROW(empty.toString(), std::out_of_range); + BOOST_CHECK_THROW(empty.toStringNoDot(), std::out_of_range); + BOOST_CHECK_THROW(empty.toDNSString(), std::out_of_range); + BOOST_CHECK(empty.empty()); + BOOST_CHECK(!empty.isRoot()); + BOOST_CHECK(!empty.isWildcard()); + BOOST_CHECK_EQUAL(empty, empty); + BOOST_CHECK(!(empty < empty)); + + DNSName root("."); + BOOST_CHECK(empty < root); + + BOOST_CHECK_THROW(empty.isPartOf(root), std::out_of_range); + BOOST_CHECK_THROW(root.isPartOf(empty), std::out_of_range); +} + +BOOST_AUTO_TEST_CASE(test_specials) { + DNSName root("."); + + BOOST_CHECK(root.isRoot()); + BOOST_CHECK(root != DNSName()); + + DNSName wcard("*.powerdns.com"); + BOOST_CHECK(wcard.isWildcard()); + + DNSName notwcard("www.powerdns.com"); + BOOST_CHECK(!notwcard.isWildcard()); +} + + +BOOST_AUTO_TEST_CASE(test_chopping) { + DNSName w("www.powerdns.com."); + BOOST_CHECK_EQUAL(w.toString(), "www.powerdns.com."); + BOOST_CHECK(w.chopOff()); + BOOST_CHECK_EQUAL(w.toString(), "powerdns.com."); + BOOST_CHECK(w.chopOff()); + BOOST_CHECK_EQUAL(w.toString(), "com."); + BOOST_CHECK(w.chopOff()); + BOOST_CHECK_EQUAL(w.toString(), "."); + BOOST_CHECK(!w.chopOff()); + BOOST_CHECK(!w.chopOff()); + + w.prependRawLabel("net"); + w.prependRawLabel("root-servers"); + w.prependRawLabel("a"); + BOOST_CHECK_EQUAL(w.toString(), "a.root-servers.net."); +} + +BOOST_AUTO_TEST_CASE(test_Append) { + DNSName dn("www."), powerdns("powerdns.com."); + DNSName tot=dn+powerdns; + + BOOST_CHECK_EQUAL(tot.toString(), "www.powerdns.com."); + BOOST_CHECK(tot == DNSName("www.powerdns.com.")); + + dn+=powerdns; + + BOOST_CHECK(dn == DNSName("www.powerdns.com.")); +} + +BOOST_AUTO_TEST_CASE(test_packetCompress) { + reportBasicTypes(); + vector packet; + DNSPacketWriter dpw(packet, DNSName("www.ds9a.nl."), QType::AAAA); + dpw.startRecord(DNSName("ds9a.nl"), QType::SOA); + SOARecordContent src("ns1.powerdns.nl admin.powerdns.nl 1 2 3 4 5"); + src.toPacket(dpw); + AAAARecordContent aaaa("::1"); + dpw.startRecord(DNSName("www.dS9A.nl"), QType::AAAA); + aaaa.toPacket(dpw); + dpw.startRecord(DNSName("www.ds9A.nl"), QType::AAAA); + aaaa.toPacket(dpw); + dpw.startRecord(DNSName("www.dS9a.nl"), QType::AAAA); + aaaa.toPacket(dpw); + dpw.startRecord(DNSName("www2.DS9a.nl"), QType::AAAA); + aaaa.toPacket(dpw); + dpw.startRecord(DNSName("www2.dS9a.nl"), QType::AAAA); + aaaa.toPacket(dpw); + dpw.commit(); + string str((const char*)&packet[0], (const char*)&packet[0] + packet.size()); + size_t pos = 0; + int count=0; + while((pos = str.find("ds9a", pos)) != string::npos) { + ++pos; + ++count; + } + BOOST_CHECK_EQUAL(count, 1); + pos = 0; + count=0; + while((pos = str.find("powerdns", pos)) != string::npos) { + ++pos; + ++count; + } + BOOST_CHECK_EQUAL(count, 1); + +} + +BOOST_AUTO_TEST_CASE(test_packetCompressLong) { + reportBasicTypes(); + vector packet; + DNSName loopback("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"); + DNSPacketWriter dpw(packet, loopback, QType::PTR); + + dpw.startRecord(loopback, QType::PTR); + PTRRecordContent prc(DNSName("localhost")); + prc.toPacket(dpw); + dpw.commit(); + DNSName roundtrip((char*)&packet[0], packet.size(), 12, false); + BOOST_CHECK_EQUAL(loopback,roundtrip); + + packet.clear(); + DNSName longer("1.2.3.4.5.6.7.8.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"); + DNSPacketWriter dpw2(packet, longer, QType::PTR); + + dpw2.startRecord(DNSName("a.b.c.d.e")+longer, QType::PTR); + PTRRecordContent prc2(DNSName("localhost")); + prc2.toPacket(dpw2); + dpw2.commit(); + +} + + + + +BOOST_AUTO_TEST_CASE(test_PacketParse) { + vector packet; + reportBasicTypes(); + DNSName root("."); + DNSPacketWriter dpw1(packet, g_rootdnsname, QType::AAAA); + DNSName p((char*)&packet[0], packet.size(), 12, false); + BOOST_CHECK_EQUAL(p, root); + unsigned char* buffer=&packet[0]; + /* set invalid label len: + - packet.size() == 17 (sizeof(dnsheader) + 1 + 2 + 2) + - label len < packet.size() but + - offset is 12, label len of 15 should be rejected + because offset + 15 >= packet.size() + */ + buffer[sizeof(dnsheader)] = 15; + BOOST_CHECK_THROW(DNSName((char*)&packet[0], packet.size(), 12, false), std::range_error); +} + + +BOOST_AUTO_TEST_CASE(test_hash) { + DNSName a("wwW.Ds9A.Nl"), b("www.ds9a.nl"); + BOOST_CHECK_EQUAL(a.hash(), b.hash()); + + vector counts(1500); + + for(unsigned int n=0; n < 100000; ++n) { + DNSName dn(std::to_string(n)+"."+std::to_string(n*2)+"ds9a.nl"); + DNSName dn2(std::to_string(n)+"."+std::to_string(n*2)+"Ds9a.nL"); + BOOST_CHECK_EQUAL(dn.hash(), dn2.hash()); + counts[dn.hash() % counts.size()]++; + } + + double sum = std::accumulate(std::begin(counts), std::end(counts), 0.0); + double m = sum / counts.size(); + + double accum = 0.0; + std::for_each (std::begin(counts), std::end(counts), [&](const double d) { + accum += (d - m) * (d - m); + }); + + double stdev = sqrt(accum / (counts.size()-1)); + BOOST_CHECK(stdev < 10); +} + +BOOST_AUTO_TEST_CASE(test_hashContainer) { + std::unordered_set s; + s.insert(DNSName("www.powerdns.com")); + BOOST_CHECK(s.count(DNSName("WwW.PoWerDNS.CoM"))); + BOOST_CHECK_EQUAL(s.size(), 1); + s.insert(DNSName("www.POWERDNS.com")); + BOOST_CHECK_EQUAL(s.size(), 1); + s.insert(DNSName("www2.POWERDNS.com")); + BOOST_CHECK_EQUAL(s.size(), 2); + + s.clear(); + unsigned int n=0; + for(; n < 100000; ++n) + s.insert(DNSName(std::to_string(n)+".test.nl")); + BOOST_CHECK_EQUAL(s.size(), n); + +} + + +BOOST_AUTO_TEST_CASE(test_QuestionHash) { + vector packet; + reportBasicTypes(); + DNSPacketWriter dpw1(packet, DNSName("www.ds9a.nl."), QType::AAAA); + + auto hash1=hashQuestion((char*)&packet[0], packet.size(), 0); + DNSPacketWriter dpw2(packet, DNSName("wWw.Ds9A.nL."), QType::AAAA); + auto hash2=hashQuestion((char*)&packet[0], packet.size(), 0); + BOOST_CHECK_EQUAL(hash1, hash2); + + vector counts(1500); + + for(unsigned int n=0; n < 100000; ++n) { + packet.clear(); + DNSPacketWriter dpw3(packet, DNSName(std::to_string(n)+"."+std::to_string(n*2)+"."), QType::AAAA); + counts[hashQuestion((char*)&packet[0], packet.size(), 0) % counts.size()]++; + } + + double sum = std::accumulate(std::begin(counts), std::end(counts), 0.0); + double m = sum / counts.size(); + + double accum = 0.0; + std::for_each (std::begin(counts), std::end(counts), [&](const double d) { + accum += (d - m) * (d - m); + }); + + double stdev = sqrt(accum / (counts.size()-1)); + BOOST_CHECK(stdev < 10); +} + + +BOOST_AUTO_TEST_CASE(test_packetParse) { + vector packet; + reportBasicTypes(); + DNSPacketWriter dpw(packet, DNSName("www.ds9a.nl."), QType::AAAA); + + uint16_t qtype, qclass; + DNSName dn((char*)&packet[0], packet.size(), 12, false, &qtype, &qclass); + BOOST_CHECK_EQUAL(dn.toString(), "www.ds9a.nl."); + BOOST_CHECK(qtype == QType::AAAA); + BOOST_CHECK_EQUAL(qclass, 1); + + dpw.startRecord(DNSName("ds9a.nl."), DNSRecordContent::TypeToNumber("NS")); + NSRecordContent nrc("ns1.powerdns.com"); + nrc.toPacket(dpw); + + dpw.commit(); + + /* packet now looks like this: + 012345678901 12 bytes of header + 3www4ds9a2nl0 13 bytes of name + 0001 0001 4 bytes of qtype and qclass + answername 2 bytes + 0001 0001 4 bytes of qtype and class + 0000 0000 4 bytes of TTL + 0000 2 bytes of content length + content name */ + + DNSName dn2((char*)&packet[0], packet.size(), 12+13+4, true, &qtype, &qclass); + BOOST_CHECK_EQUAL(dn2.toString(), "ds9a.nl."); + BOOST_CHECK(qtype == QType::NS); + BOOST_CHECK_EQUAL(qclass, 1); + + DNSName dn3((char*)&packet[0], packet.size(), 12+13+4+2 + 4 + 4 + 2, true); + BOOST_CHECK_EQUAL(dn3.toString(), "ns1.powerdns.com."); + try { + DNSName dn4((char*)&packet[0], packet.size(), 12+13+4, false); // compressed, should fail + BOOST_CHECK(0); + } + catch(...){} +} + +BOOST_AUTO_TEST_CASE(test_escaping) { + DNSName n; + string label; + + for(int i = 0; i < 250; ++i) { + if(!((i+1)%63)) { + n.appendRawLabel(label); + label.clear(); + } + label.append(1,(char)i); + } + if(!label.empty()) + n.appendRawLabel(label); + + DNSName n2(n.toString()); + BOOST_CHECK(n==n2); +} + +BOOST_AUTO_TEST_CASE(test_suffixmatch) { + SuffixMatchNode smn; + DNSName ezdns("ezdns.it."); + smn.add(ezdns.getRawLabels()); + + smn.add(DNSName("org.").getRawLabels()); + + DNSName wwwpowerdnscom("www.powerdns.com."); + DNSName wwwezdnsit("www.ezdns.it."); + BOOST_CHECK(smn.check(wwwezdnsit)); + BOOST_CHECK(!smn.check(wwwpowerdnscom)); + + BOOST_CHECK(smn.check(DNSName("www.powerdns.org."))); + BOOST_CHECK(smn.check(DNSName("www.powerdns.oRG."))); + + smn.add(DNSName("news.bbc.co.uk.")); + BOOST_CHECK(smn.check(DNSName("news.bbc.co.uk."))); + BOOST_CHECK(smn.check(DNSName("www.news.bbc.co.uk."))); + BOOST_CHECK(smn.check(DNSName("www.www.www.www.www.news.bbc.co.uk."))); + BOOST_CHECK(!smn.check(DNSName("images.bbc.co.uk."))); + + BOOST_CHECK(!smn.check(DNSName("www.news.gov.uk."))); + + smn.add(g_rootdnsname); // block the root + BOOST_CHECK(smn.check(DNSName("a.root-servers.net."))); + + DNSName examplenet("example.net."); + DNSName net("net."); + smn.add(examplenet); + smn.add(net); + BOOST_CHECK(smn.check(examplenet)); + BOOST_CHECK(smn.check(net)); + + // Remove .net and check that example.net still exists + smn.remove(net); + BOOST_CHECK_EQUAL(smn.check(net), false); + BOOST_CHECK(smn.check(examplenet)); +} + +BOOST_AUTO_TEST_CASE(test_suffixmatch_tree) { + SuffixMatchTree smt; + DNSName ezdns("ezdns.it."); + smt.add(ezdns, ezdns); + + smt.add(DNSName("org.").getRawLabels(), DNSName("org.")); + + DNSName wwwpowerdnscom("www.powerdns.com."); + DNSName wwwezdnsit("www.ezdns.it."); + BOOST_REQUIRE(smt.lookup(wwwezdnsit)); + BOOST_CHECK_EQUAL(*smt.lookup(wwwezdnsit), ezdns); + BOOST_CHECK(smt.lookup(wwwpowerdnscom) == nullptr); + + BOOST_REQUIRE(smt.lookup(DNSName("www.powerdns.org."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.powerdns.org.")), DNSName("org.")); + BOOST_REQUIRE(smt.lookup(DNSName("www.powerdns.oRG."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.powerdns.oRG.")), DNSName("org.")); + + smt.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk.")); + BOOST_REQUIRE(smt.lookup(DNSName("news.bbc.co.uk."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("news.bbc.co.uk.")), DNSName("news.bbc.co.uk.")); + BOOST_REQUIRE(smt.lookup(DNSName("www.news.bbc.co.uk."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk.")); + BOOST_REQUIRE(smt.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk.")); + BOOST_CHECK(smt.lookup(DNSName("images.bbc.co.uk.")) == nullptr); + BOOST_CHECK(smt.lookup(DNSName("www.news.gov.uk.")) == nullptr); + + smt.add(g_rootdnsname, g_rootdnsname); // block the root + BOOST_REQUIRE(smt.lookup(DNSName("a.root-servers.net."))); + BOOST_CHECK_EQUAL(*smt.lookup(DNSName("a.root-servers.net.")), g_rootdnsname); + + DNSName apowerdnscom("a.powerdns.com."); + DNSName bpowerdnscom("b.powerdns.com."); + smt.add(apowerdnscom, apowerdnscom); + smt.add(bpowerdnscom, bpowerdnscom); + BOOST_REQUIRE(smt.lookup(apowerdnscom)); + BOOST_CHECK_EQUAL(*smt.lookup(apowerdnscom), apowerdnscom); + BOOST_REQUIRE(smt.lookup(bpowerdnscom)); + BOOST_CHECK_EQUAL(*smt.lookup(bpowerdnscom), bpowerdnscom); + + DNSName examplenet("example.net."); + DNSName net("net."); + smt.add(examplenet, examplenet); + smt.add(net, net); + BOOST_REQUIRE(smt.lookup(examplenet)); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet); + BOOST_REQUIRE(smt.lookup(net)); + BOOST_CHECK_EQUAL(*smt.lookup(net), net); + + // Remove .net, and check that example.net remains + smt.remove(net); + BOOST_CHECK(smt.lookup(net) == nullptr); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet); + + smt = SuffixMatchTree(); + smt.add(examplenet, examplenet); + smt.add(net, net); + smt.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk.")); + smt.add(apowerdnscom, apowerdnscom); + + smt.remove(DNSName("not-such-entry.news.bbc.co.uk.")); + BOOST_REQUIRE(smt.lookup(DNSName("news.bbc.co.uk."))); + smt.remove(DNSName("news.bbc.co.uk.")); + BOOST_CHECK(smt.lookup(DNSName("news.bbc.co.uk.")) == nullptr); + + smt.remove(net); + BOOST_REQUIRE(smt.lookup(examplenet)); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet); + BOOST_CHECK(smt.lookup(net) == nullptr); + + smt.remove(examplenet); + BOOST_CHECK(smt.lookup(net) == nullptr); + BOOST_CHECK(smt.lookup(examplenet) == nullptr); + + smt.add(examplenet, examplenet); + smt.add(net, net); + BOOST_REQUIRE(smt.lookup(examplenet)); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet); + BOOST_REQUIRE(smt.lookup(net)); + BOOST_CHECK_EQUAL(*smt.lookup(net), net); + + smt.remove(examplenet); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), net); + BOOST_CHECK_EQUAL(*smt.lookup(net), net); + smt.remove(examplenet); + BOOST_CHECK_EQUAL(*smt.lookup(examplenet), net); + BOOST_CHECK_EQUAL(*smt.lookup(net), net); + smt.remove(net); + BOOST_CHECK(smt.lookup(net) == nullptr); + BOOST_CHECK(smt.lookup(examplenet) == nullptr); + smt.remove(net); + + size_t count = 0; + smt.visit([apowerdnscom, &count](const SuffixMatchTree& smt) { + count++; + BOOST_CHECK_EQUAL(smt.d_value, apowerdnscom); + }); + BOOST_CHECK_EQUAL(count, 1); + + BOOST_CHECK_EQUAL(*smt.lookup(apowerdnscom), apowerdnscom); + smt.remove(apowerdnscom); + BOOST_CHECK(smt.lookup(apowerdnscom) == nullptr); + + count = 0; + smt.visit([&count](const SuffixMatchTree& smt) { + count++; + }); + BOOST_CHECK_EQUAL(count, 0); +} + + +BOOST_AUTO_TEST_CASE(test_concat) { + DNSName first("www."), second("powerdns.com."); + BOOST_CHECK_EQUAL((first+second).toString(), "www.powerdns.com."); +} + +BOOST_AUTO_TEST_CASE(test_compare_naive) { + BOOST_CHECK(DNSName("abc.com.") < DNSName("zdf.com.")); + BOOST_CHECK(DNSName("Abc.com.") < DNSName("zdf.com.")); + BOOST_CHECK(DNSName("Abc.com.") < DNSName("Zdf.com.")); + BOOST_CHECK(DNSName("abc.com.") < DNSName("Zdf.com.")); +} + +BOOST_AUTO_TEST_CASE(test_compare_empty) { + DNSName a, b; + BOOST_CHECK(!(a vec; + for(const std::string& b : {"bert.com.", "alpha.nl.", "articles.xxx.", + "Aleph1.powerdns.com.", "ZOMG.powerdns.com.", "aaa.XXX.", "yyy.XXX.", + "test.powerdns.com.", "\\128.com"}) { + vec.push_back(DNSName(b)); + } + sort(vec.begin(), vec.end(), CanonDNSNameCompare()); + // for(const auto& v : vec) + // cerr<<'"'< right; + for(const auto& b: {"bert.com.", "Aleph1.powerdns.com.", + "test.powerdns.com.", + "ZOMG.powerdns.com.", + "\\128.com.", + "alpha.nl.", + "aaa.XXX.", + "articles.xxx.", + "yyy.XXX."}) + right.push_back(DNSName(b)); + + + BOOST_CHECK(vec==right); +} + + +BOOST_AUTO_TEST_CASE(test_empty_label) { // empty label + + { // append + DNSName dn("www."); + BOOST_CHECK_THROW(dn.appendRawLabel(""), std::range_error); + } + + { // prepend + DNSName dn("www."); + BOOST_CHECK_THROW(dn.prependRawLabel(""), std::range_error); + } +} + +BOOST_AUTO_TEST_CASE(test_label_length_max) { // 63 char label + + string label("123456789012345678901234567890123456789012345678901234567890123"); + + { // append + DNSName dn("www."); + dn.appendRawLabel(label); + BOOST_CHECK_EQUAL(dn.toString(), "www." + label + "."); + } + + { // prepend + DNSName dn("www."); + dn.prependRawLabel(label); + BOOST_CHECK_EQUAL(dn.toString(), label + ".www."); + } +} + +BOOST_AUTO_TEST_CASE(test_label_length_too_long) { // 64 char label + + string label("1234567890123456789012345678901234567890123456789012345678901234"); + + { // append + DNSName dn("www."); + BOOST_CHECK_THROW(dn.appendRawLabel(label), std::range_error); + } + + { // prepend + DNSName dn("www."); + BOOST_CHECK_THROW(dn.prependRawLabel(label), std::range_error); + } +} + +BOOST_AUTO_TEST_CASE(test_name_length_max) { // 255 char name + + string name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789."); + string label("123"); + + { // append + DNSName dn(name); + dn.appendRawLabel(label); + BOOST_CHECK_EQUAL(dn.toString().size(), 254); + } + + { // prepend + DNSName dn(name); + dn.prependRawLabel(label); + BOOST_CHECK_EQUAL(dn.toString().size(), 254); + } + + { // concat + DNSName dn(name); + + dn += DNSName(label + "."); + BOOST_CHECK_EQUAL(dn.toString().size(), 254); + } +} + +BOOST_AUTO_TEST_CASE(test_name_length_too_long) { // 256 char name + + string name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789."); + string label("1234"); + + { // append + DNSName dn(name); + BOOST_CHECK_THROW(dn.appendRawLabel(label), std::range_error); + } + + { // prepend + DNSName dn(name); + BOOST_CHECK_THROW(dn.prependRawLabel(label), std::range_error); + } + + { // concat + DNSName dn(name); + BOOST_CHECK_THROW(dn += DNSName(label + "."), std::range_error); + } +} + + +BOOST_AUTO_TEST_CASE(test_invalid_label_length) { // Invalid label length in qname + + string name("\x02""ns\x07""example\x04""com\x00", 16); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_compression) { // Compression test + + string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05", 21); + + DNSName dn(name.c_str(), name.size(), 15, true); + BOOST_CHECK_EQUAL(dn.toString(), "www.example.com."); +} + +BOOST_AUTO_TEST_CASE(test_compression_qtype_qclass) { // Compression test with QClass and QType extraction + + uint16_t qtype = 0; + uint16_t qclass = 0; + + { + string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""\x01", 25); + DNSName dn(name.c_str(), name.size(), 15, true, &qtype, &qclass); + BOOST_CHECK_EQUAL(dn.toString(), "www.example.com."); + BOOST_CHECK_EQUAL(qtype, 1); + BOOST_CHECK_EQUAL(qclass, 1); + } + + { + /* same but this time we are one byte short for the qclass */ + string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""", 24); + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true, &qtype, &qclass), std::range_error); + } + + { + /* this time with a compression pointer such as (labellen << 8) != 0, see #4718 */ + string name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00""\x01", 25); + name.insert(0, 256, '0'); + + DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass); + BOOST_CHECK_EQUAL(dn.toString(), "www.example.com."); + BOOST_CHECK_EQUAL(qtype, 1); + BOOST_CHECK_EQUAL(qclass, 1); + } + + { + /* same but this time we are one byte short for the qclass */ + string name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00", 24); + name.insert(0, 256, '0'); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass), std::range_error); + } +} + +BOOST_AUTO_TEST_CASE(test_compression_single_bit_set) { // first 2 bits as 10 or 01, not 11 + + // first 2 bits: 10 + { + string name("\x03""com\x00""\x07""example\x80""\x00""\x03""www\x80""\x05", 21); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error); + } + + // first 2 bits: 01 + { + string name("\x03""com\x00""\x07""example\x40""\x00""\x03""www\x40""\x05", 21); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error); + } + +} + +BOOST_AUTO_TEST_CASE(test_pointer_pointer_root) { // Pointer to pointer to root + + string name("\x00""\xc0""\x00""\x03""com\xc0""\x01",9); + + DNSName dn(name.c_str(), name.size(), 3, true); + BOOST_CHECK_EQUAL(dn.toString(), "com."); +} + +BOOST_AUTO_TEST_CASE(test_bad_compression_pointer) { // Pointing beyond packet boundary + + std::string name("\x03""com\x00""\x07""example\xc0""\x11""xc0""\x00", 17); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.length(), 5, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_compression_loop) { // Compression loop (add one label) + + std::string name("\x03""www\xc0""\x00", 6); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.length(), 0, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_compression_loop1) { // Compression loop (pointer loop) + + string name("\xc0""\x00", 2); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_compression_loop2) { // Compression loop (deep recursion) + + int i; + string name("\x00\xc0\x00", 3); + for (i=0; i<98; ++i) { + name.append( 1, ((i >> 7) & 0xff) | 0xc0); + name.append( 1, ((i << 1) & 0xff) | 0x01); + } + BOOST_CHECK_NO_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true)); + + ++i; + name.append( 1, ((i >> 7) & 0xff) | 0xc0); + name.append( 1, ((i << 1) & 0xff) | 0x01); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_wirelength) { // Testing if we get the correct value from the wirelength function + DNSName name("www.powerdns.com"); + BOOST_CHECK_EQUAL(name.wirelength(), 18); + + DNSName sname("powerdns.com"); + sname.prependRawLabel(string("ww\x00""w", 4)); + BOOST_CHECK_EQUAL(sname.wirelength(), 19); + + sname = DNSName("powerdns.com"); + sname.prependRawLabel(string("www\x00", 4)); + BOOST_CHECK_EQUAL(sname.wirelength(), 19); +} + +BOOST_AUTO_TEST_CASE(test_getrawlabel) { + DNSName name("a.bb.ccc.dddd."); + BOOST_CHECK_EQUAL(name.getRawLabel(0), "a"); + BOOST_CHECK_EQUAL(name.getRawLabel(1), "bb"); + BOOST_CHECK_EQUAL(name.getRawLabel(2), "ccc"); + BOOST_CHECK_EQUAL(name.getRawLabel(3), "dddd"); + BOOST_CHECK_THROW(name.getRawLabel(name.countLabels()), std::out_of_range); +} + +BOOST_AUTO_TEST_CASE(test_getlastlabel) { + DNSName name("www.powerdns.com"); + DNSName ans = name.getLastLabel(); + + // Check the const-ness + BOOST_CHECK_EQUAL(name, DNSName("www.powerdns.com")); + + // Check if the last label is indeed returned + BOOST_CHECK_EQUAL(ans, DNSName("com")); +} + +BOOST_AUTO_TEST_CASE(test_getcommonlabels) { + const DNSName name1("www.powerdns.com"); + const DNSName name2("a.long.list.of.labels.powerdns.com"); + + BOOST_CHECK_EQUAL(name1.getCommonLabels(name1), name1); + BOOST_CHECK_EQUAL(name2.getCommonLabels(name2), name2); + + BOOST_CHECK_EQUAL(name1.getCommonLabels(name2), DNSName("powerdns.com")); + BOOST_CHECK_EQUAL(name2.getCommonLabels(name1), DNSName("powerdns.com")); + + const DNSName name3("www.powerdns.org"); + BOOST_CHECK_EQUAL(name1.getCommonLabels(name3), DNSName()); + BOOST_CHECK_EQUAL(name2.getCommonLabels(name3), DNSName()); + BOOST_CHECK_EQUAL(name3.getCommonLabels(name1), DNSName()); + BOOST_CHECK_EQUAL(name3.getCommonLabels(name2), DNSName()); + + const DNSName name4("WWw.PowErDnS.org"); + BOOST_CHECK_EQUAL(name3.getCommonLabels(name4), name3); + BOOST_CHECK_EQUAL(name4.getCommonLabels(name3), name4); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-dnsparser_cc.cc b/pdns/test-dnsparser_cc.cc new file mode 100644 index 0000000..4a2f6dd --- /dev/null +++ b/pdns/test-dnsparser_cc.cc @@ -0,0 +1,487 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "dnsparser.hh" + +BOOST_AUTO_TEST_SUITE(test_dnsparser_cc) + +BOOST_AUTO_TEST_CASE(test_editDNSPacketTTL) { + + auto generatePacket = [](uint32_t ttl) { + DNSName name("powerdns.com."); + ComboAddress v4("1.2.3.4"); + ComboAddress v6("2001:db8::1"); + + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + + /* record we want to see altered */ + pwR.startRecord(name, QType::A, ttl, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + /* same record but different TTL (yeah, don't do that but it's just a test) */ + pwR.startRecord(name, QType::A, 100, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + /* different type */ + pwR.startRecord(name, QType::AAAA, 42, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP6(std::string(reinterpret_cast(v6.sin6.sin6_addr.s6_addr), 16)); + pwR.commit(); + + /* different class */ + pwR.startRecord(name, QType::A, 42, QClass::CHAOS, DNSResourceRecord::ANSWER); + pwR.commit(); + + /* different section */ + pwR.startRecord(name, QType::A, 42, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + return packet; + }; + + auto firstPacket = generatePacket(42); + auto expectedAlteredPacket = generatePacket(84); + + size_t called = 0; + editDNSPacketTTL(reinterpret_cast(firstPacket.data()), firstPacket.size(), [&called](uint8_t section, uint16_t class_, uint16_t type, uint32_t ttl) { + + called++; + + /* only updates the TTL of IN/A, in answer, with an existing ttl of 42 */ + if (section == 1 && class_ == QClass::IN && type == QType::A && ttl == 42) { + return 84; + } + return 0; + }); + + /* check that we have been for all records */ + BOOST_CHECK_EQUAL(called, 5); + + BOOST_REQUIRE_EQUAL(firstPacket.size(), expectedAlteredPacket.size()); + for (size_t idx = 0; idx < firstPacket.size(); idx++) { + BOOST_CHECK_EQUAL(firstPacket.at(idx), expectedAlteredPacket.at(idx)); + } + BOOST_CHECK(firstPacket == expectedAlteredPacket); + + /* now call it with a truncated packet, missing the last TTL and rdata, + we should only be called 4 times but everything else should be fine. */ + called = 0; + editDNSPacketTTL(reinterpret_cast(firstPacket.data()), firstPacket.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4, [&called](uint8_t section, uint16_t class_, uint16_t type, uint32_t ttl) { + + called++; + + /* only updates the TTL of IN/A, in answer, with an existing ttl of 42 */ + if (section == 1 && class_ == QClass::IN && type == QType::A && ttl == 42) { + return 84; + } + return 0; + }); + + /* check that we have been for all records */ + BOOST_CHECK_EQUAL(called, 4); + BOOST_CHECK(firstPacket == expectedAlteredPacket); +} + +BOOST_AUTO_TEST_CASE(test_ageDNSPacket) { + + auto generatePacket = [](uint32_t ttl) { + DNSName name("powerdns.com."); + ComboAddress v4("1.2.3.4"); + ComboAddress v6("2001:db8::1"); + + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + + /* record we want to see altered */ + pwR.startRecord(name, QType::A, ttl, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + return packet; + }; + + auto firstPacket = generatePacket(3600); + auto expectedAlteredPacket = generatePacket(1800); + + ageDNSPacket(reinterpret_cast(firstPacket.data()), firstPacket.size(), 1800); + + BOOST_REQUIRE_EQUAL(firstPacket.size(), expectedAlteredPacket.size()); + for (size_t idx = 0; idx < firstPacket.size(); idx++) { + BOOST_CHECK_EQUAL(firstPacket.at(idx), expectedAlteredPacket.at(idx)); + } + BOOST_CHECK(firstPacket == expectedAlteredPacket); + + /* now call it with a truncated packet, missing the last TTL and rdata, + the packet should not be altered. */ + ageDNSPacket(reinterpret_cast(firstPacket.data()), firstPacket.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4 - /* size of OPT record */ 11, 900); + + BOOST_CHECK(firstPacket == expectedAlteredPacket); + + /* now remove more than the remaining TTL, not that while TTL are, + per rfc1035 errata, "a 32 bit unsigned integer" so we should be + able to expect unsigned overflow to apply, but rfc2181 specifies + a maximum of "2^31 - 1". */ + ageDNSPacket(reinterpret_cast(firstPacket.data()), firstPacket.size(), 1801); + + uint32_t ttl = std::numeric_limits::max(); + + expectedAlteredPacket = generatePacket(ttl); + BOOST_REQUIRE_EQUAL(firstPacket.size(), expectedAlteredPacket.size()); + for (size_t idx = 0; idx < firstPacket.size(); idx++) { + BOOST_CHECK_EQUAL(firstPacket.at(idx), expectedAlteredPacket.at(idx)); + } + BOOST_CHECK(firstPacket == expectedAlteredPacket); +} + +BOOST_AUTO_TEST_CASE(test_getDNSPacketMinTTL) { + + const DNSName name("powerdns.com."); + const ComboAddress v4("1.2.3.4"); + const ComboAddress v6("2001:db8::1"); + + { + /* no records */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), nullptr); + BOOST_CHECK_EQUAL(result, std::numeric_limits::max()); + } + + { + /* only one record, not an OPT one */ + uint32_t ttl = 42; + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, ttl, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), nullptr); + BOOST_CHECK_EQUAL(result, ttl); + } + + { + /* only one record, an OPT one */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), nullptr); + BOOST_CHECK_EQUAL(result, std::numeric_limits::max()); + } + + { + /* records with different TTLs, should return the lower */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 257, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), nullptr); + BOOST_CHECK_EQUAL(result, 255); + } + + { + /* SOA record in answer, seenAuthSOA should not be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::ANSWER); + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 255); + BOOST_CHECK_EQUAL(seenAuthSOA, false); + } + + { + /* one SOA record in auth, seenAuthSOA should be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 255); + BOOST_CHECK_EQUAL(seenAuthSOA, true); + } + + { + /* one SOA record of the wrong qclass in auth, seenAuthSOA should not be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 257, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 255, QClass::CHAOS, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 255); + BOOST_CHECK_EQUAL(seenAuthSOA, false); + } + + { + /* one A record in auth, seenAuthSOA should not be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 257); + BOOST_CHECK_EQUAL(seenAuthSOA, false); + } + + { + /* one SOA record in additional, seenAuthSOA should not be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 255, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size(), &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 255); + BOOST_CHECK_EQUAL(seenAuthSOA, false); + } + + { + /* truncated packet, no exception should be raised */ + /* one SOA record in auth, seenAuthSOA should be set */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 254, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + bool seenAuthSOA = false; + auto result = getDNSPacketMinTTL(reinterpret_cast(packet.data()), packet.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4, &seenAuthSOA); + BOOST_CHECK_EQUAL(result, 255); + BOOST_CHECK_EQUAL(seenAuthSOA, true); + } +} + +BOOST_AUTO_TEST_CASE(test_getDNSPacketLength) { + + const DNSName name("powerdns.com."); + const ComboAddress v4("1.2.3.4"); + const ComboAddress v6("2001:db8::1"); + + { + /* no records */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + auto result = getDNSPacketLength(reinterpret_cast(packet.data()), packet.size()); + BOOST_CHECK_EQUAL(result, packet.size()); + } + + { + /* several records */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + auto result = getDNSPacketLength(reinterpret_cast(packet.data()), packet.size()); + BOOST_CHECK_EQUAL(result, packet.size()); + } + + { + /* trailing data */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + auto realSize = packet.size(); + packet.resize(realSize + 512); + auto result = getDNSPacketLength(reinterpret_cast(packet.data()), packet.size()); + BOOST_CHECK_EQUAL(result, realSize); + } + + { + /* truncated packet, should return the full size */ + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + size_t fakeSize = packet.size()-1; + auto result = getDNSPacketLength(reinterpret_cast(packet.data()), fakeSize); + BOOST_CHECK_EQUAL(result, fakeSize); + } + +} + +BOOST_AUTO_TEST_CASE(test_getRecordsOfTypeCount) { + const DNSName name("powerdns.com."); + const ComboAddress v4("1.2.3.4"); + const ComboAddress v6("2001:db8::1"); + + { + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + pwR.commit(); + + pwR.startRecord(name, QType::A, 255, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.startRecord(name, QType::SOA, 257, QClass::IN, DNSResourceRecord::AUTHORITY); + pwR.commit(); + + pwR.startRecord(name, QType::A, 256, QClass::IN, DNSResourceRecord::ADDITIONAL); + pwR.xfrIP(v4.sin4.sin_addr.s_addr); + pwR.commit(); + + pwR.addOpt(4096, 0, 0); + pwR.commit(); + + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 0, QType::A), 1); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 0, QType::SOA), 0); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 1, QType::A), 1); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 1, QType::SOA), 0); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 2, QType::A), 0); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 2, QType::SOA), 1); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 3, QType::A), 1); + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 3, QType::SOA), 0); + + BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast(packet.data()), packet.size(), 4, QType::SOA), 0); +} + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-dnsparser_hh.cc b/pdns/test-dnsparser_hh.cc new file mode 100644 index 0000000..6165743 --- /dev/null +++ b/pdns/test-dnsparser_hh.cc @@ -0,0 +1,21 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "dnsparser.hh" + +BOOST_AUTO_TEST_SUITE(test_dnsparser_hh) + +BOOST_AUTO_TEST_CASE(test_type_lowercase) { + std::string lc("type12345"); + std::string uc("TYPE12345"); + + uint16_t lc_result = DNSRecordContent::TypeToNumber(lc); + uint16_t uc_result = DNSRecordContent::TypeToNumber(uc); + BOOST_CHECK_EQUAL(lc_result, 12345); + BOOST_CHECK_EQUAL(lc_result, uc_result); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-dnsrecordcontent.cc b/pdns/test-dnsrecordcontent.cc new file mode 100644 index 0000000..527b49b --- /dev/null +++ b/pdns/test-dnsrecordcontent.cc @@ -0,0 +1,45 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "dnsrecords.hh" +#include "iputils.hh" + +BOOST_AUTO_TEST_SUITE(test_dnsrecordcontent) + +BOOST_AUTO_TEST_CASE(test_equality) { + ComboAddress ip("1.2.3.4"), ip2("10.0.0.1"), ip6("::1"); + ARecordContent a1(ip), a2(ip), a3(ip2); + AAAARecordContent aaaa(ip6), aaaa1(ip6); + + BOOST_CHECK(a1==a2); + BOOST_CHECK(!(a1==a3)); + + BOOST_CHECK(aaaa == aaaa1); + + + auto rec1=DNSRecordContent::mastermake(QType::A, 1, "192.168.0.1"); + auto rec2=DNSRecordContent::mastermake(QType::A, 1, "192.168.222.222"); + auto rec3=DNSRecordContent::mastermake(QType::AAAA, 1, "::1"); + auto recMX=DNSRecordContent::mastermake(QType::MX, 1, "25 smtp.powerdns.com"); + auto recMX2=DNSRecordContent::mastermake(QType::MX, 1, "26 smtp.powerdns.com"); + auto recMX3=DNSRecordContent::mastermake(QType::MX, 1, "26 SMTP.powerdns.com"); + BOOST_CHECK(!(*rec1==*rec2)); + BOOST_CHECK(*rec1==*rec1); + BOOST_CHECK(*rec3==*rec3); + + BOOST_CHECK(*recMX==*recMX); + BOOST_CHECK(*recMX2==*recMX3); + BOOST_CHECK(!(*recMX==*recMX3)); + + + BOOST_CHECK(!(*rec1==*rec3)); + + NSRecordContent ns1(DNSName("ns1.powerdns.com")), ns2(DNSName("NS1.powerdns.COM")), ns3(DNSName("powerdns.net")); + BOOST_CHECK(ns1==ns2); + BOOST_CHECK(!(ns1==ns3)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc new file mode 100644 index 0000000..5e50111 --- /dev/null +++ b/pdns/test-dnsrecords_cc.cc @@ -0,0 +1,568 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include + +#include "base32.hh" +#include "dnsrecords.hh" + +namespace { + enum class broken_marker { + WORKING, + BROKEN, + }; +} + +// use a user-defined literal operator instead? should be supported in +// C++11, but only C++14 added the `s` suffix. +#define BINARY(s) (std::string(s, sizeof(s) - 1)) + +// CASE_S is the simple case where zonefile format -> dns -> zonefile format roundtrips cleanly +// CASE_L can be used where this is not the case. See LOC below for a good example why this might happen + +/* (CASE_S(QType::NAME, "zone format", "line format")) */ +/* (CASE_L(QType::NAME, "zone format", "canonic zone format", "line format")) */ + +#define _CASE_L(type, inval, zoneval, lineval, broken) case_t(type, BINARY(inval), BINARY(zoneval), BINARY(lineval), broken) +#define CASE_L(type, inval, zoneval, lineval) _CASE_L(type, inval, zoneval, lineval, broken_marker::WORKING) +#define CASE_S(type, zoneval, lineval) _CASE_L(type, zoneval, zoneval, lineval, broken_marker::WORKING) +#define BROKEN_CASE_L(type, inval, zoneval, lineval) _CASE_L(type, inval, zoneval, lineval, broken_marker::BROKEN) +#define BROKEN_CASE_S(type, zoneval, lineval) _CASE_L(type, zoneval, zoneval, lineval, broken_marker::BROKEN) +BOOST_AUTO_TEST_SUITE(test_dnsrecords_cc) + +#define REC_CHECK_EQUAL(a,b) { if (broken_marker::BROKEN == broken) { BOOST_WARN_EQUAL(a,b); } else { BOOST_CHECK_EQUAL(a,b); } } +#define REC_CHECK_MESSAGE(cond,msg) { if (broken_marker::BROKEN == broken) { BOOST_WARN_MESSAGE(cond,"Failed to verify " << msg); } else { BOOST_CHECK_MESSAGE(cond,msg); } } +#define REC_FAIL_XSUCCESS(msg) { if (broken_marker::BROKEN == broken) { BOOST_CHECK_MESSAGE(false, std::string("Test has unexpectedly passed: ") + msg); } } // fail if test succeeds + +BOOST_AUTO_TEST_CASE(test_record_types) { + // tuple contains + typedef boost::tuple case_t; + typedef std::list cases_t; + MRRecordContent::report(); + IPSECKEYRecordContent::report(); + KXRecordContent::report(); + DHCIDRecordContent::report(); + TSIGRecordContent::report(); + TKEYRecordContent::report(); + +// NB!!! WHEN ADDING A TEST MAKE SURE YOU PUT IT NEXT TO ITS KIND +// TO MAKE SURE TEST NUMBERING DOES NOT BREAK + +// why yes, they are unordered by name, how nice of you to notice + + const cases_t cases = boost::assign::list_of + (CASE_S(QType::A, "127.0.0.1", "\x7F\x00\x00\x01")) +// local nameserver + (CASE_S(QType::NS, "ns.rec.test.", "\x02ns\xc0\x11")) +// non-local nameserver + (CASE_S(QType::NS, "ns.example.com.", "\x02ns\x07""example\x03""com\x00")) +// local alias + (CASE_S(QType::CNAME, "name.rec.test.", "\x04name\xc0\x11")) +// non-local alias + (CASE_S(QType::CNAME, "name.example.com.", "\x04name\x07""example\x03""com\x00")) +// max label length (63) + (CASE_S(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.example.com.", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x07""example\x03""com\x00")) +// local max name length (255) + (CASE_S(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012.rec.test.", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x34""1234567890123456789012345678901234567890123456789012\xc0\x11")) +// non-local max name length (255) + (CASE_S(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901.", "\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3f""123456789012345678901234567890123456789012345678901234567890123\x3d""1234567890123456789012345678901234567890123456789012345678901\x00")) +// local names + (CASE_S(QType::SOA, "ns.rec.test. hostmaster.test.rec. 2013051201 3600 3600 604800 120", "\x02ns\xc0\x11\x0ahostmaster\x04test\x03rec\x00\x77\xfc\xb9\x41\x00\x00\x0e\x10\x00\x00\x0e\x10\x00\x09\x3a\x80\x00\x00\x00\x78")) +// non-local names + (CASE_S(QType::SOA, "ns.example.com. hostmaster.example.com. 2013051201 3600 3600 604800 120", "\x02ns\x07""example\x03""com\x00\x0ahostmaster\xc0\x28\x77\xfc\xb9\x41\x00\x00\x0e\x10\x00\x00\x0e\x10\x00\x09\x3a\x80\x00\x00\x00\x78")) + +// local name + (CASE_S(QType::MR, "newmailbox.rec.test.", "\x0anewmailbox\xc0\x11")) +// non-local name + (CASE_S(QType::MR, "newmailbox.example.com.", "\x0anewmailbox\x07""example\x03""com\x00")) + +// local name + (CASE_S(QType::PTR, "ptr.rec.test.", "\x03ptr\xc0\x11")) +// non-local name + (CASE_S(QType::PTR, "ptr.example.com.", "\x03ptr\x07""example\x03""com\x00")) + (CASE_S(QType::HINFO, "\"i686\" \"Linux\"", "\x04i686\x05Linux")) + (BROKEN_CASE_L(QType::HINFO, "i686 \"Linux\"", "\"i686\" \"Linux\"", "\x04i686\x05Linux")) + (CASE_L(QType::HINFO, "\"i686\" Linux", "\"i686\" \"Linux\"", "\x04i686\x05Linux")) + (BROKEN_CASE_L(QType::HINFO, "i686 Linux", "\"i686\" \"Linux\"", "\x04i686\x05Linux")) +// local name + (CASE_S(QType::MX, "10 mx.rec.test.", "\x00\x0a\x02mx\xc0\x11")) +// non-local name + (CASE_S(QType::MX, "20 mx.example.com.", "\x00\x14\x02mx\x07""example\x03""com\x00")) +// root label + (CASE_S(QType::MX, "20 .", "\x00\x14\x00")) + + (CASE_S(QType::TXT, "\"short text\"", "\x0ashort text")) + (CASE_S(QType::TXT, "\"long record test 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\" \"2222222222\"", "\xff""long record test 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\x0a""2222222222")) + (CASE_L(QType::TXT, "\"long record test 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112222222222\"", "\"long record test 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\" \"2222222222\"", "\xff""long record test 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\x0a""2222222222")) + (CASE_S(QType::TXT, "\"\\195\\133LAND ISLANDS\"", "\x0e\xc3\x85LAND ISLANDS")) + (CASE_S(QType::TXT, "\"text with DEL in there: \\127\"", "\x19text with DEL in there: \x7f")) + (CASE_L(QType::TXT, "\"\xc3\x85LAND ISLANDS\"", "\"\\195\\133LAND ISLANDS\"", "\x0e\xc3\x85LAND ISLANDS")) + (CASE_S(QType::TXT, "\"nonbreakingtxt\"", "\x0enonbreakingtxt")) +// local name + (CASE_S(QType::RP, "admin.rec.test. admin-info.rec.test.", "\x05""admin\x03rec\x04test\x00\x0a""admin-info\x03rec\x04test\x00")) +// non-local name + (CASE_S(QType::RP, "admin.example.com. admin-info.example.com.", "\x05""admin\x07""example\x03""com\x00\x0a""admin-info\x07""example\x03""com\x00")) +// local name + (CASE_S(QType::AFSDB, "1 afs-server.rec.test.", "\x00\x01\x0a""afs-server\x03rec\x04test\x00")) +// non-local name + (CASE_S(QType::AFSDB, "1 afs-server.example.com.", "\x00\x01\x0a""afs-server\x07""example\x03""com\x00")) + (CASE_S(QType::KEY, "0 3 3 V19hwufL6LJARVIxzHDyGdvZ7dbQE0Kyl18yPIWj/sbCcsBbz7zO6Q2qgdzmWI3OvGNne2nxflhorhefKIMsUg==", "\x00\x00\x03\x03\x57\x5f\x61\xc2\xe7\xcb\xe8\xb2\x40\x45\x52\x31\xcc\x70\xf2\x19\xdb\xd9\xed\xd6\xd0\x13\x42\xb2\x97\x5f\x32\x3c\x85\xa3\xfe\xc6\xc2\x72\xc0\x5b\xcf\xbc\xce\xe9\x0d\xaa\x81\xdc\xe6\x58\x8d\xce\xbc\x63\x67\x7b\x69\xf1\x7e\x58\x68\xae\x17\x9f\x28\x83\x2c\x52")) + (CASE_S(QType::AAAA, "fe80::250:56ff:fe9b:114", "\xFE\x80\x00\x00\x00\x00\x00\x00\x02\x50\x56\xFF\xFE\x9B\x01\x14")) + (CASE_S(QType::AAAA, "2a02:1b8:10:2::151", "\x2a\x02\x01\xb8\x00\x10\x00\x02\x00\x00\x00\x00\x00\x00\x01\x51")) + (CASE_S(QType::AAAA, "::1", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")) + (CASE_L(QType::LOC, "32 7 19 S 116 2 25 E", "32 7 19.000 S 116 2 25.000 E 0.00m 1.00m 10000.00m 10.00m", "\x00\x12\x16\x13\x79\x1b\x7d\x28\x98\xe6\x48\x68\x00\x98\x96\x80")) + (CASE_L(QType::LOC, "32 7 19 S 116 2 25 E 10m", "32 7 19.000 S 116 2 25.000 E 10.00m 1.00m 10000.00m 10.00m", "\x00\x12\x16\x13\x79\x1b\x7d\x28\x98\xe6\x48\x68\x00\x98\x9a\x68")) + (CASE_L(QType::LOC, "42 21 54 N 71 06 18 W -24m 30m", "42 21 54.000 N 71 6 18.000 W -24.00m 30.00m 10000.00m 10.00m", "\x00\x33\x16\x13\x89\x17\x2d\xd0\x70\xbe\x15\xf0\x00\x98\x8d\x20")) + (CASE_L(QType::LOC, "42 21 43.952 N 71 5 6.344 W -24m 1m 200m", "42 21 43.952 N 71 5 6.344 W -24.00m 1.00m 200.00m 10.00m", "\x00\x12\x24\x13\x89\x17\x06\x90\x70\xbf\x2d\xd8\x00\x98\x8d\x20")) +// local name + (CASE_S(QType::SRV, "10 10 5060 sip.rec.test.", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x03rec\x04test\x00")) +// non-local name + (CASE_S(QType::SRV, "10 10 5060 sip.example.com.", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x07""example\x03""com\x00")) +// root name + (CASE_S(QType::SRV, "10 10 5060 .", "\x00\x0a\x00\x0a\x13\xc4\x00")) + + (CASE_S(QType::NAPTR, "100 10 \"\" \"\" \"/urn:cid:.+@([^\\\\.]+\\\\.)(.*)$/\\\\2/i\" .", "\x00\x64\x00\x0a\x00\x00\x20/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i\x00")) + (CASE_S(QType::NAPTR, "100 50 \"s\" \"http+I2L+I2C+I2R\" \"\" _http._tcp.rec.test.", "\x00\x64\x00\x32\x01s\x10http+I2L+I2C+I2R\x00\x05_http\x04_tcp\x03rec\x04test\x00")) + (CASE_S(QType::KX, "10 mail.rec.test.", "\x00\x0a\x04mail\x03rec\x04test\x00")) + +// X.509 as per PKIX + (CASE_S(QType::CERT, "1 0 0 MIIB9DCCAV2gAwIBAgIJAKxUfFVXhw7HMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNVBAMMCHJlYy50ZXN0MB4XDTEzMDUxMjE5NDgwOVoXDTEzMDYxMTE5NDgwOVowEzERMA8GA1UEAwwIcmVjLnRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANKCu5aN/ewOXRPfzAo27XMXhYFCThCjfInTAUIEkzs6jBFZ/eyyIa/kFoiD0tAKwfFfykYU+9XgXeLjetD7rYt3SN3bzzCznoBGbGHHM0Fecrn0LV+tC/NfBB61Yx7e0AMUxmxIeLNRQW5ca5CW8qcIiiQ4fl0BScUjc5+E9QLHAgMBAAGjUDBOMB0GA1UdDgQWBBRzcVu/2bwrgkES+FhYbxZqr7mUgjAfBgNVHSMEGDAWgBRzcVu/2bwrgkES+FhYbxZqr7mUgjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFVQ8dZBOasOhsWzA/xpAV0WdsqVkxBxrkGIRlbHHBFqOBOOz2MFSzUNx4mDy0qDKI28gcWmWaVsxoQ9VFLD6YRJuUoM8MDNcZDJbKpfDumjvvfnUAK+SiM2c4Ur3xpf0wanCA60/q2bOtFiB0tfAH6RVuIgMC3qjHAIaKEld+fE", "\x00\x01\x00\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_L(QType::DS, "20642 8 2 04443ABE7E94C3985196BEAE5D548C727B044DDA5151E60D7CD76A9F D931D00E", "20642 8 2 04443abe7e94c3985196beae5d548c727b044dda5151e60d7cd76a9fd931d00e", "\x50\xa2\x08\x02\x04\x44\x3a\xbe\x7e\x94\xc3\x98\x51\x96\xbe\xae\x5d\x54\x8c\x72\x7b\x04\x4d\xda\x51\x51\xe6\x0d\x7c\xd7\x6a\x9f\xd9\x31\xd0\x0e")) + (CASE_S(QType::SSHFP, "1 1 aa65e3415a50d9b3519c2b17aceb815fc2538d88", "\x01\x01\xaa\x65\xe3\x41\x5a\x50\xd9\xb3\x51\x9c\x2b\x17\xac\xeb\x81\x5f\xc2\x53\x8d\x88")) + (CASE_L(QType::SSHFP, "1 1 aa65e3415a50d9b3519c2b17aceb815fc253 8d88", "1 1 aa65e3415a50d9b3519c2b17aceb815fc2538d88", "\x01\x01\xaa\x65\xe3\x41\x5a\x50\xd9\xb3\x51\x9c\x2b\x17\xac\xeb\x81\x5f\xc2\x53\x8d\x88")) +// as per RFC4025 + (CASE_S(QType::IPSECKEY, "255 0 0", "\xff\x00\x00")) + (CASE_S(QType::IPSECKEY, "255 0 1 V19hwufL6LJARVIxzHDyGdvZ7dbQE0Kyl18yPIWj/sbCcsBbz7zO6Q2qgdzmWI3OvGNne2nxflhorhefKIMsUg==", "\xff\x00\x01\x57\x5f\x61\xc2\xe7\xcb\xe8\xb2\x40\x45\x52\x31\xcc\x70\xf2\x19\xdb\xd9\xed\xd6\xd0\x13\x42\xb2\x97\x5f\x32\x3c\x85\xa3\xfe\xc6\xc2\x72\xc0\x5b\xcf\xbc\xce\xe9\x0d\xaa\x81\xdc\xe6\x58\x8d\xce\xbc\x63\x67\x7b\x69\xf1\x7e\x58\x68\xae\x17\x9f\x28\x83\x2c\x52")) + (CASE_S(QType::IPSECKEY, "255 1 0 127.0.0.1", "\xff\x01\x00\x7f\x00\x00\x01")) + (CASE_S(QType::IPSECKEY, "255 2 0 fe80::250:56ff:fe9b:114", "\xff\x02\x00\xFE\x80\x00\x00\x00\x00\x00\x00\x02\x50\x56\xFF\xFE\x9B\x01\x14")) + (CASE_S(QType::IPSECKEY, "10 1 1 127.0.0.1 V19hwufL6LJARVIxzHDyGdvZ7dbQE0Kyl18yPIWj/sbCcsBbz7zO6Q2qgdzmWI3OvGNne2nxflhorhefKIMsUg==", "\x0a\x01\x01\x7f\x00\x00\x01\x57\x5f\x61\xc2\xe7\xcb\xe8\xb2\x40\x45\x52\x31\xcc\x70\xf2\x19\xdb\xd9\xed\xd6\xd0\x13\x42\xb2\x97\x5f\x32\x3c\x85\xa3\xfe\xc6\xc2\x72\xc0\x5b\xcf\xbc\xce\xe9\x0d\xaa\x81\xdc\xe6\x58\x8d\xce\xbc\x63\x67\x7b\x69\xf1\x7e\x58\x68\xae\x17\x9f\x28\x83\x2c\x52")) + (CASE_S(QType::IPSECKEY, "10 2 1 fe80::250:56ff:fe9b:114 V19hwufL6LJARVIxzHDyGdvZ7dbQE0Kyl18yPIWj/sbCcsBbz7zO6Q2qgdzmWI3OvGNne2nxflhorhefKIMsUg==", "\x0a\x02\x01\xFE\x80\x00\x00\x00\x00\x00\x00\x02\x50\x56\xFF\xFE\x9B\x01\x14\x57\x5f\x61\xc2\xe7\xcb\xe8\xb2\x40\x45\x52\x31\xcc\x70\xf2\x19\xdb\xd9\xed\xd6\xd0\x13\x42\xb2\x97\x5f\x32\x3c\x85\xa3\xfe\xc6\xc2\x72\xc0\x5b\xcf\xbc\xce\xe9\x0d\xaa\x81\xdc\xe6\x58\x8d\xce\xbc\x63\x67\x7b\x69\xf1\x7e\x58\x68\xae\x17\x9f\x28\x83\x2c\x52")) + (CASE_S(QType::IPSECKEY, "10 3 1 gw.rec.test. V19hwufL6LJARVIxzHDyGdvZ7dbQE0Kyl18yPIWj/sbCcsBbz7zO6Q2qgdzmWI3OvGNne2nxflhorhefKIMsUg==", "\x0a\x03\x01\x02gw\x03rec\x04test\x00\x57\x5f\x61\xc2\xe7\xcb\xe8\xb2\x40\x45\x52\x31\xcc\x70\xf2\x19\xdb\xd9\xed\xd6\xd0\x13\x42\xb2\x97\x5f\x32\x3c\x85\xa3\xfe\xc6\xc2\x72\xc0\x5b\xcf\xbc\xce\xe9\x0d\xaa\x81\xdc\xe6\x58\x8d\xce\xbc\x63\x67\x7b\x69\xf1\x7e\x58\x68\xae\x17\x9f\x28\x83\x2c\x52")) + + (CASE_S(QType::RRSIG, "SOA 8 3 300 20130523000000 20130509000000 54216 rec.test. ecWKD/OsdAiXpbM/sgPT82KVD/WiQnnqcxoJgiH3ixHa+LOAcYU7FG7V4BRRJxLriY1e0rB2gAs3kCel9D4bzfK6wAqG4Di/eHUgHptRlaR2ycELJ4t1pjzrnuGiIzA1wM2izRmeE+Xoy1367Qu0pOz5DLzTfQITWFsB2iUzN4Y=", "\x00\x06\x08\x03\x00\x00\x01\x2c\x51\x9d\x5c\x00\x51\x8a\xe7\x00\xd3\xc8\x03\x72\x65\x63\x04\x74\x65\x73\x74\x00\x79\xc5\x8a\x0f\xf3\xac\x74\x08\x97\xa5\xb3\x3f\xb2\x03\xd3\xf3\x62\x95\x0f\xf5\xa2\x42\x79\xea\x73\x1a\x09\x82\x21\xf7\x8b\x11\xda\xf8\xb3\x80\x71\x85\x3b\x14\x6e\xd5\xe0\x14\x51\x27\x12\xeb\x89\x8d\x5e\xd2\xb0\x76\x80\x0b\x37\x90\x27\xa5\xf4\x3e\x1b\xcd\xf2\xba\xc0\x0a\x86\xe0\x38\xbf\x78\x75\x20\x1e\x9b\x51\x95\xa4\x76\xc9\xc1\x0b\x27\x8b\x75\xa6\x3c\xeb\x9e\xe1\xa2\x23\x30\x35\xc0\xcd\xa2\xcd\x19\x9e\x13\xe5\xe8\xcb\x5d\xfa\xed\x0b\xb4\xa4\xec\xf9\x0c\xbc\xd3\x7d\x02\x13\x58\x5b\x01\xda\x25\x33\x37\x86")) + // timestamps can be given as (32-bit wrapped) epoch too: + (CASE_L(QType::RRSIG, "SOA 8 3 300 1369267200 1368057600 54216 rec.test. ecWKD/OsdAiXpbM/sgPT82KVD/WiQnnqcxoJgiH3ixHa+LOAcYU7FG7V4BRRJxLriY1e0rB2gAs3kCel9D4bzfK6wAqG4Di/eHUgHptRlaR2ycELJ4t1pjzrnuGiIzA1wM2izRmeE+Xoy1367Qu0pOz5DLzTfQITWFsB2iUzN4Y=", "SOA 8 3 300 20130523000000 20130509000000 54216 rec.test. ecWKD/OsdAiXpbM/sgPT82KVD/WiQnnqcxoJgiH3ixHa+LOAcYU7FG7V4BRRJxLriY1e0rB2gAs3kCel9D4bzfK6wAqG4Di/eHUgHptRlaR2ycELJ4t1pjzrnuGiIzA1wM2izRmeE+Xoy1367Qu0pOz5DLzTfQITWFsB2iUzN4Y=", "\x00\x06\x08\x03\x00\x00\x01\x2c\x51\x9d\x5c\x00\x51\x8a\xe7\x00\xd3\xc8\x03\x72\x65\x63\x04\x74\x65\x73\x74\x00\x79\xc5\x8a\x0f\xf3\xac\x74\x08\x97\xa5\xb3\x3f\xb2\x03\xd3\xf3\x62\x95\x0f\xf5\xa2\x42\x79\xea\x73\x1a\x09\x82\x21\xf7\x8b\x11\xda\xf8\xb3\x80\x71\x85\x3b\x14\x6e\xd5\xe0\x14\x51\x27\x12\xeb\x89\x8d\x5e\xd2\xb0\x76\x80\x0b\x37\x90\x27\xa5\xf4\x3e\x1b\xcd\xf2\xba\xc0\x0a\x86\xe0\x38\xbf\x78\x75\x20\x1e\x9b\x51\x95\xa4\x76\xc9\xc1\x0b\x27\x8b\x75\xa6\x3c\xeb\x9e\xe1\xa2\x23\x30\x35\xc0\xcd\xa2\xcd\x19\x9e\x13\xe5\xe8\xcb\x5d\xfa\xed\x0b\xb4\xa4\xec\xf9\x0c\xbc\xd3\x7d\x02\x13\x58\x5b\x01\xda\x25\x33\x37\x86")) + (CASE_S(QType::NSEC, "a.rec.test. A NS SOA MX AAAA RRSIG NSEC DNSKEY", "\x01""a\x03rec\x04test\x00\x00\x07\x62\x01\x00\x08\x00\x03\x80")) + (CASE_S(QType::DNSKEY, "257 3 5 AwEAAZVtlHc8O4TVmlGx/PGJTc7hbVjMR7RywxLuAm1dqgyHvgNRD7chYLsALOdZKW6VRvusbyhoOPilnh8XpucBDqjGD6lIemsURz7drZEqcLupVA0TPxXABZ6auJ3jumqIhSOcLj9rpSwI4xuWt0yu6LR9tL2q8+A0yEZxcAaKS+Wq0fExJ93NxgXl1/fY+JcYQvonjd31GxXXef9uf0exXyzowh5h8+IIBETU+ZiYVB5BqiwkICZL/OX57idm99ycA2/tIen66F8u2ueTvgPcecnoqHvW0MtLQKzeNmqdGNthHhV5di0SZdMZQeo/izs68uN2WzqQDZy9Ec2JwBTbxWE=", "\x01\x01\x03\x05\x03\x01\x00\x01\x95\x6d\x94\x77\x3c\x3b\x84\xd5\x9a\x51\xb1\xfc\xf1\x89\x4d\xce\xe1\x6d\x58\xcc\x47\xb4\x72\xc3\x12\xee\x02\x6d\x5d\xaa\x0c\x87\xbe\x03\x51\x0f\xb7\x21\x60\xbb\x00\x2c\xe7\x59\x29\x6e\x95\x46\xfb\xac\x6f\x28\x68\x38\xf8\xa5\x9e\x1f\x17\xa6\xe7\x01\x0e\xa8\xc6\x0f\xa9\x48\x7a\x6b\x14\x47\x3e\xdd\xad\x91\x2a\x70\xbb\xa9\x54\x0d\x13\x3f\x15\xc0\x05\x9e\x9a\xb8\x9d\xe3\xba\x6a\x88\x85\x23\x9c\x2e\x3f\x6b\xa5\x2c\x08\xe3\x1b\x96\xb7\x4c\xae\xe8\xb4\x7d\xb4\xbd\xaa\xf3\xe0\x34\xc8\x46\x71\x70\x06\x8a\x4b\xe5\xaa\xd1\xf1\x31\x27\xdd\xcd\xc6\x05\xe5\xd7\xf7\xd8\xf8\x97\x18\x42\xfa\x27\x8d\xdd\xf5\x1b\x15\xd7\x79\xff\x6e\x7f\x47\xb1\x5f\x2c\xe8\xc2\x1e\x61\xf3\xe2\x08\x04\x44\xd4\xf9\x98\x98\x54\x1e\x41\xaa\x2c\x24\x20\x26\x4b\xfc\xe5\xf9\xee\x27\x66\xf7\xdc\x9c\x03\x6f\xed\x21\xe9\xfa\xe8\x5f\x2e\xda\xe7\x93\xbe\x03\xdc\x79\xc9\xe8\xa8\x7b\xd6\xd0\xcb\x4b\x40\xac\xde\x36\x6a\x9d\x18\xdb\x61\x1e\x15\x79\x76\x2d\x12\x65\xd3\x19\x41\xea\x3f\x8b\x3b\x3a\xf2\xe3\x76\x5b\x3a\x90\x0d\x9c\xbd\x11\xcd\x89\xc0\x14\xdb\xc5\x61")) + + (CASE_S(QType::DHCID, "AAAB92JtyyO73zqENgu9LVua+0PZoeCcKapTw4asbYmx5F4=", "\x00\x00\x01\xf7\x62\x6d\xcb\x23\xbb\xdf\x3a\x84\x36\x0b\xbd\x2d\x5b\x9a\xfb\x43\xd9\xa1\xe0\x9c\x29\xaa\x53\xc3\x86\xac\x6d\x89\xb1\xe4\x5e")) + (CASE_S(QType::DHCID, "AAEB92JtyyO73zqENgu9LVua+0PZoeCcKapTw4asbYmx5F4=", "\x00\x01\x01\xf7\x62\x6d\xcb\x23\xbb\xdf\x3a\x84\x36\x0b\xbd\x2d\x5b\x9a\xfb\x43\xd9\xa1\xe0\x9c\x29\xaa\x53\xc3\x86\xac\x6d\x89\xb1\xe4\x5e")) + (CASE_S(QType::DHCID, "AAIB92JtyyO73zqENgu9LVua+0PZoeCcKapTw4asbYmx5F4=", "\x00\x02\x01\xf7\x62\x6d\xcb\x23\xbb\xdf\x3a\x84\x36\x0b\xbd\x2d\x5b\x9a\xfb\x43\xd9\xa1\xe0\x9c\x29\xaa\x53\xc3\x86\xac\x6d\x89\xb1\xe4\x5e")) + + (CASE_S(QType::NSEC3, "1 1 1 f00b RPF1JGFCCNFA7STPTIJ9FPFNM40A4FLL NS SOA RRSIG DNSKEY NSEC3PARAM", "\x01\x01\x00\x01\x02\xf0\x0b\x14\xde\x5e\x19\xc1\xec\x65\xde\xa3\xf3\xb9\xec\xa6\x97\xe5\xf7\xb1\x00\xa2\x3e\xb5\x00\x07\x22\x00\x00\x00\x00\x02\x90")) + (CASE_S(QType::NSEC3PARAM, "1 0 1 f00b", "\x01\x00\x00\x01\x02\xf0\x0b")) + + (CASE_S(QType::TLSA, "0 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x00\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::TLSA, "0 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x00\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + (CASE_S(QType::TLSA, "1 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x01\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::TLSA, "1 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x01\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + (CASE_S(QType::TLSA, "1 0 1 6acea2f68b03d9efe97a967e137aca6ac3a89490d532d87806d9e9c257668453", "\x01\x00\x01\x6a\xce\xa2\xf6\x8b\x03\xd9\xef\xe9\x7a\x96\x7e\x13\x7a\xca\x6a\xc3\xa8\x94\x90\xd5\x32\xd8\x78\x06\xd9\xe9\xc2\x57\x66\x84\x53")) + (CASE_S(QType::TLSA, "1 0 2 e6dce237992803488d11d828b7728deddd4577de73d7d078338c8a45880beddff98e076a28bf8e3068da8e73667b802a721c95d7323b038c60200a430cb6fbd4", "\x01\x00\x02\xe6\xdc\xe2\x37\x99\x28\x03\x48\x8d\x11\xd8\x28\xb7\x72\x8d\xed\xdd\x45\x77\xde\x73\xd7\xd0\x78\x33\x8c\x8a\x45\x88\x0b\xed\xdf\xf9\x8e\x07\x6a\x28\xbf\x8e\x30\x68\xda\x8e\x73\x66\x7b\x80\x2a\x72\x1c\x95\xd7\x32\x3b\x03\x8c\x60\x20\x0a\x43\x0c\xb6\xfb\xd4")) + (CASE_S(QType::TLSA, "2 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x02\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::TLSA, "2 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x02\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + + (CASE_S(QType::TLSA, "3 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x03\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::TLSA, "3 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x03\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + + (CASE_S(QType::SMIMEA, "0 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x00\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::SMIMEA, "0 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x00\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + (CASE_S(QType::SMIMEA, "1 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x01\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::SMIMEA, "1 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x01\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + (CASE_S(QType::SMIMEA, "1 0 1 6acea2f68b03d9efe97a967e137aca6ac3a89490d532d87806d9e9c257668453", "\x01\x00\x01\x6a\xce\xa2\xf6\x8b\x03\xd9\xef\xe9\x7a\x96\x7e\x13\x7a\xca\x6a\xc3\xa8\x94\x90\xd5\x32\xd8\x78\x06\xd9\xe9\xc2\x57\x66\x84\x53")) + (CASE_S(QType::SMIMEA, "1 0 2 e6dce237992803488d11d828b7728deddd4577de73d7d078338c8a45880beddff98e076a28bf8e3068da8e73667b802a721c95d7323b038c60200a430cb6fbd4", "\x01\x00\x02\xe6\xdc\xe2\x37\x99\x28\x03\x48\x8d\x11\xd8\x28\xb7\x72\x8d\xed\xdd\x45\x77\xde\x73\xd7\xd0\x78\x33\x8c\x8a\x45\x88\x0b\xed\xdf\xf9\x8e\x07\x6a\x28\xbf\x8e\x30\x68\xda\x8e\x73\x66\x7b\x80\x2a\x72\x1c\x95\xd7\x32\x3b\x03\x8c\x60\x20\x0a\x43\x0c\xb6\xfb\xd4")) + (CASE_S(QType::SMIMEA, "2 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x02\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::SMIMEA, "2 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x02\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + (CASE_S(QType::SMIMEA, "3 0 0 308201f43082015da003020102020900ac547c5557870ec7300d06092a864886f70d010105050030133111300f06035504030c087265632e74657374301e170d3133303531323139343830395a170d3133303631313139343830395a30133111300f06035504030c087265632e7465737430819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001a350304e301d0603551d0e0416041473715bbfd9bc2b824112f858586f166aafb99482301f0603551d2304183016801473715bbfd9bc2b824112f858586f166aafb99482300c0603551d13040530030101ff300d06092a864886f70d0101050500038181005550f1d64139ab0e86c5b303fc69015d1676ca95931071ae41884656c71c116a38138ecf63054b350dc78983cb4a83288dbc81c5a659a56cc6843d5452c3e98449b94a0cf0c0cd7190c96caa5f0ee9a3bef7e75002be4a233673852bdf1a5fd306a7080eb4fead9b3ad162074b5f007e9156e220302dea8c700868a12577e7c4", "\x03\x00\x00\x30\x82\x01\xf4\x30\x82\x01\x5d\xa0\x03\x02\x01\x02\x02\x09\x00\xac\x54\x7c\x55\x57\x87\x0e\xc7\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x1e\x17\x0d\x31\x33\x30\x35\x31\x32\x31\x39\x34\x38\x30\x39\x5a\x17\x0d\x31\x33\x30\x36\x31\x31\x31\x39\x34\x38\x30\x39\x5a\x30\x13\x31\x11\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x72\x65\x63\x2e\x74\x65\x73\x74\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01\xa3\x50\x30\x4e\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x73\x71\x5b\xbf\xd9\xbc\x2b\x82\x41\x12\xf8\x58\x58\x6f\x16\x6a\xaf\xb9\x94\x82\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00\x55\x50\xf1\xd6\x41\x39\xab\x0e\x86\xc5\xb3\x03\xfc\x69\x01\x5d\x16\x76\xca\x95\x93\x10\x71\xae\x41\x88\x46\x56\xc7\x1c\x11\x6a\x38\x13\x8e\xcf\x63\x05\x4b\x35\x0d\xc7\x89\x83\xcb\x4a\x83\x28\x8d\xbc\x81\xc5\xa6\x59\xa5\x6c\xc6\x84\x3d\x54\x52\xc3\xe9\x84\x49\xb9\x4a\x0c\xf0\xc0\xcd\x71\x90\xc9\x6c\xaa\x5f\x0e\xe9\xa3\xbe\xf7\xe7\x50\x02\xbe\x4a\x23\x36\x73\x85\x2b\xdf\x1a\x5f\xd3\x06\xa7\x08\x0e\xb4\xfe\xad\x9b\x3a\xd1\x62\x07\x4b\x5f\x00\x7e\x91\x56\xe2\x20\x30\x2d\xea\x8c\x70\x08\x68\xa1\x25\x77\xe7\xc4")) + (CASE_S(QType::SMIMEA, "3 1 0 30819f300d06092a864886f70d010101050003818d0030818902818100d282bb968dfdec0e5d13dfcc0a36ed73178581424e10a37c89d3014204933b3a8c1159fdecb221afe4168883d2d00ac1f15fca4614fbd5e05de2e37ad0fbad8b7748dddbcf30b39e80466c61c733415e72b9f42d5fad0bf35f041eb5631eded00314c66c4878b351416e5c6b9096f2a7088a24387e5d0149c523739f84f502c70203010001", "\x03\x01\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xd2\x82\xbb\x96\x8d\xfd\xec\x0e\x5d\x13\xdf\xcc\x0a\x36\xed\x73\x17\x85\x81\x42\x4e\x10\xa3\x7c\x89\xd3\x01\x42\x04\x93\x3b\x3a\x8c\x11\x59\xfd\xec\xb2\x21\xaf\xe4\x16\x88\x83\xd2\xd0\x0a\xc1\xf1\x5f\xca\x46\x14\xfb\xd5\xe0\x5d\xe2\xe3\x7a\xd0\xfb\xad\x8b\x77\x48\xdd\xdb\xcf\x30\xb3\x9e\x80\x46\x6c\x61\xc7\x33\x41\x5e\x72\xb9\xf4\x2d\x5f\xad\x0b\xf3\x5f\x04\x1e\xb5\x63\x1e\xde\xd0\x03\x14\xc6\x6c\x48\x78\xb3\x51\x41\x6e\x5c\x6b\x90\x96\xf2\xa7\x08\x8a\x24\x38\x7e\x5d\x01\x49\xc5\x23\x73\x9f\x84\xf5\x02\xc7\x02\x03\x01\x00\x01")) + + (CASE_S(QType::OPENPGPKEY, "mQINBFUIXh0BEADNPlL6NpWEaR2KJx6p19scIVpsBIo7UqzCIzeFbRJaGDhn/HlQgcwAalcVNmWUX0ZQsrdn9CEfLWuFu9ON2o1TslYiwn+oSAlH2raFm2eyJTp/iM7IUUCte5jmf3d+L9rjVI7JjmMnbVo6SVY2KDDD72dULcg7IqYcCAN4CT+tPZP5y4cYf+DxRlpxhxvqqiGyAi6lAcJ24/8fJ4hsG0lS1vU12LWeWTHa5aRMM+x9kmv3GYdXG+FxFqZw52kZEnAscpC2ymbX+1YFCr8sjGYGde/D+5cLvuu4PGNZ4fkSeS+0yXve/s6u1mX6RkkF6SOGWuJfBJOGdWzYwber9kqgqpHTjpr8HOybzVroBijtTlB/tommIUd4BTk9Jv4fv2gA4UkC13UM9KBF1NnzUnKC+Js49O3mj0HZDoCrkWMnZyDsEmhMyQPU6YRFHWmB6OTKeD/Znk+b1uz+HIBgrbNuiG/A0c00Vnj7lR4p94oOuypI00XusLsJwPsjI4EgFGKdoRtM0spJhi+3gf88Vq0NENBaFVHLBGWVFaVrffurGcDZYUAdnvm8jSPCgBPfFxpZutexNkLjyaaXjDtga5/n5gSd/3RpWCvp9u3W5jcTNDZF4TORnOXUWHcot/+XmyH8/+cn8ydt0prOLGQ+FtdI+AWyMCXHen6aaZ1jeSLZqwARAQABtFpwZG5zIHJlZ3Jlc3Npb24gdGVzdGluZyBrZXkgKG9ubHkgZm9yIHRlc3RpbmcgdGhlIG9wZW5wZ3BrZXkgcnIpIDxyZWdyZXNzaW9uQHBvd2VyZG5zLm9yZz6JAjcEEwEIACEFAlUIXh0CGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQPr/KqoyK2Z7A6Q//YOBu8nwt+fguSo/vyCln0PqnTiBm4RvE2gPDUnsKuoXoP5F56XHBXKl9kEgmycht/nc7c7NRHzUhacM2RQau6CgNZE8KLaqDTKlEuc/ANtrnGGYG8gMId4TlzU5taLEA8yrHIHnwnMuDDpx1a0ETkbYCrj7CynqdhXCABqFjgRL7Qb37UnLPE7YdFt7fRGwZVLnb3GVZLKHurZ0TANvLdRVDST3f0lCcYMppPbHAvi2MIU71FPGkms++tj4gTltq0VRvrMNm1e5v4+hHZ++QN4sm4+DJGlo7l850gnMXc7c7GkRGtg8gV0h5k5jX5icdgxyvENTuBQ+QprkYTRh9uYzpoTQ+NYRZlgaJxxaDIv1K/kb3oPtnAEKJBC02IZbB0EiS3R5pxYXhUNoWV7ez2A4hX1L+tfvlgCAbbQ/cBLvqXgpgsf9x4ygSi52vQBy3twZyrtLsogxacxADfPcyleHtju/+lSku+Z6+W6OojA0kY2HlaMyQATJLIXd+6NE/tYy70RsU9Oq0OyVTjxh21SPLsExeSwSfciVSLn7IuKGIOV82MEHFhpo1Uhv+G52J8T1fI730sS4Tl5DekLaCz1pg/FmI/EQeAsYqm98uDAaFQcs6gDse8VYGmp2XYsoCW72as8ElKmMIbQ/xD7qxDORLmjCtVoyKH19+s6Pp61a5Ag0EVQheHQEQAMN6pcLJUhw9bfO5kqhLv4prt0AqVBUok6U8tIaEc9vDaasBcFHXgPsoOG97DXB6BdvsHuK/5uMVH5PNe58MLp08iCoIt0C0CbN3+D9Qbeg37AyKyFanB/CXq1tPKVCJc6BMNkO/BswnUsTTmlcd4GovpaJUOOZzblGUQBbhzRohhmOGfdsScGeeYME/yNFqzt1ZArV4va1hOLOUpNFv9TOy0ZVi/yDi+sYA9fCSZU9alWI/cbBct5I+3bh1l26umlZsYQm8uqnSgiQWpRm6UJO6xQbmUN9GzCYyKCmpzZRduqqjjtiF10W1yzioTfTtq2cvU6PdINYY8w2UuOjRd9gChtvGuduOIwqlRTYSaXX1dDoFe1vWqZzRm+pIDumO9eX5jMmzFXLDG2pD2l97zoSjVFf/pYoBasgX43e3V/aEk9PUgXbYFm2QxFMcIYSO9GEDMoE+QxoMXf1UjLxMCK5gD5iHL3Ff2zyXLzlTZE+fHPMLcAkzcp2u6pJ9xpAGekqqeqnISXZ2o8yXsqv8NVvl1zaSiSqU+kak9mIg/2+WC9W1qO2PeSLW2tiis980QnmyDOBg2oL01ITh/u+GTodEGwfRYJoNAJgUjcUMpWl0LuoG8lG6wukhA4QYFWpf2QPVgTR63VbpFgwCnUcSEPqHB0BRCsDHsd0k+/YSuPolABEBAAGJAh8EGAEIAAkFAlUIXh0CGwwACgkQPr/KqoyK2Z6zPA/+PkJTzP8kQw4GW0x2ZxXfOmkRVYpSEoHehf6y9YFN00+T8pb71RGItvuX5v6oPKPClOnIVg2WVHOq6Q3HsXEzl7oIbOtPE98WXHiVXud/djc54uHz9WjSPfy/idP7SMslo29BHR/K9nQkiGtayD57wdxgbLXObE3fA0gl4AsWl1EZzNcWVL4SIrvnBGpYIUGBcsTIiP3p09bu4Qf6HjJRXZlBuizigIgeO39l/G6tb6GA1cnbq4y6aCtQeXHLrnvak1jRqznlJWUqS1mQgOPF1MuOduHAvQbfMBQXAEfgOTzuH9PuKoGm7MePwTrU5GsOpNgS4LbvIRODJxYD+vIwA5BniijgfN9aj9KQVMURrd4Np7i0EVmj8P9FtNgYsEaDt7laGpNB9+9Y9heb6kNEulF7KI7y8CKikgvFGHHCyX2BCCbQBqi6wbEGq16qkTJmesYu9ig4v4xD/Q/cLJFziJLjEcWsL7hq7q2o6e7NL6hf5aTH0/bdeMXMqRzDCAFQ5Z+x0QUCgVonxzj+CuTD/LeOs/QHu/9emvm9EOMYY/X9vidLf58PT/AMqMiYbNWty6qY6k2LMw74Yd4+hO+Tjrk8MrqbCUs9h6ih9IOCo68JTWQQbgWSk2TAyd3U4OqTyBnHWr0HhHDRTOxyDbZUtXbk/r4Q4gTcAt+qjpswPyk=", "\x99\x02\x0d\x04\x55\x08\x5e\x1d\x01\x10\x00\xcd\x3e\x52\xfa\x36\x95\x84\x69\x1d\x8a\x27\x1e\xa9\xd7\xdb\x1c\x21\x5a\x6c\x04\x8a\x3b\x52\xac\xc2\x23\x37\x85\x6d\x12\x5a\x18\x38\x67\xfc\x79\x50\x81\xcc\x00\x6a\x57\x15\x36\x65\x94\x5f\x46\x50\xb2\xb7\x67\xf4\x21\x1f\x2d\x6b\x85\xbb\xd3\x8d\xda\x8d\x53\xb2\x56\x22\xc2\x7f\xa8\x48\x09\x47\xda\xb6\x85\x9b\x67\xb2\x25\x3a\x7f\x88\xce\xc8\x51\x40\xad\x7b\x98\xe6\x7f\x77\x7e\x2f\xda\xe3\x54\x8e\xc9\x8e\x63\x27\x6d\x5a\x3a\x49\x56\x36\x28\x30\xc3\xef\x67\x54\x2d\xc8\x3b\x22\xa6\x1c\x08\x03\x78\x09\x3f\xad\x3d\x93\xf9\xcb\x87\x18\x7f\xe0\xf1\x46\x5a\x71\x87\x1b\xea\xaa\x21\xb2\x02\x2e\xa5\x01\xc2\x76\xe3\xff\x1f\x27\x88\x6c\x1b\x49\x52\xd6\xf5\x35\xd8\xb5\x9e\x59\x31\xda\xe5\xa4\x4c\x33\xec\x7d\x92\x6b\xf7\x19\x87\x57\x1b\xe1\x71\x16\xa6\x70\xe7\x69\x19\x12\x70\x2c\x72\x90\xb6\xca\x66\xd7\xfb\x56\x05\x0a\xbf\x2c\x8c\x66\x06\x75\xef\xc3\xfb\x97\x0b\xbe\xeb\xb8\x3c\x63\x59\xe1\xf9\x12\x79\x2f\xb4\xc9\x7b\xde\xfe\xce\xae\xd6\x65\xfa\x46\x49\x05\xe9\x23\x86\x5a\xe2\x5f\x04\x93\x86\x75\x6c\xd8\xc1\xb7\xab\xf6\x4a\xa0\xaa\x91\xd3\x8e\x9a\xfc\x1c\xec\x9b\xcd\x5a\xe8\x06\x28\xed\x4e\x50\x7f\xb6\x89\xa6\x21\x47\x78\x05\x39\x3d\x26\xfe\x1f\xbf\x68\x00\xe1\x49\x02\xd7\x75\x0c\xf4\xa0\x45\xd4\xd9\xf3\x52\x72\x82\xf8\x9b\x38\xf4\xed\xe6\x8f\x41\xd9\x0e\x80\xab\x91\x63\x27\x67\x20\xec\x12\x68\x4c\xc9\x03\xd4\xe9\x84\x45\x1d\x69\x81\xe8\xe4\xca\x78\x3f\xd9\x9e\x4f\x9b\xd6\xec\xfe\x1c\x80\x60\xad\xb3\x6e\x88\x6f\xc0\xd1\xcd\x34\x56\x78\xfb\x95\x1e\x29\xf7\x8a\x0e\xbb\x2a\x48\xd3\x45\xee\xb0\xbb\x09\xc0\xfb\x23\x23\x81\x20\x14\x62\x9d\xa1\x1b\x4c\xd2\xca\x49\x86\x2f\xb7\x81\xff\x3c\x56\xad\x0d\x10\xd0\x5a\x15\x51\xcb\x04\x65\x95\x15\xa5\x6b\x7d\xfb\xab\x19\xc0\xd9\x61\x40\x1d\x9e\xf9\xbc\x8d\x23\xc2\x80\x13\xdf\x17\x1a\x59\xba\xd7\xb1\x36\x42\xe3\xc9\xa6\x97\x8c\x3b\x60\x6b\x9f\xe7\xe6\x04\x9d\xff\x74\x69\x58\x2b\xe9\xf6\xed\xd6\xe6\x37\x13\x34\x36\x45\xe1\x33\x91\x9c\xe5\xd4\x58\x77\x28\xb7\xff\x97\x9b\x21\xfc\xff\xe7\x27\xf3\x27\x6d\xd2\x9a\xce\x2c\x64\x3e\x16\xd7\x48\xf8\x05\xb2\x30\x25\xc7\x7a\x7e\x9a\x69\x9d\x63\x79\x22\xd9\xab\x00\x11\x01\x00\x01\xb4\x5a\x70\x64\x6e\x73\x20\x72\x65\x67\x72\x65\x73\x73\x69\x6f\x6e\x20\x74\x65\x73\x74\x69\x6e\x67\x20\x6b\x65\x79\x20\x28\x6f\x6e\x6c\x79\x20\x66\x6f\x72\x20\x74\x65\x73\x74\x69\x6e\x67\x20\x74\x68\x65\x20\x6f\x70\x65\x6e\x70\x67\x70\x6b\x65\x79\x20\x72\x72\x29\x20\x3c\x72\x65\x67\x72\x65\x73\x73\x69\x6f\x6e\x40\x70\x6f\x77\x65\x72\x64\x6e\x73\x2e\x6f\x72\x67\x3e\x89\x02\x37\x04\x13\x01\x08\x00\x21\x05\x02\x55\x08\x5e\x1d\x02\x1b\x03\x05\x0b\x09\x08\x07\x02\x06\x15\x08\x09\x0a\x0b\x02\x04\x16\x02\x03\x01\x02\x1e\x01\x02\x17\x80\x00\x0a\x09\x10\x3e\xbf\xca\xaa\x8c\x8a\xd9\x9e\xc0\xe9\x0f\xff\x60\xe0\x6e\xf2\x7c\x2d\xf9\xf8\x2e\x4a\x8f\xef\xc8\x29\x67\xd0\xfa\xa7\x4e\x20\x66\xe1\x1b\xc4\xda\x03\xc3\x52\x7b\x0a\xba\x85\xe8\x3f\x91\x79\xe9\x71\xc1\x5c\xa9\x7d\x90\x48\x26\xc9\xc8\x6d\xfe\x77\x3b\x73\xb3\x51\x1f\x35\x21\x69\xc3\x36\x45\x06\xae\xe8\x28\x0d\x64\x4f\x0a\x2d\xaa\x83\x4c\xa9\x44\xb9\xcf\xc0\x36\xda\xe7\x18\x66\x06\xf2\x03\x08\x77\x84\xe5\xcd\x4e\x6d\x68\xb1\x00\xf3\x2a\xc7\x20\x79\xf0\x9c\xcb\x83\x0e\x9c\x75\x6b\x41\x13\x91\xb6\x02\xae\x3e\xc2\xca\x7a\x9d\x85\x70\x80\x06\xa1\x63\x81\x12\xfb\x41\xbd\xfb\x52\x72\xcf\x13\xb6\x1d\x16\xde\xdf\x44\x6c\x19\x54\xb9\xdb\xdc\x65\x59\x2c\xa1\xee\xad\x9d\x13\x00\xdb\xcb\x75\x15\x43\x49\x3d\xdf\xd2\x50\x9c\x60\xca\x69\x3d\xb1\xc0\xbe\x2d\x8c\x21\x4e\xf5\x14\xf1\xa4\x9a\xcf\xbe\xb6\x3e\x20\x4e\x5b\x6a\xd1\x54\x6f\xac\xc3\x66\xd5\xee\x6f\xe3\xe8\x47\x67\xef\x90\x37\x8b\x26\xe3\xe0\xc9\x1a\x5a\x3b\x97\xce\x74\x82\x73\x17\x73\xb7\x3b\x1a\x44\x46\xb6\x0f\x20\x57\x48\x79\x93\x98\xd7\xe6\x27\x1d\x83\x1c\xaf\x10\xd4\xee\x05\x0f\x90\xa6\xb9\x18\x4d\x18\x7d\xb9\x8c\xe9\xa1\x34\x3e\x35\x84\x59\x96\x06\x89\xc7\x16\x83\x22\xfd\x4a\xfe\x46\xf7\xa0\xfb\x67\x00\x42\x89\x04\x2d\x36\x21\x96\xc1\xd0\x48\x92\xdd\x1e\x69\xc5\x85\xe1\x50\xda\x16\x57\xb7\xb3\xd8\x0e\x21\x5f\x52\xfe\xb5\xfb\xe5\x80\x20\x1b\x6d\x0f\xdc\x04\xbb\xea\x5e\x0a\x60\xb1\xff\x71\xe3\x28\x12\x8b\x9d\xaf\x40\x1c\xb7\xb7\x06\x72\xae\xd2\xec\xa2\x0c\x5a\x73\x10\x03\x7c\xf7\x32\x95\xe1\xed\x8e\xef\xfe\x95\x29\x2e\xf9\x9e\xbe\x5b\xa3\xa8\x8c\x0d\x24\x63\x61\xe5\x68\xcc\x90\x01\x32\x4b\x21\x77\x7e\xe8\xd1\x3f\xb5\x8c\xbb\xd1\x1b\x14\xf4\xea\xb4\x3b\x25\x53\x8f\x18\x76\xd5\x23\xcb\xb0\x4c\x5e\x4b\x04\x9f\x72\x25\x52\x2e\x7e\xc8\xb8\xa1\x88\x39\x5f\x36\x30\x41\xc5\x86\x9a\x35\x52\x1b\xfe\x1b\x9d\x89\xf1\x3d\x5f\x23\xbd\xf4\xb1\x2e\x13\x97\x90\xde\x90\xb6\x82\xcf\x5a\x60\xfc\x59\x88\xfc\x44\x1e\x02\xc6\x2a\x9b\xdf\x2e\x0c\x06\x85\x41\xcb\x3a\x80\x3b\x1e\xf1\x56\x06\x9a\x9d\x97\x62\xca\x02\x5b\xbd\x9a\xb3\xc1\x25\x2a\x63\x08\x6d\x0f\xf1\x0f\xba\xb1\x0c\xe4\x4b\x9a\x30\xad\x56\x8c\x8a\x1f\x5f\x7e\xb3\xa3\xe9\xeb\x56\xb9\x02\x0d\x04\x55\x08\x5e\x1d\x01\x10\x00\xc3\x7a\xa5\xc2\xc9\x52\x1c\x3d\x6d\xf3\xb9\x92\xa8\x4b\xbf\x8a\x6b\xb7\x40\x2a\x54\x15\x28\x93\xa5\x3c\xb4\x86\x84\x73\xdb\xc3\x69\xab\x01\x70\x51\xd7\x80\xfb\x28\x38\x6f\x7b\x0d\x70\x7a\x05\xdb\xec\x1e\xe2\xbf\xe6\xe3\x15\x1f\x93\xcd\x7b\x9f\x0c\x2e\x9d\x3c\x88\x2a\x08\xb7\x40\xb4\x09\xb3\x77\xf8\x3f\x50\x6d\xe8\x37\xec\x0c\x8a\xc8\x56\xa7\x07\xf0\x97\xab\x5b\x4f\x29\x50\x89\x73\xa0\x4c\x36\x43\xbf\x06\xcc\x27\x52\xc4\xd3\x9a\x57\x1d\xe0\x6a\x2f\xa5\xa2\x54\x38\xe6\x73\x6e\x51\x94\x40\x16\xe1\xcd\x1a\x21\x86\x63\x86\x7d\xdb\x12\x70\x67\x9e\x60\xc1\x3f\xc8\xd1\x6a\xce\xdd\x59\x02\xb5\x78\xbd\xad\x61\x38\xb3\x94\xa4\xd1\x6f\xf5\x33\xb2\xd1\x95\x62\xff\x20\xe2\xfa\xc6\x00\xf5\xf0\x92\x65\x4f\x5a\x95\x62\x3f\x71\xb0\x5c\xb7\x92\x3e\xdd\xb8\x75\x97\x6e\xae\x9a\x56\x6c\x61\x09\xbc\xba\xa9\xd2\x82\x24\x16\xa5\x19\xba\x50\x93\xba\xc5\x06\xe6\x50\xdf\x46\xcc\x26\x32\x28\x29\xa9\xcd\x94\x5d\xba\xaa\xa3\x8e\xd8\x85\xd7\x45\xb5\xcb\x38\xa8\x4d\xf4\xed\xab\x67\x2f\x53\xa3\xdd\x20\xd6\x18\xf3\x0d\x94\xb8\xe8\xd1\x77\xd8\x02\x86\xdb\xc6\xb9\xdb\x8e\x23\x0a\xa5\x45\x36\x12\x69\x75\xf5\x74\x3a\x05\x7b\x5b\xd6\xa9\x9c\xd1\x9b\xea\x48\x0e\xe9\x8e\xf5\xe5\xf9\x8c\xc9\xb3\x15\x72\xc3\x1b\x6a\x43\xda\x5f\x7b\xce\x84\xa3\x54\x57\xff\xa5\x8a\x01\x6a\xc8\x17\xe3\x77\xb7\x57\xf6\x84\x93\xd3\xd4\x81\x76\xd8\x16\x6d\x90\xc4\x53\x1c\x21\x84\x8e\xf4\x61\x03\x32\x81\x3e\x43\x1a\x0c\x5d\xfd\x54\x8c\xbc\x4c\x08\xae\x60\x0f\x98\x87\x2f\x71\x5f\xdb\x3c\x97\x2f\x39\x53\x64\x4f\x9f\x1c\xf3\x0b\x70\x09\x33\x72\x9d\xae\xea\x92\x7d\xc6\x90\x06\x7a\x4a\xaa\x7a\xa9\xc8\x49\x76\x76\xa3\xcc\x97\xb2\xab\xfc\x35\x5b\xe5\xd7\x36\x92\x89\x2a\x94\xfa\x46\xa4\xf6\x62\x20\xff\x6f\x96\x0b\xd5\xb5\xa8\xed\x8f\x79\x22\xd6\xda\xd8\xa2\xb3\xdf\x34\x42\x79\xb2\x0c\xe0\x60\xda\x82\xf4\xd4\x84\xe1\xfe\xef\x86\x4e\x87\x44\x1b\x07\xd1\x60\x9a\x0d\x00\x98\x14\x8d\xc5\x0c\xa5\x69\x74\x2e\xea\x06\xf2\x51\xba\xc2\xe9\x21\x03\x84\x18\x15\x6a\x5f\xd9\x03\xd5\x81\x34\x7a\xdd\x56\xe9\x16\x0c\x02\x9d\x47\x12\x10\xfa\x87\x07\x40\x51\x0a\xc0\xc7\xb1\xdd\x24\xfb\xf6\x12\xb8\xfa\x25\x00\x11\x01\x00\x01\x89\x02\x1f\x04\x18\x01\x08\x00\x09\x05\x02\x55\x08\x5e\x1d\x02\x1b\x0c\x00\x0a\x09\x10\x3e\xbf\xca\xaa\x8c\x8a\xd9\x9e\xb3\x3c\x0f\xfe\x3e\x42\x53\xcc\xff\x24\x43\x0e\x06\x5b\x4c\x76\x67\x15\xdf\x3a\x69\x11\x55\x8a\x52\x12\x81\xde\x85\xfe\xb2\xf5\x81\x4d\xd3\x4f\x93\xf2\x96\xfb\xd5\x11\x88\xb6\xfb\x97\xe6\xfe\xa8\x3c\xa3\xc2\x94\xe9\xc8\x56\x0d\x96\x54\x73\xaa\xe9\x0d\xc7\xb1\x71\x33\x97\xba\x08\x6c\xeb\x4f\x13\xdf\x16\x5c\x78\x95\x5e\xe7\x7f\x76\x37\x39\xe2\xe1\xf3\xf5\x68\xd2\x3d\xfc\xbf\x89\xd3\xfb\x48\xcb\x25\xa3\x6f\x41\x1d\x1f\xca\xf6\x74\x24\x88\x6b\x5a\xc8\x3e\x7b\xc1\xdc\x60\x6c\xb5\xce\x6c\x4d\xdf\x03\x48\x25\xe0\x0b\x16\x97\x51\x19\xcc\xd7\x16\x54\xbe\x12\x22\xbb\xe7\x04\x6a\x58\x21\x41\x81\x72\xc4\xc8\x88\xfd\xe9\xd3\xd6\xee\xe1\x07\xfa\x1e\x32\x51\x5d\x99\x41\xba\x2c\xe2\x80\x88\x1e\x3b\x7f\x65\xfc\x6e\xad\x6f\xa1\x80\xd5\xc9\xdb\xab\x8c\xba\x68\x2b\x50\x79\x71\xcb\xae\x7b\xda\x93\x58\xd1\xab\x39\xe5\x25\x65\x2a\x4b\x59\x90\x80\xe3\xc5\xd4\xcb\x8e\x76\xe1\xc0\xbd\x06\xdf\x30\x14\x17\x00\x47\xe0\x39\x3c\xee\x1f\xd3\xee\x2a\x81\xa6\xec\xc7\x8f\xc1\x3a\xd4\xe4\x6b\x0e\xa4\xd8\x12\xe0\xb6\xef\x21\x13\x83\x27\x16\x03\xfa\xf2\x30\x03\x90\x67\x8a\x28\xe0\x7c\xdf\x5a\x8f\xd2\x90\x54\xc5\x11\xad\xde\x0d\xa7\xb8\xb4\x11\x59\xa3\xf0\xff\x45\xb4\xd8\x18\xb0\x46\x83\xb7\xb9\x5a\x1a\x93\x41\xf7\xef\x58\xf6\x17\x9b\xea\x43\x44\xba\x51\x7b\x28\x8e\xf2\xf0\x22\xa2\x92\x0b\xc5\x18\x71\xc2\xc9\x7d\x81\x08\x26\xd0\x06\xa8\xba\xc1\xb1\x06\xab\x5e\xaa\x91\x32\x66\x7a\xc6\x2e\xf6\x28\x38\xbf\x8c\x43\xfd\x0f\xdc\x2c\x91\x73\x88\x92\xe3\x11\xc5\xac\x2f\xb8\x6a\xee\xad\xa8\xe9\xee\xcd\x2f\xa8\x5f\xe5\xa4\xc7\xd3\xf6\xdd\x78\xc5\xcc\xa9\x1c\xc3\x08\x01\x50\xe5\x9f\xb1\xd1\x05\x02\x81\x5a\x27\xc7\x38\xfe\x0a\xe4\xc3\xfc\xb7\x8e\xb3\xf4\x07\xbb\xff\x5e\x9a\xf9\xbd\x10\xe3\x18\x63\xf5\xfd\xbe\x27\x4b\x7f\x9f\x0f\x4f\xf0\x0c\xa8\xc8\x98\x6c\xd5\xad\xcb\xaa\x98\xea\x4d\x8b\x33\x0e\xf8\x61\xde\x3e\x84\xef\x93\x8e\xb9\x3c\x32\xba\x9b\x09\x4b\x3d\x87\xa8\xa1\xf4\x83\x82\xa3\xaf\x09\x4d\x64\x10\x6e\x05\x92\x93\x64\xc0\xc9\xdd\xd4\xe0\xea\x93\xc8\x19\xc7\x5a\xbd\x07\x84\x70\xd1\x4c\xec\x72\x0d\xb6\x54\xb5\x76\xe4\xfe\xbe\x10\xe2\x04\xdc\x02\xdf\xaa\x8e\x9b\x30\x3f\x29")) + + (CASE_S(QType::SPF, "\"v=spf1 a:mail.rec.test ~all\"", "\x1bv=spf1 a:mail.rec.test ~all")) + (CASE_S(QType::EUI48, "00-11-22-33-44-55", "\x00\x11\x22\x33\x44\x55")) + (CASE_S(QType::EUI64, "00-11-22-33-44-55-66-77", "\x00\x11\x22\x33\x44\x55\x66\x77")) + (CASE_S(QType::TKEY, "gss-tsig. 12345 12345 3 21 4 dGVzdA== 4 dGVzdA==", "\x08gss-tsig\x00\x00\x00\x30\x39\x00\x00\x30\x39\x00\x03\x00\x15\x00\x04test\x00\x04test")) + (CASE_S(QType::TSIG, "HMAC-MD5.SIG-ALG.REG.INT. 1368386956 60 16 TkbpD66/Mtgo8GUEFZIwhg== 12345 0 0", "\x08HMAC-MD5\x07SIG-ALG\x03REG\x03INT\x00\x00\x00\x51\x8f\xed\x8c\x00\x3c\x00\x10\x4e\x46\xe9\x0f\xae\xbf\x32\xd8\x28\xf0\x65\x04\x15\x92\x30\x86\x30\x39\x00\x00\x00\x00")) + (CASE_S(QType::TSIG, "HMAC-MD5.SIG-ALG.REG.INT. 1368386956 60 16 TkbpD66/Mtgo8GUEFZIwhg== 12345 18 16 TkbpD66/Mtgo8GUEFZIwhg==", "\x08HMAC-MD5\x07SIG-ALG\x03REG\x03INT\x00\x00\x00\x51\x8f\xed\x8c\x00\x3c\x00\x10\x4e\x46\xe9\x0f\xae\xbf\x32\xd8\x28\xf0\x65\x04\x15\x92\x30\x86\x30\x39\x00\x12\x00\x10\x4e\x46\xe9\x0f\xae\xbf\x32\xd8\x28\xf0\x65\x04\x15\x92\x30\x86")) + (CASE_S(QType::URI, "10000 1 \"ftp://ftp1.example.com/public\"", "\x27\x10\x00\x01\x66\x74\x70\x3a\x2f\x2f\x66\x74\x70\x31\x2e\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x70\x75\x62\x6c\x69\x63")) + (CASE_S(QType::URI, "10 1 \"ftp://ftp1.example.com/public/with/a/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/very/long/url\"", "\x00\x0a\x00\x01\x66\x74\x70\x3a\x2f\x2f\x66\x74\x70\x31\x2e\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x70\x75\x62\x6c\x69\x63\x2f\x77\x69\x74\x68\x2f\x61\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x76\x65\x72\x79\x2f\x6c\x6f\x6e\x67\x2f\x75\x72\x6c")) + (CASE_S(QType::CAA, "0 issue \"example.net\"", "\x00\x05\x69\x73\x73\x75\x65\x65\x78\x61\x6d\x70\x6c\x65\x2e\x6e\x65\x74")) + (CASE_S(QType::DLV, "20642 8 2 04443abe7e94c3985196beae5d548c727b044dda5151e60d7cd76a9fd931d00e", "\x50\xa2\x08\x02\x04\x44\x3a\xbe\x7e\x94\xc3\x98\x51\x96\xbe\xae\x5d\x54\x8c\x72\x7b\x04\x4d\xda\x51\x51\xe6\x0d\x7c\xd7\x6a\x9f\xd9\x31\xd0\x0e")) + (CASE_S((QType::typeenum)65226,"\\# 3 414243","\x41\x42\x43")) + +; + + int n=0; + int lq=-1; + for(const cases_t::value_type& val : cases) { + const QType q(val.get<0>()); + const std::string& inval = val.get<1>(); + const std::string& zoneval = val.get<2>(); + const std::string& lineval = val.get<3>(); + const broken_marker broken = val.get<4>(); + + if (lq != q.getCode()) n = 0; + BOOST_CHECK_MESSAGE(q.getCode() >= lq, "record types should be sorted such that " << q.getCode() << " >= " << lq); + lq = q.getCode(); + n++; + BOOST_TEST_CHECKPOINT("Checking record type " << q.getName() << " test #" << n); + BOOST_TEST_MESSAGE("Checking record type " << q.getName() << " test #" << n); + try { + std::string recData; + auto rec = DNSRecordContent::mastermake(q.getCode(), 1, inval); + BOOST_CHECK_MESSAGE(rec != NULL, "mastermake( " << q.getCode() << ", 1, " << inval << ") should not return NULL"); + if (rec == NULL) continue; + // now verify the record (note that this will be same as *zone* value (except for certain QTypes) + + switch(q.getCode()) { + case QType::NS: + case QType::PTR: + case QType::MX: + case QType::CNAME: + case QType::SOA: + case QType::TXT: + // check *input* value instead + REC_CHECK_EQUAL(rec->getZoneRepresentation(), inval); + break; + default: + REC_CHECK_EQUAL(rec->getZoneRepresentation(), zoneval); + } + recData = rec->serialize(DNSName("rec.test")); + + std::shared_ptr rec2 = DNSRecordContent::unserialize(DNSName("rec.test"),q.getCode(),recData); + BOOST_CHECK_MESSAGE(rec2 != NULL, "unserialize(rec.test, " << q.getCode() << ", recData) should not return NULL"); + if (rec2 == NULL) continue; + // now verify the zone representation (here it can be different!) + REC_CHECK_EQUAL(rec2->getZoneRepresentation(), zoneval); + // and last, check the wire format (using hex format for error readability) + string cmpData = makeHexDump(lineval); + recData = makeHexDump(recData); + REC_CHECK_EQUAL(recData, cmpData); + } catch (std::runtime_error &err) { + REC_CHECK_MESSAGE(false, q.getName() << ": " << err.what()); + continue; + } + REC_FAIL_XSUCCESS(q.getName() << " test #" << n << " has unexpectedly passed") + } +} + +bool test_dnsrecords_cc_predicate( std::exception const &ex ) { return true; } + +// these *MUST NOT* parse properly! +BOOST_AUTO_TEST_CASE(test_record_types_bad_values) { + enum class case_type_t { zone, wire }; + + // qtype, value, zone/wire format, broken + typedef boost::tuple case_t; + typedef std::list cases_t; + +#define ZONE_CASE(type, input) case_t(type, BINARY(input), case_type_t::zone, broken_marker::WORKING) +#define WIRE_CASE(type, input) case_t(type, BINARY(input), case_type_t::wire, broken_marker::WORKING) +#define BROKEN_ZONE_CASE(type, input) case_t(type, BINARY(input), case_type_t::zone, broken_marker::BROKEN) +#define BROKEN_WIRE_CASE(type, input) case_t(type, BINARY(input), case_type_t::wire, broken_marker::BROKEN) + + const cases_t cases = boost::assign::list_of + (ZONE_CASE(QType::A, "932.521.256.42")) // hollywood IP + (ZONE_CASE(QType::A, "932.521")) // truncated hollywood IP + (ZONE_CASE(QType::A, "10.0")) // truncated IP + (ZONE_CASE(QType::A, "10.0.0.1.")) // trailing dot + (ZONE_CASE(QType::A, "10.0.0.")) // trailing dot + (ZONE_CASE(QType::A, ".0.0.1")) // empty octet + (ZONE_CASE(QType::A, "10..0.1")) // empty octet + (WIRE_CASE(QType::A, "\xca\xec\x00")) // truncated wire value + (ZONE_CASE(QType::A, "127.0.0.1 evil data")) // trailing garbage + (ZONE_CASE(QType::AAAA, "23:00")) // time when this test was written + (ZONE_CASE(QType::AAAA, "23:00::15::43")) // double compression + (ZONE_CASE(QType::AAAA, "2a23:00::15::")) // ditto + (WIRE_CASE(QType::AAAA, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff")) // truncated wire value +// empty label, must be broken + (ZONE_CASE(QType::CNAME, "name..example.com.")) +// overly large label (64), must be broken + (ZONE_CASE(QType::CNAME, "1234567890123456789012345678901234567890123456789012345678901234.example.com.")) +// local overly large name (256), must be broken + (ZONE_CASE(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123.rec.test.")) +// non-local overly large name (256), must be broken + (ZONE_CASE(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012.")) + (ZONE_CASE(QType::SOA, "ns.rec.test hostmaster.test.rec 20130512010 3600 3600 604800 120")) // too long serial +; + + int n=0; + int lq=-1; + + for(const cases_t::value_type& val : cases) { + const QType q(val.get<0>()); + const std::string& input = val.get<1>(); + const case_type_t case_type = val.get<2>(); + const broken_marker broken = val.get<3>(); + + if (lq != q.getCode()) n = 0; + lq = q.getCode(); + n++; + BOOST_TEST_CHECKPOINT("Checking bad value for record type " << q.getName() << " test #" << n); + BOOST_TEST_MESSAGE("Checking bad value for record type " << q.getName() << " test #" << n); + + vector packet; + DNSPacketWriter pw(packet, DNSName("unit.test"), q.getCode()); + + if (case_type == case_type_t::wire) { + BOOST_WARN_MESSAGE(false, "wire checks not supported"); + continue; + } + + if (broken_marker::BROKEN == broken) { + bool success=true; + BOOST_WARN_EXCEPTION( + { + auto drc = DNSRecordContent::mastermake(q.getCode(), 1, input); + pw.startRecord(DNSName("unit.test"), q.getCode()); + drc->toPacket(pw); + success=false; + }, + std::exception, test_dnsrecords_cc_predicate + ); + if (success) REC_FAIL_XSUCCESS(q.getName() << " test #" << n << " has unexpectedly passed"); // a bad record was detected when it was supposed not to be detected + } else { + BOOST_CHECK_EXCEPTION( + { + auto drc = DNSRecordContent::mastermake(q.getCode(), 1, input); + pw.startRecord(DNSName("unit.test"), q.getCode()); + drc->toPacket(pw); + }, + std::exception, test_dnsrecords_cc_predicate + ); + } + }; +} + +// special opt record test, because opt is odd +BOOST_AUTO_TEST_CASE(test_opt_record_in) { + EDNSOpts eo; + + // test that nsid gets parsed into system + std::string packet("\xf0\x01\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x00\x00\x00\x10\x00\x04\x7f\x00\x00\x01\x00\x00\x29\x05\x00\x00\x00\x00\x00\x00\x0c\x00\x03\x00\x08powerdns",89); + OPTRecordContent::report(); + + MOADNSParser mdp(true, (char*)&*packet.begin(), (unsigned int)packet.size()); + + BOOST_CHECK_EQUAL(getEDNSOpts(mdp, &eo), true); + + // this should contain NSID now + BOOST_CHECK_EQUAL(eo.d_packetsize, 1280); + + // it should contain NSID option with value 'powerdns', and nothing else + BOOST_CHECK_EQUAL(eo.d_options.size(), 1); + BOOST_CHECK_EQUAL(eo.d_options[0].first, 3); // nsid + BOOST_CHECK_EQUAL(eo.d_options[0].second, "powerdns"); +} + +BOOST_AUTO_TEST_CASE(test_opt_record_out) { + vector pak; + vector > opts; + + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + pw.startRecord(DNSName("www.powerdns.com"), QType::A, 16, 1, DNSResourceRecord::ANSWER); + pw.xfrIP(htonl(0x7f000001)); + opts.push_back(pair(3, "powerdns")); + pw.addOpt(1280, 0, 0, opts); + pw.getHeader()->id = htons(0xf001); + pw.getHeader()->rd = 1; + pw.commit(); + + // see if we can build a DNS packet that looks like this... + std::string packet("\xf0\x01\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x10\x00\x04\x7f\x00\x00\x01\x00\x00\x29\x05\x00\x00\x00\x00\x00\x00\x0c\x00\x03\x00\x08powerdns",73); + + BOOST_CHECK_EQUAL(makeHexDump(std::string(pak.begin(),pak.end())), makeHexDump(packet)); +} + +// special record test, because EUI are odd +BOOST_AUTO_TEST_CASE(test_eui_records_in) { + + auto validEUI48=DNSRecordContent::mastermake(QType::EUI48, QClass::IN, "00-00-5e-00-53-2a"); + + BOOST_CHECK_THROW(auto invalidEUI48=DNSRecordContent::mastermake(QType::EUI48, QClass::IN, "00-00-5e-00-53-"), MOADNSException); + + auto validEUI64=DNSRecordContent::mastermake(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-2a"); + + BOOST_CHECK_THROW(auto invalidEUI64=DNSRecordContent::mastermake(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-"), MOADNSException); +} + +// special record test, because LOC is weird +BOOST_AUTO_TEST_CASE(test_loc_records_in) { + + auto validLOC=DNSRecordContent::mastermake(QType::LOC, QClass::IN, "52 22 23.000 N 4 53 32.000 E -2.00m 0.00m 10000m 10m"); + + BOOST_CHECK_THROW(auto invalidLOC=DNSRecordContent::mastermake(QType::LOC, QClass::IN, "52 22 23.000 N"), MOADNSException); + + vector packet; + DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::LOC, QClass::IN, 0); + writer.getHeader()->qr = 1; + writer.startRecord(DNSName("powerdns.com."), QType::LOC, 100, QClass::IN, DNSResourceRecord::ANSWER); + validLOC->toPacket(writer); + writer.commit(); + + MOADNSParser parser(false, reinterpret_cast(packet.data()), packet.size()); + + BOOST_CHECK_THROW(MOADNSParser failParser(false, reinterpret_cast(packet.data()), packet.size()-1), MOADNSException); +} + +// special record test, because NSEC records are odd +BOOST_AUTO_TEST_CASE(test_nsec_records_in) { + + { + auto validNSEC=DNSRecordContent::mastermake(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234"); + + vector packet; + DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC, QClass::IN, 0); + writer.getHeader()->qr = 1; + writer.startRecord(DNSName("powerdns.com."), QType::NSEC, 100, QClass::IN, DNSResourceRecord::ANSWER); + validNSEC->toPacket(writer); + writer.commit(); + + MOADNSParser parser(false, reinterpret_cast(packet.data()), packet.size()); + + BOOST_CHECK_THROW(MOADNSParser failParser(false, reinterpret_cast(packet.data()), packet.size()-1), MOADNSException); + } + + { + auto validNSEC3=DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG"); + + vector packet; + DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC3, QClass::IN, 0); + writer.getHeader()->qr = 1; + writer.startRecord(DNSName("powerdns.com."), QType::NSEC3, 100, QClass::IN, DNSResourceRecord::ANSWER); + validNSEC3->toPacket(writer); + writer.commit(); + + MOADNSParser parser(false, reinterpret_cast(packet.data()), packet.size()); + + BOOST_CHECK_THROW(MOADNSParser failParser(false, reinterpret_cast(packet.data()), packet.size()-1), MOADNSException); + } + + { + auto validNSEC3PARAM=DNSRecordContent::mastermake(QType::NSEC3PARAM, QClass::IN, "1 0 12 aabbccdd"); + + vector packet; + DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC3PARAM, QClass::IN, 0); + writer.getHeader()->qr = 1; + writer.startRecord(DNSName("powerdns.com."), QType::NSEC3PARAM, 100, QClass::IN, DNSResourceRecord::ANSWER); + validNSEC3PARAM->toPacket(writer); + writer.commit(); + + MOADNSParser parser(false, reinterpret_cast(packet.data()), packet.size()); + + BOOST_CHECK_THROW(MOADNSParser failParser(false, reinterpret_cast(packet.data()), packet.size()-1), MOADNSException); + } +} + +BOOST_AUTO_TEST_CASE(test_nsec_records_types) { + + { + auto validNSEC = DNSRecordContent::mastermake(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234"); + auto nsecContent = std::dynamic_pointer_cast(validNSEC); + BOOST_REQUIRE(nsecContent); + + for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC, static_cast(1234) }) { + BOOST_CHECK(nsecContent->isSet(type)); + } + BOOST_CHECK_EQUAL(nsecContent->isSet(QType::NSEC3), false); + BOOST_CHECK_EQUAL(nsecContent->numberOfTypesSet(), 5); + } + + { + auto nsecContent = std::make_shared(); + BOOST_CHECK_EQUAL(nsecContent->numberOfTypesSet(), 0); + BOOST_CHECK_EQUAL(nsecContent->isSet(QType::NSEC3), false); + + for (size_t idx = 0; idx < 65536; idx++) { + nsecContent->set(idx); + } + BOOST_CHECK_EQUAL(nsecContent->isSet(QType::NSEC3), true); + BOOST_CHECK_EQUAL(nsecContent->numberOfTypesSet(), 65536); + for (size_t idx = 0; idx < 65536; idx++) { + BOOST_CHECK(nsecContent->isSet(idx)); + } + } +} + +BOOST_AUTO_TEST_CASE(test_nsec3_records_types) { + + { + const std::string str = "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s a mx rrsig nsec3 type1234 type65535"; + auto validNSEC3 = DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, str); + auto nsec3Content = std::dynamic_pointer_cast(validNSEC3); + BOOST_REQUIRE(nsec3Content); + + for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC3, static_cast(1234), static_cast(65535) }) { + BOOST_CHECK(nsec3Content->isSet(type)); + } + BOOST_CHECK_EQUAL(nsec3Content->isSet(QType::NSEC), false); + BOOST_CHECK_EQUAL(nsec3Content->numberOfTypesSet(), 6); + auto str2 = nsec3Content->getZoneRepresentation(); + boost::to_lower(str2); + BOOST_CHECK_EQUAL(str2, str); + } + + { + std::string str = "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s"; + auto nsec3Content = std::make_shared(str); + BOOST_CHECK_EQUAL(nsec3Content->numberOfTypesSet(), 0); + BOOST_CHECK_EQUAL(nsec3Content->isSet(QType::NSEC), false); + + for (size_t idx = 0; idx < 65536; idx++) { + nsec3Content->set(idx); + str += " " + toLower(DNSRecordContent::NumberToType(idx)); + } + BOOST_CHECK_EQUAL(nsec3Content->isSet(QType::NSEC), true); + BOOST_CHECK_EQUAL(nsec3Content->numberOfTypesSet(), 65536); + for (size_t idx = 0; idx < 65536; idx++) { + BOOST_CHECK(nsec3Content->isSet(idx)); + } + auto str2 = nsec3Content->getZoneRepresentation(); + boost::to_lower(str2); + BOOST_CHECK_EQUAL(str2, str); + } + + { + DNSName qname("powerdns.com."); + /* check that we can have a NSEC3 with 0 types covered */ + const std::string salt = "aabbccdd"; + const std::string hash = "2vptu5timamqttgl4luu9kg21e0aor3s"; + const std::string str = "1 1 12 " + salt + " " + hash; + auto validNSEC3=DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, str); + + vector packet; + DNSPacketWriter writer(packet, qname, QType::NSEC3, QClass::IN, 0); + writer.getHeader()->qr = 1; + writer.startRecord(qname, QType::NSEC3, 100, QClass::IN, DNSResourceRecord::ANSWER); + validNSEC3->toPacket(writer); + writer.commit(); + + static const size_t expectedSize = sizeof(dnsheader) + qname.wirelength() + 2 /* QType */ + 2 /* QClass */ + + 2 /* name pointer */ + 2 /* QType */ + 2 /* QClass */ + + 2 /* rd length */ + 1 /* hash algo */ + 1 /* flags */ + 2 /*iterations */ + 1 /* salt length */ + salt.size() + + 1 /* hash length */ + fromBase32Hex(hash).size(); + BOOST_CHECK_EQUAL(packet.size(), expectedSize); + + MOADNSParser parser(false, reinterpret_cast(packet.data()), packet.size()); + BOOST_REQUIRE_EQUAL(parser.d_answers.size(), 1); + const auto& record = parser.d_answers.at(0).first; + BOOST_REQUIRE(record.d_type == QType::NSEC3); + BOOST_REQUIRE(record.d_class == QClass::IN); + auto content = std::dynamic_pointer_cast(record.d_content); + BOOST_REQUIRE(content); + BOOST_CHECK_EQUAL(content->numberOfTypesSet(), 0); + for (size_t idx = 0; idx < 65536; idx++) { + BOOST_CHECK_EQUAL(content->isSet(idx), false); + } + auto str2 = content->getZoneRepresentation(); + boost::to_lower(str2); + BOOST_CHECK_EQUAL(str2, str); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-dnswriter_cc.cc b/pdns/test-dnswriter_cc.cc new file mode 100644 index 0000000..d4158b8 --- /dev/null +++ b/pdns/test-dnswriter_cc.cc @@ -0,0 +1,81 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "dnswriter.hh" +#include "dnsparser.hh" + +BOOST_AUTO_TEST_SUITE(test_dnswriter_cc) + +BOOST_AUTO_TEST_CASE(test_compressionBool) { + auto testCompressionBool = [](bool compress, size_t size1, size_t size2) { + DNSName name("powerdns.com."); + + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + + pwR.startRecord(DNSName("mediumsizedlabel.example.net"), QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, compress); + pwR.xfrIP('P'<<24 | + 'Q'<<16 | + 'R'<<8 | + 'S'); + pwR.commit(); + BOOST_CHECK_EQUAL(pwR.size(), size1); + + pwR.startRecord(DNSName("adifferentlabel.example.net"), QType::NS, 3600, QClass::IN, DNSResourceRecord::ANSWER, compress); + pwR.xfrName(DNSName("target.example.net"), true); + pwR.commit(); + BOOST_CHECK_EQUAL(pwR.size(), size2); + + string spacket(packet.begin(), packet.end()); + + BOOST_CHECK_NO_THROW(MOADNSParser mdp(false, spacket)); + }; + + testCompressionBool(true, 74, 111); + testCompressionBool(false, 74, 133); +} + +BOOST_AUTO_TEST_CASE(test_compressionBoundary) { + DNSName name("powerdns.com."); + + vector packet; + DNSPacketWriter pwR(packet, name, QType::A, QClass::IN, 0); + pwR.getHeader()->qr = 1; + + /* record we want to see altered */ + pwR.startRecord(name, QType::TXT, 3600, QClass::IN, DNSResourceRecord::ANSWER); + auto txt = string("\"")+string(16262, 'A')+string("\""); + pwR.xfrText(txt); + pwR.commit(); + BOOST_CHECK_EQUAL(pwR.size(), 16368); + + pwR.startRecord(DNSName("mediumsizedlabel.example.net"), QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP('P'<<24 | + 'Q'<<16 | + 'R'<<8 | + 'S'); + pwR.commit(); + BOOST_CHECK_EQUAL(pwR.size(), 16412); // 16412 (0x401c) puts '7example3net' at 0x4001 + + pwR.startRecord(DNSName("adifferentlabel.example.net"), QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER); + pwR.xfrIP('D'<<24 | + 'E'<<16 | + 'F'<<8 | + 'G'); + pwR.commit(); + BOOST_CHECK_EQUAL(pwR.size(), 16455); + + string spacket(packet.begin(), packet.end()); + + BOOST_CHECK_NO_THROW(MOADNSParser mdp(false, spacket)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-ipcrypt_cc.cc b/pdns/test-ipcrypt_cc.cc new file mode 100644 index 0000000..a3eae8e --- /dev/null +++ b/pdns/test-ipcrypt_cc.cc @@ -0,0 +1,70 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "ipcipher.hh" +#include "misc.hh" + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(test_ipcrypt_hh) + +BOOST_AUTO_TEST_CASE(test_ipcrypt4) +{ + ComboAddress ca("127.0.0.1"); + std::string key="0123456789ABCDEF"; + auto encrypted = encryptCA(ca, key); + + auto decrypted = decryptCA(encrypted, key); + BOOST_CHECK_EQUAL(ca.toString(), decrypted.toString()); +} + +BOOST_AUTO_TEST_CASE(test_ipcrypt4_vector) +{ + vector> tests{ // test vector from https://github.com/veorq/ipcrypt + {{"127.0.0.1"},{"114.62.227.59"}}, + {{"8.8.8.8"}, {"46.48.51.50"}}, + {{"1.2.3.4"}, {"171.238.15.199"}}}; + + std::string key="some 16-byte key"; + + for(const auto& p : tests) { + auto encrypted = encryptCA(ComboAddress(p.first), key); + BOOST_CHECK_EQUAL(encrypted.toString(), p.second); + auto decrypted = decryptCA(encrypted, key); + BOOST_CHECK_EQUAL(decrypted.toString(), p.first); + } + + // test from Frank Denis' test.cc + ComboAddress ip("192.168.69.42"), out, dec; + string key2; + for(int n=0; n<16; ++n) + key2.append(1, (char)n+1); + + for (unsigned int i = 0; i < 100000000UL; i++) { + out=encryptCA(ip, key2); + // dec=decryptCA(out, key2); + // BOOST_CHECK(ip==dec); + ip=out; + } + + ComboAddress expected("93.155.197.186"); + + BOOST_CHECK_EQUAL(ip.toString(), expected.toString()); +} + + +BOOST_AUTO_TEST_CASE(test_ipcrypt6) +{ + ComboAddress ca("::1"); + std::string key="0123456789ABCDEF"; + auto encrypted = encryptCA(ca, key); + + auto decrypted = decryptCA(encrypted, key); + BOOST_CHECK_EQUAL(ca.toString(), decrypted.toString()); +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-iputils_hh.cc b/pdns/test-iputils_hh.cc new file mode 100644 index 0000000..f30207f --- /dev/null +++ b/pdns/test-iputils_hh.cc @@ -0,0 +1,472 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "iputils.hh" + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(test_iputils_hh) + +BOOST_AUTO_TEST_CASE(test_ComboAddress) { + ComboAddress local("127.0.0.1", 53); + BOOST_CHECK(local==local); + BOOST_CHECK_EQUAL(local.sin4.sin_family, AF_INET); + BOOST_CHECK_EQUAL(local.sin4.sin_port, htons(53)); + BOOST_CHECK_EQUAL(local.sin4.sin_addr.s_addr, htonl(0x7f000001UL)); + + ComboAddress remote("130.161.33.15", 53); + BOOST_CHECK(!(local == remote)); + BOOST_CHECK_EQUAL(remote.sin4.sin_port, htons(53)); + + ComboAddress withport("213.244.168.210:53"); + BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(53)); + + ComboAddress withportO("213.244.168.210:53", 5300); + BOOST_CHECK_EQUAL(withportO.sin4.sin_port, htons(53)); + + withport = ComboAddress("[::]:53"); + BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(53)); + + withport = ComboAddress("[::]:5300", 53); + BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(5300)); + + ComboAddress defaultport("213.244.168.210"); + BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0)); + + defaultport = ComboAddress("[::1]"); + BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0)); + + defaultport = ComboAddress("::1"); + BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0)); + + // Verify that 2 'empty' ComboAddresses are equal, used in syncres.hh to + // signal auth-zones + ComboAddress a = ComboAddress(); + ComboAddress b = ComboAddress(); + BOOST_CHECK(a == b); + + // Verify that 2 ComboAddresses are not the same + ComboAddress c = ComboAddress("127.0.0.1:53"); + ComboAddress d = ComboAddress("127.0.0.1:52"); + ComboAddress e = ComboAddress("127.0.0.2:53"); + + BOOST_CHECK(a != c); + BOOST_CHECK(c != d); + BOOST_CHECK(c != e); + BOOST_CHECK(d != e); + BOOST_CHECK(!(a != b)); + + // Verify that we don't allow invalid port numbers + BOOST_CHECK_THROW(ComboAddress("127.0.0.1:70000"), PDNSException); // Port no. too high + BOOST_CHECK_THROW(ComboAddress("127.0.0.1:-6"), PDNSException); // Port no. too low + BOOST_CHECK_THROW(ComboAddress("[::1]:70000"), PDNSException); // Port no. too high + BOOST_CHECK_THROW(ComboAddress("[::1]:-6"), PDNSException); // Port no. too low +} + +BOOST_AUTO_TEST_CASE(test_ComboAddressCompare) { + ComboAddress a, b; + a.reset(); + b.reset(); + BOOST_CHECK(!(ab)); +} + +BOOST_AUTO_TEST_CASE(test_ComboAddressTruncate) { + ComboAddress ca4("130.161.252.29"); + ca4.truncate(24); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + ca4.truncate(16); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.0.0"); + + + + ca4 = ComboAddress("130.161.252.29"); + ComboAddress orig(ca4); + for(int n=32; n; --n) { + ca4.truncate(n); + + uint32_t p; + memcpy(&p, (char*)&ca4.sin4.sin_addr.s_addr, 4); + std::bitset<32> result(htonl(p)); + + memcpy(&p, (char*)&orig.sin4.sin_addr.s_addr, 4); + std::bitset<32> manual(htonl(p)); + + auto tokill=32-n; + for(int i =0; i< tokill; ++i) + manual.set(i, 0); + + BOOST_CHECK_EQUAL(result, manual); + } + + ca4 = ComboAddress("130.161.252.29"); + ca4.truncate(31); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28"); + + ca4.truncate(30); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28"); + + ca4.truncate(29); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.24"); + + ca4.truncate(23); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + + ca4.truncate(22); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0"); + + ca4.truncate(21); + BOOST_CHECK_EQUAL(ca4.toString(), "130.161.248.0"); + + ComboAddress ca6("2001:888:2000:1d::2"); + ca6.truncate(120); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(64); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(72); // 0102 304 0506 78 + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::"); + ca6.truncate(56); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::"); + ca6.truncate(48); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::"); + ca6.truncate(32); + BOOST_CHECK_EQUAL(ca6.toString(), "2001:888::"); + ca6.truncate(16); + BOOST_CHECK_EQUAL(ca6.toString(), "2001::"); + ca6.truncate(8); + BOOST_CHECK_EQUAL(ca6.toString(), "2000::"); + + + orig=ca6=ComboAddress("2001:888:2000:1d::2"); + for(int n=128; n; --n) { + ca6.truncate(n); + + std::bitset<128> result, manual; + for(int i=0; i < 16; ++i) { + result<<=8; + result|= std::bitset<128>(*((unsigned char*)&ca6.sin6.sin6_addr.s6_addr + i)); + + manual<<=8; + manual|= std::bitset<128>(*((unsigned char*)&orig.sin6.sin6_addr.s6_addr + i)); + } + + auto tokill=128-n; + for(int i =0; i< tokill; ++i) + manual.set(i, 0); + + BOOST_CHECK_EQUAL(result, manual); + } +} + + +BOOST_AUTO_TEST_CASE(test_Mapping) +{ + ComboAddress lh("::1"); + BOOST_CHECK_EQUAL(lh.toString(), "::1"); +} + +BOOST_AUTO_TEST_CASE(test_Netmask) { + ComboAddress local("127.0.0.1", 53); + ComboAddress remote("130.161.252.29", 53); + + Netmask nm("127.0.0.1/24"); + BOOST_CHECK(nm.getBits() == 24); + BOOST_CHECK(nm.match(local)); + BOOST_CHECK(!nm.match(remote)); + BOOST_CHECK(nm.isIpv4()); + BOOST_CHECK(!nm.isIpv6()); + + Netmask nm6("fe80::92fb:a6ff:fe4a:51da/64"); + BOOST_CHECK(nm6.getBits() == 64); + BOOST_CHECK(nm6.match("fe80::92fb:a6ff:fe4a:51db")); + BOOST_CHECK(!nm6.match("fe81::92fb:a6ff:fe4a:51db")); + BOOST_CHECK(!nm6.isIpv4()); + BOOST_CHECK(nm6.isIpv6()); + + Netmask nmp("130.161.252.29/32"); + BOOST_CHECK(nmp.match(remote)); + + Netmask nmp6("fe80::92fb:a6ff:fe4a:51da/128"); + BOOST_CHECK(nmp6.match("fe80::92fb:a6ff:fe4a:51da")); + BOOST_CHECK(!nmp6.match("fe81::92fb:a6ff:fe4a:51db")); + + Netmask all("0.0.0.0/0"); + BOOST_CHECK(all.match(local) && all.match(remote)); + + Netmask all6("::/0"); + BOOST_CHECK(all6.match("::1") && all6.match("fe80::92fb:a6ff:fe4a:51da")); + + + Netmask fromCombo1(ComboAddress("192.0.2.1:53"), 32); + Netmask fromCombo2(ComboAddress("192.0.2.1:54"), 32); + BOOST_CHECK(fromCombo1 == fromCombo2); + BOOST_CHECK(fromCombo1.match("192.0.2.1")); + BOOST_CHECK(fromCombo1.match(ComboAddress("192.0.2.1:80"))); + BOOST_CHECK(fromCombo1.getNetwork() == ComboAddress("192.0.2.1")); + BOOST_CHECK(fromCombo1.getMaskedNetwork() == ComboAddress("192.0.2.1")); + + Netmask nm25("192.0.2.255/25"); + BOOST_CHECK(nm25.getBits() == 25); + BOOST_CHECK(nm25.getNetwork() == ComboAddress("192.0.2.255")); + BOOST_CHECK(nm25.getMaskedNetwork() == ComboAddress("192.0.2.128")); + + /* Make sure that more specific Netmasks are lesser than less specific ones, + as this is very useful when matching. */ + Netmask specific32("192.0.0.0/32"); + Netmask specific24("192.0.0.0/24"); + Netmask specific16("192.0.0.0/16"); + BOOST_CHECK(specific32 < specific24); + BOOST_CHECK(specific24 > specific32); + BOOST_CHECK(specific24 < specific16); + BOOST_CHECK(specific16 > specific24); + + Netmask sameMask1("192.0.0.0/16"); + Netmask sameMask2("192.0.0.1/16"); + BOOST_CHECK(sameMask1 < sameMask2); + BOOST_CHECK(sameMask2 > sameMask1); + + /* An empty Netmask should be larger than + every others. */ + Netmask empty = Netmask(); + Netmask full("255.255.255.255/32"); + BOOST_CHECK(empty > all); + BOOST_CHECK(all < empty); + BOOST_CHECK(empty > full); + BOOST_CHECK(full < empty); +} + +static std::string NMGOutputToSorted(const std::string& str) +{ + std::vector vect; + stringtok(vect, str, ", "); + std::sort(vect.begin(), vect.end()); + std::string result; + for (const auto& entry : vect) { + if (!result.empty()) { + result += " "; + } + result += entry; + } + + return result; +} + +BOOST_AUTO_TEST_CASE(test_NetmaskGroup) { + + { + NetmaskGroup ng; + ng.addMask("10.0.1.0"); + BOOST_CHECK(ng.match(ComboAddress("10.0.1.0"))); + ng.toMasks("127.0.0.0/8, 10.0.0.0/24"); + BOOST_CHECK(ng.match(ComboAddress("127.0.0.1"))); + BOOST_CHECK(ng.match(ComboAddress("10.0.0.3"))); + BOOST_CHECK(ng.match(ComboAddress("10.0.1.0"))); + BOOST_CHECK(!ng.match(ComboAddress("128.1.2.3"))); + BOOST_CHECK(!ng.match(ComboAddress("10.0.1.1"))); + BOOST_CHECK(!ng.match(ComboAddress("::1"))); + ng.addMask("::1"); + BOOST_CHECK(ng.match(ComboAddress("::1"))); + BOOST_CHECK(!ng.match(ComboAddress("::2"))); + ng.addMask("fe80::/16"); + BOOST_CHECK(ng.match(ComboAddress("fe80::1"))); + BOOST_CHECK(!ng.match(ComboAddress("fe81::1"))); + BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16")); + + /* negative entries using the explicit flag */ + ng.addMask("172.16.0.0/16", true); + BOOST_CHECK(ng.match(ComboAddress("172.16.1.1"))); + BOOST_CHECK(ng.match(ComboAddress("172.16.4.50"))); + ng.addMask("172.16.4.0/24", false); + BOOST_CHECK(ng.match(ComboAddress("172.16.1.1"))); + BOOST_CHECK(!ng.match(ComboAddress("172.16.4.50"))); + ng.addMask("fe80::/24", false); + BOOST_CHECK(!ng.match(ComboAddress("fe80::1"))); + BOOST_CHECK(!ng.match(ComboAddress("fe81::1"))); + /* not in fe80::/24 but in fe80::/16, should match */ + BOOST_CHECK(ng.match(ComboAddress("fe80:0100::1"))); + + /* negative entries using '!' */ + BOOST_CHECK(ng.match(ComboAddress("172.16.10.80"))); + ng.addMask("!172.16.10.0/24"); + BOOST_CHECK(!ng.match(ComboAddress("172.16.10.80"))); + ng.addMask("2001:db8::/32"); + ng.addMask("!2001:db8::/64"); + BOOST_CHECK(!ng.match(ComboAddress("2001:db8::1"))); + /* not in 2001:db8::/64 but in 2001:db8::/32, should match */ + BOOST_CHECK(ng.match(ComboAddress("2001:db8:1::1"))); + + BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16, 172.16.0.0/16, !172.16.4.0/24, !fe80::/24, !172.16.10.0/24, 2001:db8::/32, !2001:db8::/64")); + } + + { + /* this time using Netmask objects instead of strings */ + NetmaskGroup ng; + ng.addMask(Netmask("10.0.1.0")); + BOOST_CHECK(ng.match(ComboAddress("10.0.1.0"))); + ng.addMask(Netmask("127.0.0.0/8")); + ng.addMask(Netmask("10.0.0.0/24")); + BOOST_CHECK(ng.match(ComboAddress("127.0.0.1"))); + BOOST_CHECK(ng.match(ComboAddress("10.0.0.3"))); + BOOST_CHECK(ng.match(ComboAddress("10.0.1.0"))); + BOOST_CHECK(!ng.match(ComboAddress("128.1.2.3"))); + BOOST_CHECK(!ng.match(ComboAddress("10.0.1.1"))); + BOOST_CHECK(!ng.match(ComboAddress("::1"))); + ng.addMask(Netmask("::1")); + BOOST_CHECK(ng.match(ComboAddress("::1"))); + BOOST_CHECK(!ng.match(ComboAddress("::2"))); + ng.addMask(Netmask("fe80::/16")); + BOOST_CHECK(ng.match(ComboAddress("fe80::1"))); + BOOST_CHECK(!ng.match(ComboAddress("fe81::1"))); + BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16")); + + /* negative entries using the explicit flag */ + ng.addMask(Netmask("172.16.0.0/16"), true); + BOOST_CHECK(ng.match(ComboAddress("172.16.1.1"))); + BOOST_CHECK(ng.match(ComboAddress("172.16.4.50"))); + ng.addMask(Netmask("172.16.4.0/24"), false); + BOOST_CHECK(ng.match(ComboAddress("172.16.1.1"))); + BOOST_CHECK(!ng.match(ComboAddress("172.16.4.50"))); + ng.addMask("fe80::/24", false); + BOOST_CHECK(!ng.match(ComboAddress("fe80::1"))); + BOOST_CHECK(!ng.match(ComboAddress("fe81::1"))); + /* not in fe80::/24 but in fe80::/16, should match */ + BOOST_CHECK(ng.match(ComboAddress("fe80:0100::1"))); + + BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16, 172.16.0.0/16, !172.16.4.0/24, !fe80::/24")); + } +} + + +BOOST_AUTO_TEST_CASE(test_NetmaskTree) { + NetmaskTree nmt; + nmt.insert(Netmask("130.161.252.0/24")).second=0; + nmt.insert(Netmask("130.161.0.0/16")).second=1; + nmt.insert(Netmask("130.0.0.0/8")).second=2; + + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("213.244.168.210")), (void*)0); + auto found=nmt.lookup(ComboAddress("130.161.252.29")); + BOOST_CHECK(found); + BOOST_CHECK_EQUAL(found->second, 0); + found=nmt.lookup(ComboAddress("130.161.180.1")); + BOOST_CHECK(found); + BOOST_CHECK_EQUAL(found->second, 1); + + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.255.255.255"))->second, 2); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.252.255"))->second, 0); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.253.255"))->second, 1); + + found=nmt.lookup(ComboAddress("130.145.180.1")); + BOOST_CHECK(found); + BOOST_CHECK_EQUAL(found->second, 2); + + nmt.clear(); + BOOST_CHECK(!nmt.lookup(ComboAddress("130.161.180.1"))); + + nmt.insert(Netmask("::1")).second=1; + nmt.insert(Netmask("::/0")).second=0; + nmt.insert(Netmask("fe80::/16")).second=2; + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.253.255")), (void*)0); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::2"))->second, 0); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::ffff"))->second, 0); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::1"))->second, 1); + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("fe80::1"))->second, 2); +} + +BOOST_AUTO_TEST_CASE(test_single) { + NetmaskTree nmt; + nmt.insert(Netmask("127.0.0.0/8")).second=1; + BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("127.0.0.1"))->second, 1); +} + +BOOST_AUTO_TEST_CASE(test_scale) { + string start="192.168."; + NetmaskTree works; + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + works.insert(Netmask(start+std::to_string(i)+"."+std::to_string(j))).second=i*j; + } + } + + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+"."+std::to_string(j)))->second, i*j); + } + } + + start="130.161."; + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+"."+std::to_string(j))), (void*)0); + } + } + + start="2000:123:"; + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + works.insert(Netmask(start+std::to_string(i)+":"+std::to_string(j)+"::/64")).second=i*j; + } + } + + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+":"+std::to_string(j)+"::"+std::to_string(i)+":"+std::to_string(j)))->second, i*j); + } + } + + start="2001:123:"; + for(int i=0; i < 256; ++i) { + for(int j=0; j < 256; ++j) { + BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+":"+std::to_string(j)+"::"+std::to_string(i)+":"+std::to_string(j))), (void*)0); + } + } +} + +BOOST_AUTO_TEST_CASE(test_removal) { + std::string prefix = "192."; + NetmaskTree nmt(true); + + size_t count = 0; + for(unsigned int i = 0; i < 256; ++i) { + for(unsigned int j = 16; j <= 32; ++j) { + nmt.insert(Netmask(prefix + std::to_string(i) +".127.255/"+std::to_string(j))).second = j; + count++; + } + } + + BOOST_CHECK_EQUAL(nmt.size(), count); + + for(unsigned int i = 0; i < 256; ++i) { + ComboAddress key(prefix + std::to_string(i) + ".127.255"); + const auto result = nmt.lookup(key); + BOOST_CHECK_EQUAL(result->first.getBits(), 32); + BOOST_CHECK_EQUAL(result->first.getMaskedNetwork().toString(), key.toString()); + BOOST_CHECK_EQUAL(result->second, 32); + } + + for(unsigned int i = 0; i < 256; ++i) { + for(unsigned int j = 32; j >= 16; --j) { + ComboAddress key(prefix + std::to_string(i) + ".127.255"); + nmt.erase(Netmask(key, j)); + const auto result = nmt.lookup(key); + + if (j > 16) { + BOOST_REQUIRE(result != nullptr); + BOOST_CHECK_EQUAL(result->first.getBits(), j-1); + BOOST_CHECK_EQUAL(result->first.getMaskedNetwork().toString(), Netmask(key, j-1).getMaskedNetwork().toString()); + BOOST_CHECK_EQUAL(result->second, j - 1); + } + else { + BOOST_CHECK(result == nullptr); + } + } + } + + BOOST_CHECK_EQUAL(nmt.size(), 0); + BOOST_CHECK(nmt.empty()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-ixfr_cc.cc b/pdns/test-ixfr_cc.cc new file mode 100644 index 0000000..00d795e --- /dev/null +++ b/pdns/test-ixfr_cc.cc @@ -0,0 +1,310 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "test-common.hh" +#include "ixfr.hh" + +BOOST_AUTO_TEST_SUITE(test_ixfr_cc) + +BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_axfr) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::NS, "NS.JAIN.AD.JP."); + addRecordToList(records, DNSName("NS.JAIN.AD.JP."), QType::A, "133.69.136.1"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + BOOST_CHECK_EQUAL(ret.size(), 1); + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 0); + BOOST_REQUIRE_EQUAL(ret.at(0).second.size(), records.size()); + for (size_t idx = 0; idx < records.size(); idx++) { + BOOST_CHECK(ret.at(0).second.at(idx) == records.at(idx)); + } +} + +BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_incremental) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.4"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.4"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + // two sequences + BOOST_CHECK_EQUAL(ret.size(), 2); + // the first one has one removal, two additions (plus the corresponding SOA removal/addition) + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(0).second.size(), 2 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(0).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(0).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(1).d_type, QType(QType::A).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(2).d_type, QType(QType::A).getCode()); + + // the second one has one removal, one addition + BOOST_CHECK_EQUAL(ret.at(1).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(1).second.size(), 1 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(1).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(1).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).second.at(1).d_type, QType(QType::A).getCode()); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_condensed_incremental) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + // one sequence + BOOST_CHECK_EQUAL(ret.size(), 1); + // it has one removal, two additions (plus the corresponding SOA removal/addition) + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(0).second.size(), 2 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(0).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(0).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(1).d_type, QType(QType::A).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(2).d_type, QType(QType::A).getCode()); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_no_additions_in_first_sequence) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + // two sequences + BOOST_CHECK_EQUAL(ret.size(), 2); + // the first one has one removal, no additions (plus the corresponding SOA removal/addition) + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(0).second.size(), 0 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(0).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(0).second.at(0).d_type, QType(QType::SOA).getCode()); + + // the second one has one removal, one addition + BOOST_CHECK_EQUAL(ret.at(1).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(1).second.size(), 1 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(1).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(1).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).second.at(1).d_type, QType(QType::A).getCode()); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_no_removals_in_first_sequence) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.4"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.4"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + // two sequences + BOOST_CHECK_EQUAL(ret.size(), 2); + // the first one has no removal, two additions (plus the corresponding SOA removal/addition) + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 0 + 1); + BOOST_CHECK_EQUAL(ret.at(0).second.size(), 2 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(0).first.at(0).d_type, QType(QType::SOA).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(0).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(1).d_type, QType(QType::A).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(1).d_type, QType(QType::A).getCode()); + + // the second one has one removal, one addition + BOOST_CHECK_EQUAL(ret.at(1).first.size(), 1 + 1); + BOOST_CHECK_EQUAL(ret.at(1).second.size(), 1 + 1); + + // check removals + BOOST_CHECK_EQUAL(ret.at(1).first.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).first.at(1).d_type, QType(QType::A).getCode()); + + // check additions + BOOST_CHECK_EQUAL(ret.at(1).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(1).second.at(1).d_type, QType(QType::A).getCode()); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_same_serial) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + + // this is actually an empty AXFR + BOOST_CHECK_EQUAL(ret.size(), 1); + // nothing in the deletion part then + BOOST_CHECK_EQUAL(ret.at(0).first.size(), 0); + // and the two SOAs in the addition part + BOOST_CHECK_EQUAL(ret.at(0).second.size(), 2); + BOOST_CHECK_EQUAL(ret.at(0).second.at(0).d_type, QType(QType::SOA).getCode()); + BOOST_CHECK_EQUAL(ret.at(0).second.at(1).d_type, QType(QType::SOA).getCode()); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_records) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + + auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)); + BOOST_CHECK_EQUAL(ret.size(), 0); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_master_soa) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); +; + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + auto ret = processIXFRRecords(master, zone, records, nullptr); + BOOST_CHECK_EQUAL(ret.size(), 0); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_trailing_soa) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + + BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_soa_after_removals) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + + BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_mistmatching_serial_before_and_after_additions) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 2 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + + BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_ixfr_trailing_record_after_end) { + const ComboAddress master("[2001:DB8::1]:53"); + const DNSName zone("JAIN.AD.JP."); + + auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + vector records; + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800"); + addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2"); + addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800"); + addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3"); + + BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast(masterSOA)), std::runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/pdns/test-lock_hh.cc b/pdns/test-lock_hh.cc new file mode 100644 index 0000000..7f73d5e --- /dev/null +++ b/pdns/test-lock_hh.cc @@ -0,0 +1,63 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "lock.hh" +#include + +using namespace boost; + +BOOST_AUTO_TEST_SUITE(test_lock_hh) + +static std::vector > g_locks; + +static void lthread() +{ + std::vector rlocks; + for(auto& pp : g_locks) + rlocks.emplace_back(&*pp); + +} + +BOOST_AUTO_TEST_CASE(test_pdns_lock) +{ + for(unsigned int n=0; n < 1000; ++n) { + auto p = new pthread_rwlock_t; + pthread_rwlock_init(p, 0); + g_locks.emplace_back(p); + } + + std::vector rlocks; + for(auto& pp : g_locks) + rlocks.emplace_back(&*pp); + + std::thread thr(lthread); + thr.join(); + rlocks.clear(); + + std::vector wlocks; + for(auto& pp : g_locks) + wlocks.emplace_back(&*pp); + + // on macOS, this TryReadLock throws (EDEADLK) instead of simply failing + // so we catch the exception and consider that success for this test + bool gotit = false; + try { + TryReadLock trl(&*g_locks[0]); + gotit = trl.gotIt(); + } + catch(const PDNSException &e) { + gotit = false; + } + BOOST_CHECK(!gotit); + + wlocks.clear(); + TryReadLock trl2(&*g_locks[0]); + BOOST_CHECK(trl2.gotIt()); + + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-lua_auth4_cc.cc b/pdns/test-lua_auth4_cc.cc new file mode 100644 index 0000000..00ed0d7 --- /dev/null +++ b/pdns/test-lua_auth4_cc.cc @@ -0,0 +1,73 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "arguments.hh" +#include +#include "lua-auth4.hh" + +struct SetupArgFixture { + SetupArgFixture() { + ::arg().set("resolver") = "127.0.0.1"; + }; +}; + +BOOST_FIXTURE_TEST_SUITE(lua_auth4_cc, SetupArgFixture) + +BOOST_AUTO_TEST_CASE(test_prequery) { + const std::string script = +"function prequery(q)\n" +" if q.qdomain == newDN(\"mod.unit.test.\")\n" +" then\n" +" return true\n" +" end\n" +" return false\n" +"end"; + AuthLua4 lua; + DNSPacket *p = new DNSPacket(true); + p->qdomain = DNSName("mod.unit.test."); + lua.loadString(script); + DNSPacket *r = nullptr; + try { + r = lua.prequery(p); + BOOST_CHECK_EQUAL(r->qdomain.toString(), "mod.unit.test."); + } catch (const LuaContext::ExecutionErrorException& e) { + try { + std::rethrow_if_nested(e); + } catch(const std::exception& exp) { + g_log<<"Extra info: "<setRemote(&ca); + p->d_peer_principal = "admin@DOMAIN"; + BOOST_CHECK_EQUAL(lua.updatePolicy(DNSName("mod.example.com."), QType(QType::A), DNSName("example.com."), p), true); + p->d_peer_principal = ""; + BOOST_CHECK_EQUAL(lua.updatePolicy(DNSName("mod.example.com."), QType(QType::A), DNSName("example.com."), p), true); + ca = ComboAddress(std::string("192.168.1.2")); + p->setRemote(&ca); + BOOST_CHECK_EQUAL(lua.updatePolicy(DNSName("mod.example.com."), QType(QType::A), DNSName("example.com."), p), false); + delete p; +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-misc_hh.cc b/pdns/test-misc_hh.cc new file mode 100644 index 0000000..081661a --- /dev/null +++ b/pdns/test-misc_hh.cc @@ -0,0 +1,180 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include "misc.hh" +#include "dns.hh" +#include +#include + +using std::string; + +BOOST_AUTO_TEST_SUITE(test_misc_hh) +typedef pair typedns_t; + +BOOST_AUTO_TEST_CASE(test_CIStringCompare) { + set nsset; + nsset.insert("abc"); + nsset.insert("ns.example.com"); + nsset.insert(""); + nsset.insert("def"); + nsset.insert("aBc"); + nsset.insert("ns.example.com"); + BOOST_CHECK_EQUAL(nsset.size(), 4); + + ostringstream s; + for(set::const_iterator i=nsset.begin();i!=nsset.end();++i) { + s<<"("<<*i<<")"; + } + BOOST_CHECK_EQUAL(s.str(), "()(abc)(def)(ns.example.com)"); +} + +BOOST_AUTO_TEST_CASE(test_CIStringPairCompare) { + set nsset2; + nsset2.insert(make_pair("ns.example.com", 1)); + nsset2.insert(make_pair("abc", 1)); + nsset2.insert(make_pair("", 1)); + nsset2.insert(make_pair("def", 1)); + nsset2.insert(make_pair("abc", 2)); + nsset2.insert(make_pair("abc", 1)); + nsset2.insert(make_pair("ns.example.com", 0)); + nsset2.insert(make_pair("abc", 2)); + nsset2.insert(make_pair("ABC", 2)); + BOOST_CHECK_EQUAL(nsset2.size(), 6); + + ostringstream s; + for(set::const_iterator i=nsset2.begin();i!=nsset2.end();++i) { + s<<"("<first<<"|"<second<<")"; + } + BOOST_CHECK_EQUAL(s.str(), "(|1)(abc|1)(abc|2)(def|1)(ns.example.com|0)(ns.example.com|1)"); +} + +BOOST_AUTO_TEST_CASE(test_pdns_ilexicographical_compare) { + typedef boost::tuple case_t; + typedef std::list cases_t; + + cases_t cases = boost::assign::list_of + (case_t(std::string(""), std::string(""), false)) + (case_t(std::string(""), std::string("abc"), true)) + (case_t(std::string("abc"), std::string(""), false)) + (case_t(std::string("abc"), std::string("abcd"), true)) + (case_t(std::string("abcd"), std::string("abc"), false)) + (case_t(std::string("abd"), std::string("abc"), false)) + (case_t(std::string("abc"), std::string("abd"), true)) + (case_t(std::string("abc"), std::string("Abc"), false)) + (case_t(std::string("Abc"), std::string("abc"), false)) + ; + + for(const case_t& val : cases) { + bool res; + res = pdns_ilexicographical_compare(val.get<0>(), val.get<1>()); + BOOST_CHECK_EQUAL(res, val.get<2>()); + } +} + +BOOST_AUTO_TEST_CASE(test_pdns_iequals) { + typedef boost::tuple case_t; + typedef std::list cases_t; + + cases_t cases = boost::assign::list_of + (case_t(std::string(""), std::string(""), true)) + (case_t(std::string(""), std::string("abc"), false)) + (case_t(std::string("abc"), std::string(""), false)) + (case_t(std::string("abc"), std::string("abcd"), false)) + (case_t(std::string("abcd"), std::string("abc"), false)) + (case_t(std::string("abd"), std::string("abc"), false)) + (case_t(std::string("abc"), std::string("abd"), false)) + (case_t(std::string("abc"), std::string("Abc"), true)) + (case_t(std::string("Abc"), std::string("abc"), true)) + ; + + for(const case_t& val : cases) { + bool res; + res = pdns_iequals(val.get<0>(), val.get<1>()); + BOOST_CHECK_EQUAL(res, val.get<2>()); + } +} + +BOOST_AUTO_TEST_CASE(test_stripDot) { + BOOST_CHECK_EQUAL(stripDot("."), ""); + BOOST_CHECK_EQUAL(stripDot(""), ""); + BOOST_CHECK_EQUAL(stripDot("www.powerdns.com."), "www.powerdns.com"); + BOOST_CHECK_EQUAL(stripDot("www.powerdns.com"), "www.powerdns.com"); +} + +BOOST_AUTO_TEST_CASE(test_labelReverse) { + BOOST_CHECK_EQUAL(DNSName("www.powerdns.com").labelReverse().toString(" ", false), "com powerdns www"); +} + + +BOOST_AUTO_TEST_CASE(test_AtomicCounter) { + AtomicCounter ac(0); + ++ac; + ++ac; + BOOST_CHECK_EQUAL(ac, 2); +} + +BOOST_AUTO_TEST_CASE(test_endianness) { + uint32_t i = 1; +#if BYTE_ORDER == BIG_ENDIAN + BOOST_CHECK_EQUAL(i, htonl(i)); +#elif BYTE_ORDER == LITTLE_ENDIAN + uint32_t j=0x01000000; + BOOST_CHECK_EQUAL(i, ntohl(j)); +#else + BOOST_FAIL("Did not detect endianness at all"); +#endif +} + +BOOST_AUTO_TEST_CASE(test_parseService) { + ServiceTuple tp; + parseService("smtp.powerdns.com:25", tp); + BOOST_CHECK_EQUAL(tp.host, "smtp.powerdns.com"); + BOOST_CHECK_EQUAL(tp.port, 25); + parseService("smtp.powerdns.com", tp); + BOOST_CHECK_EQUAL(tp.port, 25); +} + +BOOST_AUTO_TEST_CASE(test_ternary) { + int maxqps=1024; + BOOST_CHECK_EQUAL(defTer(maxqps, 16384), maxqps); + BOOST_CHECK_EQUAL(defTer(0, 16384), 16384); + + int* qps=0; + BOOST_CHECK_EQUAL(*defTer(qps, &maxqps), 1024); +} + +BOOST_AUTO_TEST_CASE(test_SimpleMatch) { + BOOST_CHECK_EQUAL(SimpleMatch("").match(std::string("")), true); + BOOST_CHECK_EQUAL(SimpleMatch("?").match(std::string("")), false); + BOOST_CHECK_EQUAL(SimpleMatch("*").match(std::string("")), true); + + BOOST_CHECK_EQUAL(SimpleMatch("abc").match(std::string("abc")), true); + BOOST_CHECK_EQUAL(SimpleMatch("abc").match(std::string("ab")), false); + BOOST_CHECK_EQUAL(SimpleMatch("abc").match(std::string("bc")), false); + + BOOST_CHECK_EQUAL(SimpleMatch("?").match(std::string("a")), true); + BOOST_CHECK_EQUAL(SimpleMatch("a?c").match(std::string("abc")), true); + BOOST_CHECK_EQUAL(SimpleMatch("a?c").match(std::string("ab")), false); + BOOST_CHECK_EQUAL(SimpleMatch("a?c").match(std::string("bc")), false); + + BOOST_CHECK_EQUAL(SimpleMatch("*").match(std::string("*")), true); + BOOST_CHECK_EQUAL(SimpleMatch("a*c").match(std::string("abc")), true); + BOOST_CHECK_EQUAL(SimpleMatch("a*c").match(std::string("ab")), false); + BOOST_CHECK_EQUAL(SimpleMatch("a*c").match(std::string("bc")), false); + + BOOST_CHECK_EQUAL(SimpleMatch("*").match(std::string("abcdefghj")), true); + BOOST_CHECK_EQUAL(SimpleMatch("*a").match(std::string("abca")), true); + BOOST_CHECK_EQUAL(SimpleMatch("*a").match(std::string("abcb")), false); + BOOST_CHECK_EQUAL(SimpleMatch("abc*").match(std::string("abcabcabcabacabac")), true); + BOOST_CHECK_EQUAL(SimpleMatch("abc*").match(std::string("abc")), true); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/pdns/test-mplexer.cc b/pdns/test-mplexer.cc new file mode 100644 index 0000000..8a7412f --- /dev/null +++ b/pdns/test-mplexer.cc @@ -0,0 +1,182 @@ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#include +#include + +#include "mplexer.hh" +#include "misc.hh" + +BOOST_AUTO_TEST_SUITE(mplexer) + +BOOST_AUTO_TEST_CASE(test_MPlexer) { + auto mplexer = std::unique_ptr(FDMultiplexer::getMultiplexerSilent()); + BOOST_REQUIRE(mplexer != nullptr); + + struct timeval now; + int ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 0); + + std::vector readyFDs; + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_CHECK_EQUAL(readyFDs.size(), 0); + + auto timeouts = mplexer->getTimeouts(now); + BOOST_CHECK_EQUAL(timeouts.size(), 0); + + int pipes[2]; + int res = pipe(pipes); + BOOST_REQUIRE_EQUAL(res, 0); + BOOST_REQUIRE_EQUAL(setNonBlocking(pipes[0]), true); + BOOST_REQUIRE_EQUAL(setNonBlocking(pipes[1]), true); + + /* let's declare a TTD that expired 5s ago */ + struct timeval ttd = now; + ttd.tv_sec -= 5; + + bool writeCBCalled = false; + auto writeCB = [](int fd, FDMultiplexer::funcparam_t param) { + auto calledPtr = boost::any_cast(param); + BOOST_REQUIRE(calledPtr != nullptr); + *calledPtr = true; + }; + mplexer->addWriteFD(pipes[1], + writeCB, + &writeCBCalled, + &ttd); + /* we can't add it twice */ + BOOST_CHECK_THROW(mplexer->addWriteFD(pipes[1], + writeCB, + &writeCBCalled, + &ttd), + FDMultiplexerException); + + readyFDs.clear(); + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_REQUIRE_EQUAL(readyFDs.size(), 1); + BOOST_CHECK_EQUAL(readyFDs.at(0), pipes[1]); + + ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 1); + BOOST_CHECK_EQUAL(writeCBCalled, true); + + /* no read timeouts */ + timeouts = mplexer->getTimeouts(now, false); + BOOST_CHECK_EQUAL(timeouts.size(), 0); + /* but we should have a write one */ + timeouts = mplexer->getTimeouts(now, true); + BOOST_REQUIRE_EQUAL(timeouts.size(), 1); + BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]); + + /* can't remove from the wrong type of FD */ + BOOST_CHECK_THROW(mplexer->removeReadFD(pipes[1]), FDMultiplexerException); + mplexer->removeWriteFD(pipes[1]); + /* can't remove a non-existing FD */ + BOOST_CHECK_THROW(mplexer->removeWriteFD(pipes[0]), FDMultiplexerException); + BOOST_CHECK_THROW(mplexer->removeWriteFD(pipes[1]), FDMultiplexerException); + + readyFDs.clear(); + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_REQUIRE_EQUAL(readyFDs.size(), 0); + + ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 0); + + bool readCBCalled = false; + auto readCB = [](int fd, FDMultiplexer::funcparam_t param) { + auto calledPtr = boost::any_cast(param); + BOOST_REQUIRE(calledPtr != nullptr); + *calledPtr = true; + }; + mplexer->addReadFD(pipes[0], + readCB, + &readCBCalled, + &ttd); + + /* not ready for reading yet */ + readyFDs.clear(); + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_REQUIRE_EQUAL(readyFDs.size(), 0); + + ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 0); + BOOST_CHECK_EQUAL(readCBCalled, false); + + /* let's make the pipe readable */ + BOOST_REQUIRE_EQUAL(write(pipes[1], "0", 1), 1); + + readyFDs.clear(); + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_REQUIRE_EQUAL(readyFDs.size(), 1); + BOOST_CHECK_EQUAL(readyFDs.at(0), pipes[0]); + + ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 1); + BOOST_CHECK_EQUAL(readCBCalled, true); + + /* add back the write FD */ + mplexer->addWriteFD(pipes[1], + writeCB, + &writeCBCalled, + &ttd); + + /* both should be available */ + readyFDs.clear(); + mplexer->getAvailableFDs(readyFDs, 0); + BOOST_REQUIRE_EQUAL(readyFDs.size(), 2); + + readCBCalled = false; + writeCBCalled = false; + ready = mplexer->run(&now, 100); + BOOST_CHECK_EQUAL(ready, 2); + BOOST_CHECK_EQUAL(readCBCalled, true); + BOOST_CHECK_EQUAL(writeCBCalled, true); + + /* both the read and write FD should be reported */ + timeouts = mplexer->getTimeouts(now, false); + BOOST_REQUIRE_EQUAL(timeouts.size(), 1); + BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[0]); + timeouts = mplexer->getTimeouts(now, true); + BOOST_REQUIRE_EQUAL(timeouts.size(), 1); + BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]); + + struct timeval past = ttd; + /* so five seconds before the actual TTD */ + past.tv_sec -= 5; + + /* no read timeouts */ + timeouts = mplexer->getTimeouts(past, false); + BOOST_CHECK_EQUAL(timeouts.size(), 0); + /* and we should not have a write one either */ + timeouts = mplexer->getTimeouts(past, true); + BOOST_CHECK_EQUAL(timeouts.size(), 0); + + /* update the timeouts to now, they should not be reported anymore */ + mplexer->setReadTTD(pipes[0], now, 0); + mplexer->setWriteTTD(pipes[1], now, 0); + timeouts = mplexer->getTimeouts(now, false); + BOOST_REQUIRE_EQUAL(timeouts.size(), 0); + timeouts = mplexer->getTimeouts(now, true); + BOOST_REQUIRE_EQUAL(timeouts.size(), 0); + + /* put it back into the past */ + mplexer->setReadTTD(pipes[0], now, -5); + mplexer->setWriteTTD(pipes[1], now, -5); + timeouts = mplexer->getTimeouts(now, false); + BOOST_REQUIRE_EQUAL(timeouts.size(), 1); + BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[0]); + timeouts = mplexer->getTimeouts(now, true); + BOOST_REQUIRE_EQUAL(timeouts.size(), 1); + BOOST_CHECK_EQUAL(timeouts.at(0).first, pipes[1]); + + mplexer->removeReadFD(pipes[0]); + mplexer->removeWriteFD(pipes[1]); + + /* clean up */ + close(pipes[0]); + close(pipes[1]); +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-nameserver_cc.cc b/pdns/test-nameserver_cc.cc new file mode 100644 index 0000000..2f6044d --- /dev/null +++ b/pdns/test-nameserver_cc.cc @@ -0,0 +1,52 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "iputils.hh" +#include "nameserver.hh" +#include "statbag.hh" +#include + +extern vector g_localaddresses; + +BOOST_AUTO_TEST_SUITE(test_nameserver_cc) + +BOOST_AUTO_TEST_CASE(test_AddressIsUs4) { + ComboAddress local1("127.0.0.1", 53); + ComboAddress local2("127.0.0.2", 53); + ComboAddress Remote("192.168.255.255", 53); + + g_localaddresses.push_back(ComboAddress("0.0.0.0", 53)); + + BOOST_CHECK_EQUAL(AddressIsUs(local1), true); +// BOOST_CHECK_EQUAL(AddressIsUs(local2), false); + BOOST_CHECK_EQUAL(AddressIsUs(Remote), false); + + g_localaddresses.clear(); + g_localaddresses.push_back(ComboAddress("192.168.255.255", 53)); + BOOST_CHECK_EQUAL(AddressIsUs(Remote), true); + Remote.sin4.sin_port = 1; + BOOST_CHECK_EQUAL(AddressIsUs(Remote), false); +} + +BOOST_AUTO_TEST_CASE(test_AddressIsUs6) { + ComboAddress local1("127.0.0.1", 53); + ComboAddress local2("127.0.0.2", 53); + ComboAddress local3("::1", 53); + ComboAddress Remote("192.168.255.255", 53); + + g_localaddresses.clear(); + g_localaddresses.push_back(ComboAddress("::", 53)); + + BOOST_CHECK_EQUAL(AddressIsUs(local1), true); +// BOOST_CHECK_EQUAL(AddressIsUs(local2), false); + if(!getenv("PDNS_TEST_NO_IPV6")) BOOST_CHECK_EQUAL(AddressIsUs(local3), true); + BOOST_CHECK_EQUAL(AddressIsUs(Remote), false); + Remote.sin4.sin_port = 1; + BOOST_CHECK_EQUAL(AddressIsUs(Remote), false); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-packetcache_cc.cc b/pdns/test-packetcache_cc.cc new file mode 100644 index 0000000..60741ba --- /dev/null +++ b/pdns/test-packetcache_cc.cc @@ -0,0 +1,472 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "iputils.hh" +#include "nameserver.hh" +#include "statbag.hh" +#include "auth-packetcache.hh" +#include "auth-querycache.hh" +#include "arguments.hh" +#include +extern StatBag S; + +BOOST_AUTO_TEST_SUITE(test_packetcache_cc) + +BOOST_AUTO_TEST_CASE(test_AuthQueryCacheSimple) { + AuthQueryCache QC; + QC.setMaxEntries(1000000); + + vector records; + + BOOST_CHECK_EQUAL(QC.size(), 0); + QC.insert(DNSName("hello"), QType(QType::A), records, 3600, 1); + BOOST_CHECK_EQUAL(QC.size(), 1); + BOOST_CHECK_EQUAL(QC.purge(), 1); + BOOST_CHECK_EQUAL(QC.size(), 0); + + uint64_t counter=0; + try { + for(counter = 0; counter < 100000; ++counter) { + DNSName a=DNSName("hello ")+DNSName(std::to_string(counter)); + BOOST_CHECK_EQUAL(DNSName(a.toString()), a); + + QC.insert(a, QType(QType::A), records, 3600, 1); + if(!QC.purge(a.toString())) + BOOST_FAIL("Could not remove entry we just added to the query cache!"); + QC.insert(a, QType(QType::A), records, 3600, 1); + } + + BOOST_CHECK_EQUAL(QC.size(), counter); + + uint64_t delcounter=0; + for(delcounter=0; delcounter < counter/100; ++delcounter) { + DNSName a=DNSName("hello ")+DNSName(std::to_string(delcounter)); + BOOST_CHECK_EQUAL(QC.purge(a.toString()), 1); + } + + BOOST_CHECK_EQUAL(QC.size(), counter-delcounter); + + uint64_t matches=0; + vector entry; + int64_t expected=counter-delcounter; + for(; delcounter < counter; ++delcounter) { + if(QC.getEntry(DNSName("hello ")+DNSName(std::to_string(delcounter)), QType(QType::A), entry, 1)) { + matches++; + } + } + BOOST_CHECK_EQUAL(matches, expected); + BOOST_CHECK_EQUAL(entry.size(), records.size()); + } + catch(PDNSException& e) { + cerr<<"Had error: "< records; + unsigned int offset=(unsigned int)(unsigned long)a; + for(unsigned int counter=0; counter < 100000; ++counter) + g_QC->insert(DNSName("hello ")+DNSName(std::to_string(counter+offset)), QType(QType::A), records, 3600, 1); + return 0; +} + catch(PDNSException& e) { + cerr<<"Had error: "< entry; + for(unsigned int counter=0; counter < 100000; ++counter) + if(!g_QC->getEntry(DNSName("hello ")+DNSName(std::to_string(counter+offset)), QType(QType::A), entry, 1)) { + g_QCmissing++; + } + return 0; +} +catch(PDNSException& e) { + cerr<<"Had error in threadQCReader: "<= g_QCmissing); + // BOOST_CHECK_EQUAL(S.read("deferred-cache-lookup"), 0); // cache cleaning invalidates this + } + catch(PDNSException& e) { + cerr<<"Had error: "< pak; + DNSName qname = DNSName("hello ")+DNSName(std::to_string(counter+offset)); + + DNSPacketWriter pw(pak, qname, QType::A); + DNSPacket q(true); + q.parse((char*)&pak[0], pak.size()); + + pak.clear(); + DNSPacketWriter pw2(pak, qname, QType::A); + pw2.startRecord(qname, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER); + pw2.xfrIP(htonl(0x7f000001)); + pw2.commit(); + + DNSPacket r(false); + r.parse((char*)&pak[0], pak.size()); + + /* this step is necessary to get a valid hash + we directly compute the hash instead of querying the + cache because 1/ it's faster 2/ no deferred-lookup issues + */ + q.setHash(g_PC->canHashPacket(q.getString())); + + const unsigned int maxTTL = 3600; + g_PC->insert(&q, &r, maxTTL); + } + + return 0; +} + catch(PDNSException& e) { + cerr<<"Had error: "< entry; + for(unsigned int counter=0; counter < 100000; ++counter) { + vector pak; + DNSName qname = DNSName("hello ")+DNSName(std::to_string(counter+offset)); + + DNSPacketWriter pw(pak, qname, QType::A); + DNSPacket q(true); + q.parse((char*)&pak[0], pak.size()); + DNSPacket r(false); + + if(!g_PC->get(&q, &r)) { + g_PCmissing++; + } + } + + return 0; +} +catch(PDNSException& e) { + cerr<<"Had error in threadPCReader: "<cleanup(); + } + + return 0; +} +catch(PDNSException& e) { + cerr<<"Had error in cacheCleaner: "< records; + + for(unsigned int counter = 0; counter < 1000000; ++counter) { + QC.insert(DNSName("hello ")+DNSName(std::to_string(counter)), QType(QType::A), records, 1, 1); + } + + sleep(1); + + g_QC=&QC; + pthread_t tid[4]; + + pthread_create(&tid[0], 0, threadQCReader, (void*)(0*1000000UL)); + pthread_create(&tid[1], 0, threadQCReader, (void*)(1*1000000UL)); + pthread_create(&tid[2], 0, threadQCReader, (void*)(2*1000000UL)); + // pthread_create(&tid[2], 0, threadMangler, (void*)(0*1000000UL)); + pthread_create(&tid[3], 0, cacheCleaner, 0); + + void *res; + for(int i=0; i < 3 ; ++i) + pthread_join(tid[i], &res); + g_stopCleaning=true; + pthread_join(tid[3], &res); + } + catch(PDNSException& e) { + cerr<<"Had error in test_QueryCacheClean: "< pak; + DNSPacket q(true), differentIDQ(true), ednsQ(true), ednsVersion42(true), ednsDO(true), ecs1(true), ecs2(true), ecs3(true); + DNSPacket r(false), r2(false); + + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + q.parse((char*)&pak[0], pak.size()); + + differentIDQ.parse((char*)&pak[0], pak.size()); + differentIDQ.setID(4242); + + pw.addOpt(512, 0, 0); + pw.commit(); + ednsQ.parse((char*)&pak[0], pak.size()); + + pak.clear(); + } + + DNSPacketWriter::optvect_t opts; + EDNSSubnetOpts ecsOpts; + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + pw.addOpt(512, 0, 0, DNSPacketWriter::optvect_t(), 42); + pw.commit(); + ednsVersion42.parse((char*)&pak[0], pak.size()); + pak.clear(); + } + + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + pw.addOpt(512, 0, EDNSOpts::DNSSECOK); + pw.commit(); + ednsDO.parse((char*)&pak[0], pak.size()); + pak.clear(); + } + + { + ecsOpts.source = Netmask(ComboAddress("192.0.2.1"), 32); + opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(ecsOpts))); + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + pw.addOpt(512, 0, 0, opts); + pw.commit(); + ecs1.parse((char*)&pak[0], pak.size()); + pak.clear(); + opts.clear(); + } + + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + ecsOpts.source = Netmask(ComboAddress("192.0.2.2"), 32); + opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(ecsOpts))); + pw.addOpt(512, 0, 0, opts); + pw.commit(); + ecs2.parse((char*)&pak[0], pak.size()); + pak.clear(); + opts.clear(); + } + + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + ecsOpts.source = Netmask(ComboAddress("192.0.2.3"), 16); + opts.push_back(make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(ecsOpts))); + pw.addOpt(512, 0, 0, opts); + pw.commit(); + ecs3.parse((char*)&pak[0], pak.size()); + pak.clear(); + opts.clear(); + } + + { + DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); + pw.startRecord(DNSName("www.powerdns.com"), QType::A, 16, 1, DNSResourceRecord::ANSWER); + pw.xfrIP(htonl(0x7f000001)); + pw.commit(); + + r.parse((char*)&pak[0], pak.size()); + } + + /* this call is required so the correct hash is set into q->d_hash */ + BOOST_CHECK_EQUAL(PC.get(&q, &r2), false); + + PC.insert(&q, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 1); + + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + + /* different QID, still should match */ + BOOST_CHECK_EQUAL(PC.get(&differentIDQ, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + + /* with EDNS, should not match */ + BOOST_CHECK_EQUAL(PC.get(&ednsQ, &r2), false); + /* inserting the EDNS-enabled one too */ + PC.insert(&ednsQ, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 2); + + /* different EDNS versions, should not match */ + BOOST_CHECK_EQUAL(PC.get(&ednsVersion42, &r2), false); + + /* EDNS DO set, should not match */ + BOOST_CHECK_EQUAL(PC.get(&ednsDO, &r2), false); + + /* EDNS Client Subnet set, should not match + since not only we don't skip the actual option, but the + total EDNS opt RR is still different. */ + BOOST_CHECK_EQUAL(PC.get(&ecs1, &r2), false); + + /* inserting the version with ECS Client Subnet set, + it should NOT replace the existing EDNS one. */ + PC.insert(&ecs1, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 3); + + /* different subnet of same size, should NOT match + since we don't skip the option */ + BOOST_CHECK_EQUAL(PC.get(&ecs2, &r2), false); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + + /* different subnet of different size, should NOT match. */ + BOOST_CHECK_EQUAL(PC.get(&ecs3, &r2), false); + + BOOST_CHECK_EQUAL(PC.purge("www.powerdns.com"), 3); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), false); + BOOST_CHECK_EQUAL(PC.size(), 0); + + PC.insert(&q, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + BOOST_CHECK_EQUAL(PC.purge("com$"), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), false); + BOOST_CHECK_EQUAL(PC.size(), 0); + + PC.insert(&q, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + BOOST_CHECK_EQUAL(PC.purge("powerdns.com$"), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), false); + BOOST_CHECK_EQUAL(PC.size(), 0); + + PC.insert(&q, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + BOOST_CHECK_EQUAL(PC.purge("www.powerdns.com$"), 1); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), false); + BOOST_CHECK_EQUAL(PC.size(), 0); + + PC.insert(&q, &r, 3600); + BOOST_CHECK_EQUAL(PC.size(), 1); + BOOST_CHECK_EQUAL(PC.purge("www.powerdns.net"), 0); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + BOOST_CHECK_EQUAL(PC.size(), 1); + + BOOST_CHECK_EQUAL(PC.purge("net$"), 0); + BOOST_CHECK_EQUAL(PC.get(&q, &r2), true); + BOOST_CHECK_EQUAL(r2.qdomain, r.qdomain); + BOOST_CHECK_EQUAL(PC.size(), 1); + + BOOST_CHECK_EQUAL(PC.purge("www.powerdns.com$"), 1); + BOOST_CHECK_EQUAL(PC.size(), 0); + } + catch(PDNSException& e) { + cerr<<"Had error in AuthPacketCache: "< + +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "ednscookies.hh" +#include "ednssubnet.hh" +#include "packetcache.hh" + +BOOST_AUTO_TEST_SUITE(packetcache_hh) + +BOOST_AUTO_TEST_CASE(test_PacketCacheAuthCollision) { + + /* auth version (ECS is not processed, we just hash the whole query except for the ID, while lowercasing the qname) */ + const DNSName qname("www.powerdns.com."); + uint16_t qtype = QType::AAAA; + EDNSSubnetOpts opt; + DNSPacketWriter::optvect_t ednsOptions; + + { + /* same query, different IDs */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2); + + BOOST_CHECK_EQUAL(hash1, hash2); + BOOST_CHECK(PacketCache::queryMatches(spacket1, spacket2, qname)); + } + + { + /* same query, different IDs, different ECS, still hashes to the same value */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + opt.source = Netmask("10.0.18.199/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + pw1.addOpt(512, 0, 0, ednsOptions); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + opt.source = Netmask("10.0.131.66/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + pw2.addOpt(512, 0, 0, ednsOptions); + pw2.commit(); + + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2); + + BOOST_CHECK_EQUAL(hash1, hash2); + /* the hash is the same but we should _not_ match */ + BOOST_CHECK(!PacketCache::queryMatches(spacket1, spacket2, qname)); + } + + { + /* same query but one has DNSSECOK, not the other, different IDs, different ECS, still hashes to the same value */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + opt.source = Netmask("47.8.0.0/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + pw1.addOpt(512, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + opt.source = Netmask("18.43.1.0/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + /* no EDNSOpts::DNSSECOK !! */ + pw2.addOpt(512, 0, 0, ednsOptions); + pw2.commit(); + + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2); + + BOOST_CHECK_EQUAL(hash1, hash2); + /* the hash is the same but we should _not_ match */ + BOOST_CHECK(!PacketCache::queryMatches(spacket1, spacket2, qname)); + } + + { + /* same query but different cookies, still hashes to the same value */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + opt.source = Netmask("192.0.2.1/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + EDNSCookiesOpt cookiesOpt; + cookiesOpt.client = string("deadbeef"); + cookiesOpt.server = string("deadbeef"); + cookiesOpt.server[4] = -42; + cookiesOpt.server[5] = -6; + cookiesOpt.server[6] = 1; + cookiesOpt.server[7] = 0; + ednsOptions.push_back(std::make_pair(EDNSOptionCode::COOKIE, makeEDNSCookiesOptString(cookiesOpt))); + pw1.addOpt(512, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + opt.source = Netmask("192.0.2.1/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + cookiesOpt.client = string("deadbeef"); + cookiesOpt.server = string("deadbeef"); + cookiesOpt.server[4] = 29; + cookiesOpt.server[5] = -79; + cookiesOpt.server[6] = 1; + cookiesOpt.server[7] = 0; + ednsOptions.push_back(std::make_pair(EDNSOptionCode::COOKIE, makeEDNSCookiesOptString(cookiesOpt))); + pw2.addOpt(512, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw2.commit(); + + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2); + + BOOST_CHECK_EQUAL(hash1, hash2); + /* the hash is the same but we should _not_ match */ + BOOST_CHECK(!PacketCache::queryMatches(spacket1, spacket2, qname)); + } +} + +BOOST_AUTO_TEST_CASE(test_PacketCacheRecSimple) { + + const DNSName qname("www.powerdns.com."); + uint16_t qtype = QType::AAAA; + EDNSSubnetOpts opt; + DNSPacketWriter::optvect_t ednsOptions; + uint16_t ecsBegin; + uint16_t ecsEnd; + + { + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + pw1.addOpt(512, 0, 0); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + /* set the RD length to a large value */ + unsigned char* ptr = reinterpret_cast(&spacket1.at(sizeof(dnsheader) + qname.wirelength() + /* qtype and qclass */ 4 + /* OPT root label (1), type (2), class (2) and ttl (4) */ 9)); + *ptr = 255; + *(ptr + 1) = 255; + /* truncate the end of the OPT header to try to trigger an out of bounds read */ + spacket1.resize(spacket1.size() - 6); + PacketCache::canHashPacket(spacket1, &ecsBegin, &ecsEnd); + /* no ECS */ + BOOST_CHECK_EQUAL(ecsBegin, 0); + BOOST_CHECK_EQUAL(ecsEnd, 0); + } +} + +BOOST_AUTO_TEST_CASE(test_PacketCacheRecCollision) { + + /* rec version (ECS is processed, we hash the whole query except for the ID and the ECS value, while lowercasing the qname) */ + const DNSName qname("www.powerdns.com."); + uint16_t qtype = QType::AAAA; + EDNSSubnetOpts opt; + DNSPacketWriter::optvect_t ednsOptions; + uint16_t ecsBegin; + uint16_t ecsEnd; + + { + /* same query, different IDs */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1, &ecsBegin, &ecsEnd); + /* no ECS */ + BOOST_CHECK_EQUAL(ecsBegin, 0); + BOOST_CHECK_EQUAL(ecsEnd, 0); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2, &ecsBegin, &ecsEnd); + /* no ECS */ + BOOST_CHECK_EQUAL(ecsBegin, 0); + BOOST_CHECK_EQUAL(ecsEnd, 0); + + BOOST_CHECK_EQUAL(hash1, hash2); + BOOST_CHECK(PacketCache::queryMatches(spacket1, spacket2, qname, ecsBegin, ecsEnd)); + } + + { + /* same query, different IDs, different ECS, still hashes to the same value */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + opt.source = Netmask("10.0.18.199/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + pw1.addOpt(512, 0, 0, ednsOptions); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1, &ecsBegin, &ecsEnd); + /* ECS value */ + BOOST_CHECK_EQUAL(ecsBegin, sizeof(dnsheader) + qname.wirelength() + ( 2 * sizeof(uint16_t)) /* qtype */ + (2 * sizeof(uint16_t)) /* qclass */ + /* OPT root label */ 1 + sizeof(uint32_t) /* TTL */ + DNS_RDLENGTH_SIZE); + BOOST_CHECK_EQUAL(ecsEnd, ecsBegin + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 /* family */ + 1 /* scope length */ + 1 /* source length */ + 4 /* IPv4 */); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + opt.source = Netmask("10.0.131.66/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + pw2.addOpt(512, 0, 0, ednsOptions); + pw2.commit(); + + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2, &ecsBegin, &ecsEnd); + /* ECS value */ + BOOST_CHECK_EQUAL(ecsBegin, sizeof(dnsheader) + qname.wirelength() + ( 2 * sizeof(uint16_t)) /* qtype */ + (2 * sizeof(uint16_t)) /* qclass */ + /* OPT root label */ 1 + sizeof(uint32_t) /* TTL */ + DNS_RDLENGTH_SIZE); + BOOST_CHECK_EQUAL(ecsEnd, ecsBegin + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 /* family */ + 1 /* scope length */ + 1 /* source length */ + 4 /* IPv4 */); + + BOOST_CHECK_EQUAL(hash1, hash2); + /* the hash is the same and we don't hash the ECS so we should match */ + BOOST_CHECK(PacketCache::queryMatches(spacket1, spacket2, qname, ecsBegin, ecsEnd)); + } + + { + /* same query but different cookies, still hashes to the same value */ + vector packet; + DNSPacketWriter pw1(packet, qname, qtype); + pw1.getHeader()->rd = true; + pw1.getHeader()->qr = false; + pw1.getHeader()->id = 0x42; + opt.source = Netmask("192.0.2.1/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + EDNSCookiesOpt cookiesOpt; + cookiesOpt.client = string("deadbeef"); + cookiesOpt.server = string("deadbeef"); + cookiesOpt.server[4] = -20; + cookiesOpt.server[5] = -114; + cookiesOpt.server[6] = 0; + cookiesOpt.server[7] = 0; + ednsOptions.push_back(std::make_pair(EDNSOptionCode::COOKIE, makeEDNSCookiesOptString(cookiesOpt))); + pw1.addOpt(512, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw1.commit(); + + string spacket1((const char*)&packet[0], packet.size()); + auto hash1 = PacketCache::canHashPacket(spacket1, &ecsBegin, &ecsEnd); + /* ECS value */ + BOOST_CHECK_EQUAL(ecsBegin, sizeof(dnsheader) + qname.wirelength() + ( 2 * sizeof(uint16_t)) /* qtype */ + (2 * sizeof(uint16_t)) /* qclass */ + /* OPT root label */ 1 + sizeof(uint32_t) /* TTL */ + DNS_RDLENGTH_SIZE); + BOOST_CHECK_EQUAL(ecsEnd, ecsBegin + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 /* family */ + 1 /* scope length */ + 1 /* source length */ + 4 /* IPv4 */); + + packet.clear(); + DNSPacketWriter pw2(packet, qname, qtype); + pw2.getHeader()->rd = true; + pw2.getHeader()->qr = false; + pw2.getHeader()->id = 0x84; + opt.source = Netmask("192.0.2.1/32"); + ednsOptions.clear(); + ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt))); + cookiesOpt.client = string("deadbeef"); + cookiesOpt.server = string("deadbeef"); + cookiesOpt.server[4] = 103; + cookiesOpt.server[5] = 68; + cookiesOpt.server[6] = 0; + cookiesOpt.server[7] = 0; + ednsOptions.push_back(std::make_pair(EDNSOptionCode::COOKIE, makeEDNSCookiesOptString(cookiesOpt))); + pw2.addOpt(512, 0, EDNSOpts::DNSSECOK, ednsOptions); + pw2.commit(); + + string spacket2((const char*)&packet[0], packet.size()); + auto hash2 = PacketCache::canHashPacket(spacket2, &ecsBegin, &ecsEnd); + /* ECS value */ + BOOST_CHECK_EQUAL(ecsBegin, sizeof(dnsheader) + qname.wirelength() + ( 2 * sizeof(uint16_t)) /* qtype */ + (2 * sizeof(uint16_t)) /* qclass */ + /* OPT root label */ 1 + sizeof(uint32_t) /* TTL */ + DNS_RDLENGTH_SIZE); + BOOST_CHECK_EQUAL(ecsEnd, ecsBegin + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE + 2 /* family */ + 1 /* scope length */ + 1 /* source length */ + 4 /* IPv4 */); + + BOOST_CHECK_EQUAL(hash1, hash2); + /* the hash is the same but we should _not_ match, even though we skip the ECS part, because the cookies are different */ + BOOST_CHECK(!PacketCache::queryMatches(spacket1, spacket2, qname, ecsBegin, ecsEnd)); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-rcpgenerator_cc.cc b/pdns/test-rcpgenerator_cc.cc new file mode 100644 index 0000000..a5303cd --- /dev/null +++ b/pdns/test-rcpgenerator_cc.cc @@ -0,0 +1,34 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "rcpgenerator.hh" +#include "misc.hh" +#include + +using std::string; + +BOOST_AUTO_TEST_SUITE(test_rcpgenerator_cc) + +BOOST_AUTO_TEST_CASE(test_xfrIP6) { + RecordTextReader rtr("::1"); + string rawIPv6; + rtr.xfrIP6(rawIPv6); + string loopback6; + loopback6.append(15, 0); + loopback6.append(1,1); + BOOST_CHECK_EQUAL(makeHexDump(rawIPv6), makeHexDump(loopback6)); + + RecordTextReader rtr2("2a01:4f8:d12:1880::5"); + rtr2.xfrIP6(rawIPv6); + string ip6("\x2a\x01\x04\xf8\x0d\x12\x18\x80\x00\x00\x00\x00\x00\x00\x00\x05", 16); + BOOST_CHECK_EQUAL(makeHexDump(rawIPv6), makeHexDump(ip6)); + + +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/pdns/test-sha_hh.cc b/pdns/test-sha_hh.cc new file mode 100644 index 0000000..a0753bc --- /dev/null +++ b/pdns/test-sha_hh.cc @@ -0,0 +1,63 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include + +#include "sha.hh" +#include "misc.hh" + +using namespace boost; +using namespace boost::assign; + +BOOST_AUTO_TEST_SUITE(test_sha_hh) + +// input, output +typedef boost::tuple case_t; +typedef std::vector cases_t; + +BOOST_AUTO_TEST_CASE(test_sha1) { + cases_t cases = list_of + (case_t("abc", "a9 99 3e 36 47 06 81 6a ba 3e 25 71 78 50 c2 6c 9c d0 d8 9d ")) + (case_t("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84 98 3e 44 1c 3b d2 6e ba ae 4a a1 f9 51 29 e5 e5 46 70 f1 ")); + + for(case_t& val : cases) { + BOOST_CHECK_EQUAL(makeHexDump(pdns_sha1sum(val.get<0>())), val.get<1>()); + } +} + +BOOST_AUTO_TEST_CASE(test_sha256) { + cases_t cases = list_of + (case_t("abc", "ba 78 16 bf 8f 01 cf ea 41 41 40 de 5d ae 22 23 b0 03 61 a3 96 17 7a 9c b4 10 ff 61 f2 00 15 ad ")) + (case_t("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "24 8d 6a 61 d2 06 38 b8 e5 c0 26 93 0c 3e 60 39 a3 3c e4 59 64 ff 21 67 f6 ec ed d4 19 db 06 c1 ")); + + for(case_t& val : cases) { + BOOST_CHECK_EQUAL(makeHexDump(pdns_sha256sum(val.get<0>())), val.get<1>()); + } +} + +BOOST_AUTO_TEST_CASE(test_sha384) { + cases_t cases = list_of + (case_t("abc", "cb 00 75 3f 45 a3 5e 8b b5 a0 3d 69 9a c6 50 07 27 2c 32 ab 0e de d1 63 1a 8b 60 5a 43 ff 5b ed 80 86 07 2b a1 e7 cc 23 58 ba ec a1 34 c8 25 a7 ")) + (case_t("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "33 91 fd dd fc 8d c7 39 37 07 a6 5b 1b 47 09 39 7c f8 b1 d1 62 af 05 ab fe 8f 45 0d e5 f3 6b c6 b0 45 5a 85 20 bc 4e 6f 5f e9 5b 1f e3 c8 45 2b ")); + + for(case_t& val : cases) { + BOOST_CHECK_EQUAL(makeHexDump(pdns_sha384sum(val.get<0>())), val.get<1>()); + } +} + +BOOST_AUTO_TEST_CASE(test_sha512) { + cases_t cases = list_of + (case_t("abc", "dd af 35 a1 93 61 7a ba cc 41 73 49 ae 20 41 31 12 e6 fa 4e 89 a9 7e a2 0a 9e ee e6 4b 55 d3 9a 21 92 99 2a 27 4f c1 a8 36 ba 3c 23 a3 fe eb bd 45 4d 44 23 64 3c e8 0e 2a 9a c9 4f a5 4c a4 9f ")) + (case_t("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "20 4a 8f c6 dd a8 2f 0a 0c ed 7b eb 8e 08 a4 16 57 c1 6e f4 68 b2 28 a8 27 9b e3 31 a7 03 c3 35 96 fd 15 c1 3b 1b 07 f9 aa 1d 3b ea 57 78 9c a0 31 ad 85 c7 a7 1d d7 03 54 ec 63 12 38 ca 34 45 ")); + + for(case_t& val : cases) { + BOOST_CHECK_EQUAL(makeHexDump(pdns_sha512sum(val.get<0>())), val.get<1>()); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-signers.cc b/pdns/test-signers.cc new file mode 100644 index 0000000..6b8f77f --- /dev/null +++ b/pdns/test-signers.cc @@ -0,0 +1,260 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include + +#include "base64.hh" +#include "dnsseckeeper.hh" +#include "dnssecinfra.hh" +#include "misc.hh" +BOOST_AUTO_TEST_SUITE(test_signers) + +static const std::string message = "Very good, young padawan."; + +static const struct signerParams +{ + std::string iscMap; + std::string dsSHA1; + std::string dsSHA256; + std::string dsSHA384; + std::vector signature; + std::string zoneRepresentation; + std::string name; + std::string rfcMsgDump; + std::string rfcB64Signature; + unsigned int bits; + uint16_t flags; + uint16_t rfcFlags; + uint8_t algorithm; + bool isDeterministic; +} signers[] = { + /* RSA from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h */ + { "Algorithm: 8\n" + "Modulus: qtunSiHnYq4XRLBehKAw1Glxb+48oIpAC7w3Jhpj570bb2uHt6orWGqnuyRtK8oqUi2ABoV0PFm8+IPgDMEdCQ==\n" + "PublicExponent: AQAB\n" + "PrivateExponent: MiItniUAngXzMeaGdWgDq/AcpvlCtOCcFlVt4TJRKkfp8DNRSxIxG53NNlOFkp1W00iLHqYC2GrH1qkKgT9l+Q==\n" + "Prime1: 3sZmM+5FKFy5xaRt0n2ZQOZ2C+CoKzVil6/al9LmYVs=\n" + "Prime2: xFcNWSIW6v8dDL2JQ1kxFDm/8RVeUSs1BNXXnvCjBGs=\n" + "Exponent1: WuUwhjfN1+4djlrMxHmisixWNfpwI1Eg7Ss/UXsnrMk=\n" + "Exponent2: vfMqas1cNsXRqP3Fym6D2Pl2BRuTQBv5E1B/ZrmQPTk=\n" + "Coefficient: Q10z43cA3hkwOkKsj5T0W5jrX97LBwZoY5lIjDCa4+M=\n", + "1506 8 1 172a500b374158d1a64ba3073cdbbc319b2fdf2c", + "1506 8 2 253b099ff47b02c6ffa52695a30a94c6681c56befe0e71a5077d6f79514972f9", + "1506 8 4 22ea940600dc2d9a98b1126c26ac0dc5c91b31eb50fe784b36ad675e9eecfe6573c1f85c53b6bc94580f3ac443d13c4c", + /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ + { 0x93, 0x93, 0x5f, 0xd8, 0xa1, 0x2b, 0x4c, 0x0b, 0xf3, 0x67, 0x42, 0x13, 0x52, 0x00, 0x35, 0xdc, 0x09, 0xe0, 0xdf, 0xe0, 0x3e, 0xc2, 0xcf, 0x64, 0xab, 0x9f, 0x9f, 0x51, 0x5f, 0x5c, 0x27, 0xbe, 0x13, 0xd6, 0x17, 0x07, 0xa6, 0xe4, 0x3b, 0x63, 0x44, 0x85, 0x06, 0x13, 0xaa, 0x01, 0x3c, 0x58, 0x52, 0xa3, 0x98, 0x20, 0x65, 0x03, 0xd0, 0x40, 0xc8, 0xa0, 0xe9, 0xd2, 0xc0, 0x03, 0x5a, 0xab }, + "256 3 8 AwEAAarbp0oh52KuF0SwXoSgMNRpcW/uPKCKQAu8NyYaY+e9G29rh7eqK1hqp7skbSvKKlItgAaFdDxZvPiD4AzBHQk=", + "rsa.", + "", + "", + 512, + 256, + 0, + DNSSECKeeper::RSASHA256, + true + }, +#ifdef HAVE_LIBCRYPTO_ECDSA + /* ECDSA-P256-SHA256 from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h */ + { "Algorithm: 13\n" + "PrivateKey: iyLIPdk3DOIxVmmSYlmTstbtUPiVlEyDX46psyCwNVQ=\n", + "5345 13 1 954103ac7c43810ce9f414e80f30ab1cbe49b236", + "5345 13 2 bac2107036e735b50f85006ce409a19a3438cab272e70769ebda032239a3d0ca", + "5345 13 4 a0ac6790483872be72a258314200a88ab75cdd70f66a18a09f0f414c074df0989fdb1df0e67d82d4312cda67b93a76c1", + /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ + { 0xa2, 0x95, 0x76, 0xb5, 0xf5, 0x7e, 0xbd, 0xdd, 0xf5, 0x62, 0xa2, 0xc3, 0xa4, 0x8d, 0xd4, 0x53, 0x5c, 0xba, 0x29, 0x71, 0x8c, 0xcc, 0x28, 0x7b, 0x58, 0xf3, 0x1e, 0x4e, 0x58, 0xe2, 0x36, 0x7e, 0xa0, 0x1a, 0xb6, 0xe6, 0x29, 0x71, 0x1b, 0xd3, 0x8c, 0x88, 0xc3, 0xee, 0x12, 0x0e, 0x69, 0x70, 0x55, 0x99, 0xec, 0xd5, 0xf6, 0x4f, 0x4b, 0xe2, 0x41, 0xd9, 0x10, 0x7e, 0x67, 0xe5, 0xad, 0x2f, }, + "256 3 13 8uD7C4THTM/w7uhryRSToeE/jKT78/p853RX0L5EwrZrSLBubLPiBw7gbvUP6SsIga5ZQ4CSAxNmYA/gZsuXzA==", + "ecdsa.", + "", + "", + 256, + 256, + 0, + DNSSECKeeper::ECDSA256, + false + }, +#endif /* HAVE_LIBCRYPTO_ECDSA */ +#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBDECAF) || defined(HAVE_LIBCRYPTO_ED25519) + /* ed25519 from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h, + also from rfc8080 section 6.1 */ + { "Algorithm: 15\n" + "PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=\n", + "3612 15 1 501249721e1f09a79d30d5c6c4dca1dc1da4ed5d", + "3612 15 2 1b1c8766b2a96566ff196f77c0c4194af86aaa109c5346ff60231a27d2b07ac0", + "3612 15 4 d11831153af4985efbd0ae792c967eb4aff3c35488db95f7e2f85dcec74ae8f59f9a72641798c91c67c675db1d710c18", + /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ + { 0x0a, 0x9e, 0x51, 0x5f, 0x16, 0x89, 0x49, 0x27, 0x0e, 0x98, 0x34, 0xd3, 0x48, 0xef, 0x5a, 0x6e, 0x85, 0x2f, 0x7c, 0xd6, 0xd7, 0xc8, 0xd0, 0xf4, 0x2c, 0x68, 0x8c, 0x1f, 0xf7, 0xdf, 0xeb, 0x7c, 0x25, 0xd6, 0x1a, 0x76, 0x3e, 0xaf, 0x28, 0x1f, 0x1d, 0x08, 0x10, 0x20, 0x1c, 0x01, 0x77, 0x1b, 0x5a, 0x48, 0xd6, 0xe5, 0x1c, 0xf9, 0xe3, 0xe0, 0x70, 0x34, 0x5e, 0x02, 0x49, 0xfb, 0x9e, 0x05 }, + "256 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=", + "ed25519.", + // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev 476d6ded) by printing signature_data + "00 0f 0f 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 0e 1d 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 ", + // vector verified from dnskey.py as above, and confirmed with https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935 + "oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==", + 256, + 256, + 257, + DNSSECKeeper::ED25519, + true + }, +#endif /* defined(HAVE_LIBSODIUM) || defined(HAVE_LIBDECAF) || defined(HAVE_LIBCRYPTO_ED25519) */ +}; + +static void checkRR(const signerParams& signer) +{ + DNSKEYRecordContent drc; + auto dcke = DNSCryptoKeyEngine::makeFromISCString(drc, signer.iscMap); + DNSSECPrivateKey dpk; + dpk.setKey(dcke); + dpk.d_flags = signer.rfcFlags; + + vector > rrs; + /* values taken from rfc8080 for ed25519 and ed448, rfc5933 for gost */ + DNSName qname(dpk.d_algorithm == 12 ? "www.example.net." : "example.com."); + + reportBasicTypes(); + + RRSIGRecordContent rrc; + uint32_t expire = 1440021600; + uint32_t inception = 1438207200; + + if (dpk.d_algorithm == 12) { + rrc.d_signer = DNSName("example.net."); + inception = 946684800; + expire = 1893456000; + rrs.push_back(DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.1")); + } + else { + rrc.d_signer = qname; + rrs.push_back(DNSRecordContent::mastermake(QType::MX, QClass::IN, "10 mail.example.com.")); + } + + rrc.d_originalttl = 3600; + rrc.d_sigexpire = expire; + rrc.d_siginception = inception; + rrc.d_type = rrs.at(0)->getType(); + rrc.d_labels = qname.countLabels(); + rrc.d_tag = dpk.getTag(); + rrc.d_algorithm = dpk.d_algorithm; + + string msg = getMessageForRRSET(qname, rrc, rrs, false); + + BOOST_CHECK_EQUAL(makeHexDump(msg), signer.rfcMsgDump); + + string signature = dcke->sign(msg); + + BOOST_CHECK(dcke->verify(msg, signature)); + + if (signer.isDeterministic) { + string b64 = Base64Encode(signature); + BOOST_CHECK_EQUAL(b64, signer.rfcB64Signature); + } + else { + std::string raw; + B64Decode(signer.rfcB64Signature, raw); + BOOST_CHECK(dcke->verify(msg, raw)); + } +} + +BOOST_AUTO_TEST_CASE(test_generic_signers) +{ + for (const auto signer : signers) { + DNSKEYRecordContent drc; + auto dcke = DNSCryptoKeyEngine::makeFromISCString(drc, signer.iscMap); + + BOOST_CHECK_EQUAL(dcke->getAlgorithm(), signer.algorithm); + BOOST_CHECK_EQUAL(dcke->getBits(), signer.bits); + BOOST_CHECK_EQUAL(dcke->checkKey(nullptr), true); + + BOOST_CHECK_EQUAL(drc.d_algorithm, signer.algorithm); + + DNSSECPrivateKey dpk; + dpk.setKey(dcke); + dpk.d_flags = signer.flags; + drc = dpk.getDNSKEY(); + + BOOST_CHECK_EQUAL(drc.d_algorithm, signer.algorithm); + BOOST_CHECK_EQUAL(drc.d_protocol, 3); + BOOST_CHECK_EQUAL(drc.getZoneRepresentation(), signer.zoneRepresentation); + + DNSName name(signer.name); + auto ds1 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA1); + if (!signer.dsSHA1.empty()) { + BOOST_CHECK_EQUAL(ds1.getZoneRepresentation(), signer.dsSHA1); + } + + auto ds2 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA256); + if (!signer.dsSHA256.empty()) { + BOOST_CHECK_EQUAL(ds2.getZoneRepresentation(), signer.dsSHA256); + } + + auto ds4 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA384); + if (!signer.dsSHA384.empty()) { + BOOST_CHECK_EQUAL(ds4.getZoneRepresentation(), signer.dsSHA384); + } + + auto signature = dcke->sign(message); + BOOST_CHECK(dcke->verify(message, signature)); + + if (signer.isDeterministic) { + BOOST_CHECK_EQUAL(signature, std::string(signer.signature.begin(), signer.signature.end())); + } else { + /* since the signing process is not deterministic, we can't directly compare our signature + with the one we have. Still the one we have should also validate correctly. */ + BOOST_CHECK(dcke->verify(message, std::string(signer.signature.begin(), signer.signature.end()))); + } + + if (!signer.rfcMsgDump.empty() && !signer.rfcB64Signature.empty()) { + checkRR(signer); + } + } +} + +#if defined(HAVE_LIBDECAF) || defined(HAVE_LIBCRYPTO_ED448) +BOOST_AUTO_TEST_CASE(test_ed448_signer) { + vector > rrs; + DNSName qname("example.com."); + DNSKEYRecordContent drc; + + // TODO: make this a collection of inputs and resulting sigs for various algos + shared_ptr engine = DNSCryptoKeyEngine::makeFromISCString(drc, +"Private-key-format: v1.2\n" +"Algorithm: 16 (ED448)\n" +"PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA\n"); + + DNSSECPrivateKey dpk; + dpk.setKey(engine); + + reportBasicTypes(); + + rrs.push_back(DNSRecordContent::mastermake(QType::MX, 1, "10 mail.example.com.")); + + RRSIGRecordContent rrc; + rrc.d_originalttl = 3600; + rrc.d_sigexpire = 1440021600; + rrc.d_siginception = 1438207200; + rrc.d_signer = qname; + rrc.d_type = QType::MX; + rrc.d_labels = 2; + // TODO: derive the next two from the key + rrc.d_tag = 9713; + rrc.d_algorithm = 16; + + string msg = getMessageForRRSET(qname, rrc, rrs, false); + + // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev 476d6ded) by printing signature_data + BOOST_CHECK_EQUAL(makeHexDump(msg), "00 0f 10 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 25 f1 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 "); + + string signature = engine->sign(msg); + string b64 = Base64Encode(signature); + + // vector verified from dnskey.py as above, and confirmed with https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935 + BOOST_CHECK_EQUAL(b64, "3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA"); +} +#endif /* defined(HAVE_LIBDECAF) || defined(HAVE_LIBCRYPTO_ED448) */ + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/test-statbag_cc.cc b/pdns/test-statbag_cc.cc new file mode 100644 index 0000000..601f76c --- /dev/null +++ b/pdns/test-statbag_cc.cc @@ -0,0 +1,109 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include +#include "misc.hh" +#include "dns.hh" +#include "statbag.hh" + +using std::string; + +static void *threadMangler(void* a) +{ + AtomicCounter* ac=(AtomicCounter*)a; + for(unsigned int n=0; n < 1000000; ++n) + (*ac)++; + return 0; +} + +static void *threadMangler2(void* a) +{ + StatBag* S = (StatBag*)a; + for(unsigned int n=0; n < 1000000; ++n) + S->inc("c"); + return 0; +} + + + +BOOST_AUTO_TEST_SUITE(test_misc_hh) + +BOOST_AUTO_TEST_CASE(test_StatBagBasic) { + StatBag s; + s.declare("a", "description"); + s.declare("b", "description"); + s.declare("c", "description"); + s.inc("a"); + BOOST_CHECK_EQUAL(s.read("a"), 1); + + int n; + for(n=0; n < 1000000; ++n) + s.inc("b"); + + BOOST_CHECK_EQUAL(s.read("b"), n); + + AtomicCounter* ac = s.getPointer("a"); + for(n=0; n < 1000000; ++n) + (*ac)++; + + BOOST_CHECK_EQUAL(s.read("a"), n+1); + + AtomicCounter* acc = s.getPointer("c"); + pthread_t tid[4]; + for(int i=0; i < 4; ++i) + pthread_create(&tid[i], 0, threadMangler, (void*)acc); + void* res; + for(int i=0; i < 4 ; ++i) + pthread_join(tid[i], &res); + + BOOST_CHECK_EQUAL(s.read("c"), 4000000U); + + s.set("c", 0); + + for(int i=0; i < 4; ++i) + pthread_create(&tid[i], 0, threadMangler2, (void*)&s); + + for(int i=0; i < 4 ; ++i) + pthread_join(tid[i], &res); + + BOOST_CHECK_EQUAL(s.read("c"), 4000000U); + + + s.set("c", 1ULL<<31); + BOOST_CHECK_EQUAL(s.read("c"), (1ULL<<31) ); + s.inc("c"); + BOOST_CHECK_EQUAL(s.read("c"), (1ULL<<31) +1 ); + +#ifdef UINTPTR_MAX +#if UINTPTR_MAX > 0xffffffffULL + BOOST_CHECK_EQUAL(sizeof(AtomicCounterInner), 8); + s.set("c", 1ULL<<33); + BOOST_CHECK_EQUAL(s.read("c"), (1ULL<<33) ); + s.inc("c"); + BOOST_CHECK_EQUAL(s.read("c"), (1ULL<<33) +1 ); + + s.set("c", ~0ULL); + BOOST_CHECK_EQUAL(s.read("c"), 0xffffffffffffffffULL ); + s.inc("c"); + BOOST_CHECK_EQUAL(s.read("c"), 0 ); +#else + BOOST_CHECK_EQUAL(sizeof(AtomicCounterInner), 4); + BOOST_CHECK_EQUAL(~0UL, 0xffffffffUL); + s.set("c", ~0UL); + BOOST_CHECK_EQUAL(s.read("c"), 0xffffffffUL ); + s.inc("c"); + BOOST_CHECK_EQUAL(s.read("c"), 0 ); +#endif +#endif +} + + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/pdns/test-tsig.cc b/pdns/test-tsig.cc new file mode 100644 index 0000000..9e8761a --- /dev/null +++ b/pdns/test-tsig.cc @@ -0,0 +1,243 @@ + +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2013 - 2015 PowerDNS.COM BV + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation + + Additionally, the license of this program contains a special + exception which allows to distribute the program in binary form when + it is linked against OpenSSL. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "dnssecinfra.hh" +#include "dnswriter.hh" +#include "misc.hh" +#include "tsigverifier.hh" + +BOOST_AUTO_TEST_SUITE(test_tsig) + +static vector generateTSIGQuery(const DNSName& qname, const DNSName& tsigName, const DNSName& tsigAlgo, const string& tsigSecret, uint16_t fudge=300, time_t tsigTime=time(nullptr)) +{ + vector packet; + DNSPacketWriter pw(packet, qname, QType::A); + pw.getHeader()->qr=0; + pw.getHeader()->rd=0; + pw.getHeader()->id=42; + pw.startRecord(qname, QType::A); + pw.xfr32BitInt(0x01020304); + pw.addOpt(512, 0, 0); + pw.commit(); + + TSIGTriplet tt; + tt.name = tsigName; + tt.algo = tsigAlgo; + tt.secret = tsigSecret; + + TSIGHashEnum the; + BOOST_REQUIRE(getTSIGHashEnum(tt.algo, the)); + + TSIGRecordContent trc; + trc.d_algoName = getTSIGAlgoName(the); + trc.d_time = tsigTime; + trc.d_fudge = fudge; + trc.d_origID = ntohs(pw.getHeader()->id); + trc.d_eRcode = 0; + + addTSIG(pw, trc, tt.name, tt.secret, "", false); + return packet; +} + +static void checkTSIG(const DNSName& tsigName, const DNSName& tsigAlgo, const string& tsigSecret, const vector& packet, const string* overrideMac=nullptr, uint16_t* overrideExtendedRCode=nullptr, uint16_t* overrideOrigID=nullptr) +{ + string packetStr(reinterpret_cast(packet.data()), packet.size()); + MOADNSParser mdp(true, packetStr); + + bool tsigFound = false; + string theirMac; + DNSName keyName; + TSIGRecordContent trc; + + for(const auto& answer: mdp.d_answers) { + if(answer.first.d_type == QType::TSIG) { + BOOST_CHECK_EQUAL(answer.first.d_place, DNSResourceRecord::ADDITIONAL); + BOOST_CHECK_EQUAL(answer.first.d_class, QClass::ANY); + BOOST_CHECK_EQUAL(answer.first.d_ttl, 0); + BOOST_CHECK_EQUAL(tsigFound, false); + + shared_ptr rectrc = getRR(answer.first); + if (rectrc) { + trc = *rectrc; + theirMac = rectrc->d_mac; + keyName = answer.first.d_name; + tsigFound = true; + } + } + } + + if (overrideMac) { + theirMac = *overrideMac; + } + + if (overrideOrigID) { + trc.d_origID = *overrideOrigID; + } + + if (overrideExtendedRCode) { + trc.d_eRcode = *overrideExtendedRCode; + } + + BOOST_REQUIRE(tsigFound); + TSIGTriplet tt; + tt.name = tsigName; + tt.algo = tsigAlgo; + tt.secret = tsigSecret; + + BOOST_CHECK(validateTSIG(packetStr, mdp.getTSIGPos(), tt, trc, "", theirMac, false)); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_valid) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + checkTSIG(tsigName, tsigAlgo, tsigSecret, packet);} + + +BOOST_AUTO_TEST_CASE(test_TSIG_different_case_algo) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + checkTSIG(tsigName, tsigAlgo.makeLowerCase(), tsigSecret, packet); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_different_name_same_algo) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + checkTSIG(tsigName, DNSName("hmac-md5."), tsigSecret, packet); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_key_name) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + BOOST_CHECK_THROW(checkTSIG(DNSName("another.tsig.key.name"), tsigAlgo, tsigSecret, packet), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_algo) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + BOOST_CHECK_THROW(checkTSIG(tsigName, DNSName("hmac-sha512."), tsigSecret, packet), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_secret) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, "bad secret", packet), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_ercode) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + uint16_t badERcode = 1; + + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, nullptr, &badERcode), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_origID) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + uint16_t badOrigID = 1; + + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, nullptr, nullptr, &badOrigID), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_bad_mac) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + string badMac = "badmac"; + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet, &badMac), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_signature_expired) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret, 5, time(nullptr) - 10); + + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(test_TSIG_signature_too_far_in_the_future) { + DNSName tsigName("tsig.name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret, 5, time(nullptr) + 20); + + BOOST_CHECK_THROW(checkTSIG(tsigName, tsigAlgo, tsigSecret, packet), std::runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/pdns/test-zoneparser_tng_cc.cc b/pdns/test-zoneparser_tng_cc.cc new file mode 100644 index 0000000..d923d52 --- /dev/null +++ b/pdns/test-zoneparser_tng_cc.cc @@ -0,0 +1,57 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#include +#include "dns.hh" +#include "zoneparser-tng.hh" +#include "dnsrecords.hh" +#include "dnsname.hh" +#include +#include + +BOOST_AUTO_TEST_SUITE(test_zoneparser_tng_cc) + +BOOST_AUTO_TEST_CASE(test_tng_record_types) { + reportAllTypes(); + + std::ostringstream pathbuf; + const char* p = std::getenv("SRCDIR"); + if(!p) + p = "."; + pathbuf << p << "/../regression-tests/zones/unit.test"; + ZoneParserTNG zp(pathbuf.str(), DNSName("unit.test")); + DNSResourceRecord rr; + + ifstream ifs(pathbuf.str()); + + while(zp.get(rr)) { + // make sure these concur. + std::string host, type, data; + unsigned int ttl; + std::getline(ifs, host, ' '); + std::getline(ifs, type, ' '); + ttl = pdns_stou(type); + std::getline(ifs, type, ' '); + std::getline(ifs, type, ' '); + std::getline(ifs, data, '\n'); + // see if these agree + BOOST_CHECK_EQUAL(rr.qname.toString(), host); + BOOST_CHECK_EQUAL(rr.ttl, ttl); + BOOST_CHECK_EQUAL(rr.qtype.getName(), type); + if (rr.qtype == QType::SOA) + continue; // FIXME400 remove trailing dots from data + if (*(rr.content.rbegin()) != '.' && *(data.rbegin()) == '.') + BOOST_CHECK_EQUAL(rr.content, std::string(data.begin(),data.end()-1)); + else + BOOST_CHECK_EQUAL(rr.content, data); + } + +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/pdns/testrunner.cc b/pdns/testrunner.cc new file mode 100644 index 0000000..0ea1545 --- /dev/null +++ b/pdns/testrunner.cc @@ -0,0 +1,31 @@ +#define BOOST_TEST_DYN_LINK + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include "arguments.hh" +#include "auth-packetcache.hh" +#include "auth-querycache.hh" +#include "statbag.hh" +StatBag S; +AuthPacketCache PC; +AuthQueryCache QC; + +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} + + +bool init_unit_test() { + reportAllTypes(); + return true; +} + +// entry point: +int main(int argc, char* argv[]) +{ + return boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); +} diff --git a/pdns/threadname.cc b/pdns/threadname.cc new file mode 100644 index 0000000..249248a --- /dev/null +++ b/pdns/threadname.cc @@ -0,0 +1,69 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#if HAVE_PTHREAD_NP_H +#include +#endif + +#ifdef DNSDIST +#include "dolog.hh" +#else +#include "logger.hh" +#endif + +#include "threadname.hh" + +void setThreadName(const std::string& threadName) { + int retval = 0; + +#ifdef HAVE_PTHREAD_SETNAME_NP_2 + retval = pthread_setname_np(pthread_self(), threadName.c_str()); +#endif +#ifdef HAVE_PTHREAD_SET_NAME_NP_2 + retval = pthread_set_name_np(pthread_self(), threadName.c_str()); +#endif +#ifdef HAVE_PTHREAD_SET_NAME_NP_2_VOID + pthread_set_name_np(pthread_self(), threadName.c_str()); +#endif +#ifdef HAVE_PTHREAD_SETNAME_NP_1 + retval = pthread_setname_np(threadName.c_str()); +#endif +#ifdef HAVE_PTHREAD_SETNAME_NP_3 + retval = pthread_setname_np(pthread_self(), threadName.c_str(), nullptr); +#endif + + if (retval != 0) { +#ifdef DNSDIST + warnlog("Could not set thread name %s for thread: %s", threadName, strerror(retval)); +#else + g_log< + +void setThreadName(const std::string& threadName); diff --git a/pdns/tkey.cc b/pdns/tkey.cc new file mode 100644 index 0000000..b8d9ce8 --- /dev/null +++ b/pdns/tkey.cc @@ -0,0 +1,99 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "packethandler.hh" + +void PacketHandler::tkeyHandler(DNSPacket *p, DNSPacket *r) { + TKEYRecordContent tkey_in; + std::shared_ptr tkey_out(new TKEYRecordContent()); + DNSName name; + bool sign = false; + + if (!p->getTKEYRecord(&tkey_in, &name)) { + g_log<setRcode(RCode::FormErr); + return; + } + + // retain original name for response + tkey_out->d_error = 0; + tkey_out->d_mode = tkey_in.d_mode; + tkey_out->d_algo = tkey_in.d_algo; + tkey_out->d_inception = time((time_t*)NULL); + tkey_out->d_expiration = tkey_out->d_inception+15; + + GssContext ctx(name); + + if (tkey_in.d_mode == 3) { // establish context + if (tkey_in.d_algo == DNSName("gss-tsig.")) { + std::vector meta; + DNSName tmpName(name); + do { + if (B.getDomainMetadata(tmpName, "GSS-ACCEPTOR-PRINCIPAL", meta) && meta.size()>0) { + break; + } + } while(tmpName.chopOff()); + + if (meta.size()>0) { + ctx.setLocalPrincipal(meta[0]); + } + // try to get a context + if (!ctx.accept(tkey_in.d_key, tkey_out->d_key)) + tkey_out->d_error = 19; + else + sign = true; + } else { + tkey_out->d_error = 21; // BADALGO + } + } else if (tkey_in.d_mode == 5) { // destroy context + if (p->d_havetsig == false) { // unauthenticated + if (p->d.opcode == Opcode::Update) + r->setRcode(RCode::Refused); + else + r->setRcode(RCode::NotAuth); + return; + } + if (ctx.valid()) + ctx.destroy(); + else + tkey_out->d_error = 20; // BADNAME (because we have no support for anything here) + } else { + if (p->d_havetsig == false && tkey_in.d_mode != 2) { // unauthenticated + if (p->d.opcode == Opcode::Update) + r->setRcode(RCode::Refused); + else + r->setRcode(RCode::NotAuth); + return; + } + tkey_out->d_error = 19; // BADMODE + } + + tkey_out->d_keysize = tkey_out->d_key.size(); + tkey_out->d_othersize = tkey_out->d_other.size(); + + DNSZoneRecord zrr; + + zrr.dr.d_name = name; + zrr.dr.d_ttl = 0; + zrr.dr.d_type = QType::TKEY; + zrr.dr.d_class = QClass::ANY; + zrr.dr.d_content = tkey_out; + zrr.dr.d_place = DNSResourceRecord::ANSWER; + r->addRecord(zrr); + + if (sign) + { + TSIGRecordContent trc; + trc.d_algoName = DNSName("gss-tsig"); + trc.d_time = tkey_out->d_inception; + trc.d_fudge = 300; + trc.d_mac = ""; + trc.d_origID = p->d.id; + trc.d_eRcode = 0; + trc.d_otherData = ""; + // this should cause it to lookup name context + r->setTSIGDetails(trc, name, name.toStringNoDot(), "", false); + } + + r->commitD(); +} diff --git a/pdns/toysdig.cc b/pdns/toysdig.cc new file mode 100644 index 0000000..82fba87 --- /dev/null +++ b/pdns/toysdig.cc @@ -0,0 +1,183 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "dnsparser.hh" +#include "rec-lua-conf.hh" +#include "sstuff.hh" +#include "misc.hh" +#include "dnswriter.hh" +#include "dnsrecords.hh" +#include "statbag.hh" +#include "ednssubnet.hh" +#include "dnssecinfra.hh" +#include "recursor_cache.hh" +#include "base32.hh" +#include "root-dnssec.hh" + +#include "validate.hh" +StatBag S; + +class TCPResolver : public boost::noncopyable +{ +public: + TCPResolver(ComboAddress addr) : d_rsock(AF_INET, SOCK_STREAM) + { + d_rsock.connect(addr); + } + + string query(const DNSName& qname, uint16_t qtype) + { + cerr<<"Q "< packet; + DNSPacketWriter pw(packet, qname, qtype); + + // recurse + pw.getHeader()->rd=true; + + // we'll do the validation + pw.getHeader()->cd=true; + pw.getHeader()->ad=true; + + // we do require DNSSEC records to do that! + pw.addOpt(2800, 0, EDNSOpts::DNSSECOK); + pw.commit(); + + uint16_t len; + len = htons(packet.size()); + if(d_rsock.write((char *) &len, 2) != 2) + throw PDNSException("tcp write failed"); + + d_rsock.writen(string(packet.begin(), packet.end())); + + int bread=d_rsock.read((char *) &len, 2); + if( bread <0) + throw PDNSException("tcp read failed: "+std::string(strerror(errno))); + if(bread != 2) + throw PDNSException("EOF on TCP read"); + + len=ntohs(len); + char *creply = new char[len]; + int n=0; + int numread; + while(n get(const DNSName& qname, uint16_t qtype) override + { + TCPResolver tr(d_dest); + string resp=tr.query(qname, qtype); + MOADNSParser mdp(false, resp); + vector ret; + ret.reserve(mdp.d_answers.size()); + for(const auto& a : mdp.d_answers) { + ret.push_back(a.first); + } + return ret; + } +private: + ComboAddress d_dest; +}; + +GlobalStateHolder g_luaconfs; +LuaConfigItems::LuaConfigItems() +{ + for (const auto &dsRecord : rootDSs) { + auto ds=std::dynamic_pointer_cast(DSRecordContent::make(dsRecord)); + dsAnchors[g_rootdnsname].insert(*ds); + } +} + +DNSFilterEngine::DNSFilterEngine() {} + +int main(int argc, char** argv) +try +{ + reportAllTypes(); +// g_rootDS = "19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"; + +// if(argv[5]) +// g_rootDS = argv[5]; + + // g_anchors.insert(DSRecordContent("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")); + if(argc < 4) { + cerr<<"Syntax: toysdig IP-address port question question-type [rootDS]\n"; + exit(EXIT_FAILURE); + } + ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2])); + TCPRecordOracle tro(dest); + DNSName qname(argv[3]); + uint16_t qtype=DNSRecordContent::TypeToNumber(argv[4]); + cout<<"digraph oneshot {"<d_signer<<"/"<d_tag<d_signer, keys); + cerr<<"! state = "<first.first<<"/"<first.second)<second.records.begin(); j!=i->second.records.end(); j++) { + cerr<<"\t% > "<<(*j)->getZoneRepresentation()< packet; + + DNSPacketWriter pw(packet, DNSName(argv[3]), DNSRecordContent::TypeToNumber(argv[4])); + + pw.getHeader()->id=htons(0x4831); + + string key; + B64Decode("Syq9L9WrBWdxBC+HxKok2g==", key); + + DNSName keyname("pdns-b-aa"); + + TSIGRecordContent trc; + trc.d_algoName=DNSName("hmac-md5.sig-alg.reg.int"); + trc.d_time=time(0); + trc.d_fudge=300; + trc.d_origID=ntohs(pw.getHeader()->id); + trc.d_eRcode=0; + + addTSIG(pw, trc, keyname, key, "", false); + + Socket sock(AF_INET, SOCK_DGRAM); + ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2])); + cerr<<"Keyname: '"< res; + while(axfr.getChunk(res)) { + } + return 0; +} +catch(std::exception &e) +{ + cerr<<"Fatal: "< + +/* + * Returns a generated Base64'd TSIG key + * + * Will raise a PDNSException() if algorithm is invalid + */ +std::string makeTSIGKey(const DNSName& algorithm) { + TSIGHashEnum tsigHashEnum; + if (!getTSIGHashEnum(algorithm, tsigHashEnum)) { + throw PDNSException("Invalid TSIG algorithm: " + algorithm.toStringNoDot()); + } + + size_t klen = 64; + if (tsigHashEnum == TSIG_MD5 + || tsigHashEnum == TSIG_SHA1 + || tsigHashEnum == TSIG_SHA224) { + klen = 32; + } + + string tmpkey; + tmpkey.resize(klen); + + // Fill out the key + for (size_t i = 0; i < klen; i += sizeof(uint32_t)) { + uint32_t t = dns_random(std::numeric_limits::max()); + memcpy(&tmpkey.at(i), &t, sizeof(uint32_t)); + } + + return Base64Encode(tmpkey); +} diff --git a/pdns/tsigutils.hh b/pdns/tsigutils.hh new file mode 100644 index 0000000..bffd097 --- /dev/null +++ b/pdns/tsigutils.hh @@ -0,0 +1,26 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsname.hh" +#include + +std::string makeTSIGKey(const DNSName& algorithm); diff --git a/pdns/tsigverifier.cc b/pdns/tsigverifier.cc new file mode 100644 index 0000000..de0471b --- /dev/null +++ b/pdns/tsigverifier.cc @@ -0,0 +1,74 @@ + +#include "tsigverifier.hh" +#include "dnssecinfra.hh" +#include "gss_context.hh" + +bool TSIGTCPVerifier::check(const string& data, const MOADNSParser& mdp) +{ + if(d_tt.name.empty()) { // TSIG verify message + return true; + } + + string theirMac; + bool checkTSIG = false; + // If we have multiple messages, we need to concatenate them together. We also need to make sure we know the location of + // the TSIG record so we can remove it in makeTSIGMessageFromTSIGPacket + d_signData.append(data); + if (mdp.getTSIGPos() == 0) { + d_tsigPos += data.size(); + } + else { + d_tsigPos += mdp.getTSIGPos(); + } + + for(const auto& answer : mdp.d_answers) { + if (answer.first.d_type == QType::SOA) { + // A SOA is either the first or the last record. We need to check TSIG if that's the case. + checkTSIG = true; + } + + if(answer.first.d_type == QType::TSIG) { + shared_ptr trc = getRR(answer.first); + if(trc) { + theirMac = trc->d_mac; + d_trc.d_time = trc->d_time; + d_trc.d_fudge = trc->d_fudge; + d_trc.d_eRcode = trc->d_eRcode; + d_trc.d_origID = trc->d_origID; + checkTSIG = true; + } + } + } + + if(!checkTSIG && d_nonSignedMessages > 99) { // We're allowed to get 100 digest without a TSIG. + throw std::runtime_error("No TSIG message received in last 100 messages of AXFR transfer."); + } + + if (checkTSIG) { + if (theirMac.empty()) { + throw std::runtime_error("No TSIG on AXFR response from "+d_remote.toStringWithPort()+" , should be signed with TSIG key '"+d_tt.name.toLogString()+"'"); + } + + try { + if (!d_prevMac.empty()) { + validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_prevMac, theirMac, true, d_signData.size()-data.size()); + } + else { + validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_trc.d_mac, theirMac, false); + } + } + catch(const std::runtime_error& err) { + throw std::runtime_error("Error while validating TSIG signature on AXFR response from "+d_remote.toStringWithPort()+":"+err.what()); + } + + // Reset and store some values for the next chunks. + d_prevMac = theirMac; + d_nonSignedMessages = 0; + d_signData.clear(); + d_tsigPos = 0; + } + else + d_nonSignedMessages++; + + return true; +} diff --git a/pdns/tsigverifier.hh b/pdns/tsigverifier.hh new file mode 100644 index 0000000..84b87eb --- /dev/null +++ b/pdns/tsigverifier.hh @@ -0,0 +1,22 @@ + +#pragma once + +#include "dnsrecords.hh" +#include "iputils.hh" + +class TSIGTCPVerifier +{ +public: + TSIGTCPVerifier(const TSIGTriplet& tt, const ComboAddress& remote, TSIGRecordContent& trc): d_tt(tt), d_remote(remote), d_trc(trc) + { + } + bool check(const string& data, const MOADNSParser& mdp); +private: + const TSIGTriplet& d_tt; + const ComboAddress& d_remote; + TSIGRecordContent& d_trc; + string d_prevMac; // RFC2845 4.4 + string d_signData; + size_t d_tsigPos{0}; + uint8_t d_nonSignedMessages{0}; // RFC2845 4.4 +}; diff --git a/pdns/ueberbackend.cc b/pdns/ueberbackend.cc new file mode 100644 index 0000000..e33b903 --- /dev/null +++ b/pdns/ueberbackend.cc @@ -0,0 +1,700 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "auth-querycache.hh" +#include "utility.hh" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dns.hh" +#include "arguments.hh" +#include "dnsbackend.hh" +#include "ueberbackend.hh" +#include "dnspacket.hh" +#include "logger.hh" +#include "statbag.hh" + +extern StatBag S; + +vectorUeberBackend::instances; +pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER; + +// initially we are blocked +bool UeberBackend::d_go=false; +pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER; + +//! Loads a module and reports it to all UeberBackend threads +bool UeberBackend::loadmodule(const string &name) +{ + g_log<& modules, const string& path) +{ + for (const auto& module: modules) { + bool res; + if (module.find(".")==string::npos) { + res = UeberBackend::loadmodule(path+"/lib"+module+"backend.so"); + } else if (module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) { + // absolute or current path + res = UeberBackend::loadmodule(module); + } else { + res = UeberBackend::loadmodule(path+"/"+module); + } + + if (res == false) { + return false; + } + } + return true; +} + +void UeberBackend::go(void) +{ + pthread_mutex_lock(&d_mut); + d_go=true; + pthread_cond_broadcast(&d_cond); + pthread_mutex_unlock(&d_mut); +} + +bool UeberBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial) +{ + for(vector::const_iterator i=backends.begin();i!=backends.end();++i) + if((*i)->getDomainInfo(domain, di, getSerial)) + return true; + return false; +} + +bool UeberBackend::createDomain(const DNSName &domain) +{ + for(DNSBackend* mydb : backends) { + if(mydb->createDomain(domain)) { + return true; + } + } + return false; +} + +bool UeberBackend::doesDNSSEC() +{ + for(auto* db : backends) { + if(db->doesDNSSEC()) + return true; + } + return false; +} + +bool UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& id) +{ + id = -1; + for(DNSBackend* db : backends) { + if(db->addDomainKey(name, key, id)) + return true; + } + return false; +} +bool UeberBackend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + for(DNSBackend* db : backends) { + if(db->getDomainKeys(name, keys)) + return true; + } + return false; +} + +bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) +{ + for(DNSBackend* db : backends) { + if(db->getAllDomainMetadata(name, meta)) + return true; + } + return false; +} + +bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ + for(DNSBackend* db : backends) { + if(db->getDomainMetadata(name, kind, meta)) + return true; + } + return false; +} + +bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ + for(DNSBackend* db : backends) { + if(db->setDomainMetadata(name, kind, meta)) + return true; + } + return false; +} + +bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int id) +{ + for(DNSBackend* db : backends) { + if(db->activateDomainKey(name, id)) + return true; + } + return false; +} + +bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int id) +{ + for(DNSBackend* db : backends) { + if(db->deactivateDomainKey(name, id)) + return true; + } + return false; +} + +bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int id) +{ + for(DNSBackend* db : backends) { + if(db->removeDomainKey(name, id)) + return true; + } + return false; +} + + +bool UeberBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) +{ + for(DNSBackend* db : backends) { + if(db->getTSIGKey(name, algorithm, content)) + return true; + } + return false; +} + + +bool UeberBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) +{ + for(DNSBackend* db : backends) { + if(db->setTSIGKey(name, algorithm, content)) + return true; + } + return false; +} + +bool UeberBackend::deleteTSIGKey(const DNSName& name) +{ + for(DNSBackend* db : backends) { + if(db->deleteTSIGKey(name)) + return true; + } + return false; +} + +bool UeberBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +{ + for(DNSBackend* db : backends) { + db->getTSIGKeys(keys); + } + return true; +} + +void UeberBackend::reload() +{ + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + { + ( *i )->reload(); + } +} + +void UeberBackend::rediscover(string *status) +{ + + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + { + string tmpstr; + ( *i )->rediscover(&tmpstr); + if(status) + *status+=tmpstr + (i!=backends.begin() ? "\n" : ""); + } +} + + +void UeberBackend::getUnfreshSlaveInfos(vector* domains) +{ + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + { + ( *i )->getUnfreshSlaveInfos( domains ); + } +} + + + +void UeberBackend::getUpdatedMasters(vector* domains) +{ + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + { + ( *i )->getUpdatedMasters( domains ); + } +} + +bool UeberBackend::getAuth(const DNSName &target, const QType& qtype, SOAData* sd, bool cachedOk) +{ + // A backend can respond to our authority request with the 'best' match it + // has. For example, when asked for a.b.c.example.com. it might respond with + // com. We then store that and keep querying the other backends in case one + // of them has a more specific zone but don't bother asking this specific + // backend again for b.c.example.com., c.example.com. and example.com. + // If a backend has no match it may respond with an empty qname. + + bool found = false; + int cstat; + DNSName shorter(target); + vector > bestmatch (backends.size(), make_pair(target.wirelength()+1, SOAData())); + do { + + // Check cache + if(cachedOk && (d_cache_ttl || d_negcache_ttl)) { + d_question.qtype = QType::SOA; + d_question.qname = shorter; + d_question.zoneId = -1; + + cstat = cacheHas(d_question,d_answers); + + if(cstat == 1 && !d_answers.empty() && d_cache_ttl) { + DLOG(g_log<db = 0; + sd->qname = shorter; + goto found; + } else if(cstat == 0 && d_negcache_ttl) { + DLOG(g_log<::const_iterator i = backends.begin(); + vector >::iterator j = bestmatch.begin(); + for(; i != backends.end() && j != bestmatch.end(); ++i, ++j) { + + DLOG(g_log<first < shorter.wirelength()) { + DLOG(g_log<second.qname<first == shorter.wirelength()) { + DLOG(g_log<second.qname<second; + break; + } else { + DLOG(g_log<getAuth(shorter, sd)) { + DLOG(g_log<qname<qname.empty() && !shorter.isPartOf(sd->qname)) { + throw PDNSException("getAuth() returned an SOA for the wrong zone. Zone '"+sd->qname.toLogString()+"' is not part of '"+shorter.toLogString()+"'"); + } + j->first = sd->qname.wirelength(); + j->second = *sd; + if(sd->qname == shorter) { + break; + } + } else { + DLOG(g_log<qname<qname; + d_question.zoneId = -1; + + DNSZoneRecord rr; + rr.dr.d_name = sd->qname; + rr.dr.d_type = QType::SOA; + rr.dr.d_content = makeSOAContent(*sd); + rr.dr.d_ttl = sd->ttl; + rr.domain_id = sd->domain_id; + + addCache(d_question, {rr}); + } + } + +found: + if(found == (qtype == QType::DS) || target != shorter) { + DLOG(g_log<qname<qname<::const_iterator i=backends.begin();i!=backends.end();++i) + if((*i)->getSOA(domain, sd)) { + if(domain != sd.qname) { + throw PDNSException("getSOA() returned an SOA for the wrong zone. Question: '"+domain.toLogString()+"', answer: '"+sd.qname.toLogString()+"'"); + } + if(d_cache_ttl) { + DNSZoneRecord rr; + rr.dr.d_name = sd.qname; + rr.dr.d_type = QType::SOA; + rr.dr.d_content = makeSOAContent(sd); + rr.dr.d_ttl = sd.ttl; + rr.domain_id = sd.domain_id; + + addCache(d_question, {rr}); + + } + return true; + } + + if(d_negcache_ttl) + addNegCache(d_question); + return false; +} + +bool UeberBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) +{ + for(vector::const_iterator i=backends.begin();i!=backends.end();++i) + if((*i)->superMasterBackend(ip, domain, nsset, nameserver, account, db)) + return true; + return false; +} + +UeberBackend::UeberBackend(const string &pname) +{ + pthread_mutex_lock(&instances_lock); + instances.push_back(this); // report to the static list of ourself + pthread_mutex_unlock(&instances_lock); + + d_negcached=0; + d_ancount=0; + d_domain_id=-1; + d_cached=0; + d_cache_ttl = ::arg().asNum("query-cache-ttl"); + d_negcache_ttl = ::arg().asNum("negquery-cache-ttl"); + + d_tid=pthread_self(); + d_stale=false; + + backends=BackendMakers().all(pname=="key-only"); +} + +void del(DNSBackend* d) +{ + delete d; +} + +void UeberBackend::cleanup() +{ + pthread_mutex_lock(&instances_lock); + + remove(instances.begin(),instances.end(),this); + instances.resize(instances.size()-1); + + pthread_mutex_unlock(&instances_lock); + + for_each(backends.begin(),backends.end(),del); +} + +// returns -1 for miss, 0 for negative match, 1 for hit +int UeberBackend::cacheHas(const Question &q, vector &rrs) +{ + extern AuthQueryCache QC; + + if(!d_cache_ttl && ! d_negcache_ttl) { + return -1; + } + + rrs.clear(); + // g_log<(), d_negcache_ttl, q.zoneId); +} + +void UeberBackend::addCache(const Question &q, const vector &rrs) +{ + extern AuthQueryCache QC; + + if(!d_cache_ttl) + return; + + unsigned int store_ttl = d_cache_ttl; + for(const auto& rr : rrs) { + if (rr.dr.d_ttl < d_cache_ttl) + store_ttl = rr.dr.d_ttl; + if (rr.scopeMask) + return; + } + + QC.insert(q.qname, q.qtype, rrs, store_ttl, q.zoneId); +} + +void UeberBackend::alsoNotifies(const DNSName &domain, set *ips) +{ + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + (*i)->alsoNotifies(domain,ips); +} + +UeberBackend::~UeberBackend() +{ + DLOG(g_log<lookup(qtype, qname,pkt_p,zoneId); + } + else if(cstat==0) { + // cout<<"UeberBackend::lookup("< *domains, bool include_disabled) { + for (vector::iterator i = backends.begin(); i != backends.end(); ++i ) + { + (*i)->getAllDomains(domains, include_disabled); + } +} + +bool UeberBackend::get(DNSZoneRecord &rr) +{ + // cout<<"UeberBackend::get(DNSZoneRecord) called"<& result) +{ + bool rc = false; + for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast::size_type>(maxResults) && i != backends.end(); ++i ) + if ((*i)->searchRecords(pattern, maxResults - result.size(), result)) rc = true; + return rc; +} + +bool UeberBackend::searchComments(const string& pattern, int maxResults, vector& result) +{ + bool rc = false; + for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast::size_type>(maxResults) && i != backends.end(); ++i ) + if ((*i)->searchComments(pattern, maxResults - result.size(), result)) rc = true; + return rc; +} + +AtomicCounter UeberBackend::handle::instances(0); + +UeberBackend::handle::handle() +{ + // g_log<get(r))) { // this backend out of answers + if(ibackends.size()) { + DLOG(g_log<<"Backend #"<backends.size() + <<" out of answers, taking next"<backends[i++]; + d_hinterBackend->lookup(qtype,qname,pkt_p,parent->d_domain_id); + } + else + break; + + DLOG(g_log<<"Now asking backend #"<backends.size()) { + DLOG(g_log<<"UeberBackend reached end of backends"<backends.size(); // don't go on to the next backend + return true; +} diff --git a/pdns/ueberbackend.hh b/pdns/ueberbackend.hh new file mode 100644 index 0000000..658c435 --- /dev/null +++ b/pdns/ueberbackend.hh @@ -0,0 +1,167 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef UEBERBACKEND_HH +#define UEBERBACKEND_HH + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "dnspacket.hh" +#include "dnsbackend.hh" + +#include "namespaces.hh" + +/** This is a very magic backend that allows us to load modules dynamically, + and query them in order. This is persistent over all UeberBackend instantiations + across multiple threads. + + The UeberBackend is transparent for exceptions, which should fall straight through. +*/ + +class UeberBackend : public boost::noncopyable +{ +public: + UeberBackend(const string &pname="default"); + ~UeberBackend(); + + bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db); + + /** Tracks all created UeberBackend instances for us. We use this vector to notify + existing threads of new modules + */ + static vectorinstances; + static pthread_mutex_t instances_lock; + + static bool loadmodule(const string &name); + static bool loadModules(const vector& modules, const string& path); + + static void go(void); + + /** This contains all registered backends. The DynListener modifies this list for us when + new modules are loaded */ + vector backends; + + void cleanup(); + + //! the very magic handle for UeberBackend questions + class handle + { + public: + bool get(DNSZoneRecord &dr); + handle(); + ~handle(); + + //! The UeberBackend class where this handle belongs to + UeberBackend *parent; + //! The current real backend, which is answering questions + DNSBackend *d_hinterBackend; + + //! DNSPacket who asked this question + DNSPacket *pkt_p; + DNSName qname; + + //! Index of the current backend within the backends vector + unsigned int i; + QType qtype; + + private: + + static AtomicCounter instances; + }; + + void lookup(const QType &, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1); + + /** Determines if we are authoritative for a zone, and at what level */ + bool getAuth(const DNSName &target, const QType &qtype, SOAData* sd, bool cachedOk=true); + bool getSOA(const DNSName &domain, SOAData &sd); + /** Load SOA info from backends, ignoring the cache.*/ + bool getSOAUncached(const DNSName &domain, SOAData &sd); + bool get(DNSZoneRecord &r); + void getAllDomains(vector *domains, bool include_disabled=false); + + void getUnfreshSlaveInfos(vector* domains); + void getUpdatedMasters(vector* domains); + bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true); + bool createDomain(const DNSName &domain); + + bool doesDNSSEC(); + bool addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& id); + bool getDomainKeys(const DNSName& name, std::vector& keys); + bool getAllDomainMetadata(const DNSName& name, std::map >& meta); + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta); + bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta); + + bool removeDomainKey(const DNSName& name, unsigned int id); + bool activateDomainKey(const DNSName& name, unsigned int id); + bool deactivateDomainKey(const DNSName& name, unsigned int id); + + bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content); + bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content); + bool deleteTSIGKey(const DNSName& name); + bool getTSIGKeys(std::vector< struct TSIGKey > &keys); + + void alsoNotifies(const DNSName &domain, set *ips); + void rediscover(string* status=0); + void reload(); + bool searchRecords(const string &pattern, int maxResults, vector& result); + bool searchComments(const string &pattern, int maxResults, vector& result); +private: + pthread_t d_tid; + handle d_handle; + vector d_answers; + vector::const_iterator d_cachehandleiter; + + static pthread_mutex_t d_mut; + static pthread_cond_t d_cond; + + struct Question + { + DNSName qname; + int zoneId; + QType qtype; + }d_question; + + unsigned int d_cache_ttl, d_negcache_ttl; + int d_domain_id; + int d_ancount; + + bool d_negcached; + bool d_cached; + static bool d_go; + bool d_stale; + + int cacheHas(const Question &q, vector &rrs); + void addNegCache(const Question &q); + void addCache(const Question &q, const vector &rrs); + +}; + +#endif diff --git a/pdns/unix_semaphore.cc b/pdns/unix_semaphore.cc new file mode 100644 index 0000000..a4b25b6 --- /dev/null +++ b/pdns/unix_semaphore.cc @@ -0,0 +1,186 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include +#include +#include +#include +#include "pdnsexception.hh" +#include "logger.hh" +#include "misc.hh" +#include +#include +#include + + +#if defined(_AIX) || defined(__APPLE__) + +// Darwin 6.0 Compatible implementation, uses pthreads so it portable across more platforms. + +#define SEM_VALUE_MAX 32767 +#define SEM_MAGIC ((uint32_t) 0x09fa4012) + +Semaphore::Semaphore(unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + throw PDNSException("Cannot create semaphore: value too large"); + } + + // Initialize + + if (pthread_mutex_init(&m_lock, NULL) != 0) { + throw PDNSException("Cannot create semaphore: cannot allocate mutex"); + } + + if (pthread_cond_init(&m_gtzero, NULL) != 0) { + pthread_mutex_destroy(&m_lock); + throw PDNSException("Cannot create semaphore: cannot allocate condition"); + } + + m_count = (uint32_t) value; + m_nwaiters = 0; + m_magic = SEM_MAGIC; +} + +int Semaphore::post() +{ + pthread_mutex_lock(&m_lock); + + m_count++; + if (m_nwaiters > 0) { + pthread_cond_signal(&m_gtzero); + } + + pthread_mutex_unlock(&m_lock); + + return 0; +} + +int Semaphore::wait() +{ + pthread_mutex_lock(&m_lock); + + while (m_count == 0) { + m_nwaiters++; + pthread_cond_wait(&m_gtzero, &m_lock); + m_nwaiters--; + } + + m_count--; + + pthread_mutex_unlock(&m_lock); + + return 0; +} + +int Semaphore::tryWait() +{ + int retval = 0; + + pthread_mutex_lock(&m_lock); + + if (m_count > 0) { + m_count--; + } else { + errno = EAGAIN; + retval = -1; + } + + pthread_mutex_unlock(&m_lock); + + return retval; +} + +int Semaphore::getValue(Semaphore::sem_value_t *sval) +{ + pthread_mutex_lock(&m_lock); + *sval = m_count; + pthread_mutex_unlock(&m_lock); + + return 0; +} + +Semaphore::~Semaphore() +{ + // Make sure there are no waiters. + + pthread_mutex_lock(&m_lock); + if (m_nwaiters > 0) { + pthread_mutex_unlock(&m_lock); + //errno = EBUSY; + //return -1; + } + pthread_mutex_unlock(&m_lock); + + // Destroy it. + + pthread_mutex_destroy(&m_lock); + pthread_cond_destroy(&m_gtzero); + m_magic = 0; + + //return 0; +} + +#else /* not DARWIN from here on */ + + +Semaphore::Semaphore(unsigned int value) +{ + m_pSemaphore=new sem_t; + if (sem_init(m_pSemaphore, 0, value) == -1) { + g_log << Logger::Error << "Cannot create semaphore: " << stringerror() << endl; + exit(1); + } +} + +int Semaphore::post() +{ + return sem_post(m_pSemaphore); +} + +int Semaphore::wait() +{ + int ret; + do + ret = sem_wait(m_pSemaphore); + while (ret == -1 && errno == EINTR); + return ret; +} +int Semaphore::tryWait() +{ + return sem_trywait(m_pSemaphore); +} + +int Semaphore::getValue(Semaphore::sem_value_t *sval) +{ + return sem_getvalue(m_pSemaphore, sval); +} + +Semaphore::~Semaphore() +{ + delete m_pSemaphore; +} + +#endif diff --git a/pdns/unix_utility.cc b/pdns/unix_utility.cc new file mode 100644 index 0000000..6e5d817 --- /dev/null +++ b/pdns/unix_utility.cc @@ -0,0 +1,300 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include +#include +#include +#include +#include "pdnsexception.hh" +#include "logger.hh" +#include "misc.hh" +#include +#include +#include +#include + +#ifdef NEED_INET_NTOP_PROTO +extern "C" { +const char *inet_ntop(int af, const void *src, char *dst, size_t cnt); +} +#endif + + +#include "namespaces.hh" + + +// Connects to socket with timeout +int Utility::timed_connect( Utility::sock_t sock, + const sockaddr *addr, + Utility::socklen_t sockaddr_size, + int timeout_sec, + int timeout_usec ) +{ + fd_set set; + struct timeval timeout; + int ret; + + timeout.tv_sec = timeout_sec; + timeout.tv_usec = timeout_usec; + + FD_ZERO(&set); + FD_SET(sock, &set); + + setNonBlocking(sock); + + if ((ret = connect (sock, addr, sockaddr_size)) < 0) { + if (errno != EINPROGRESS) + return ret; + } + + ret = select(sock + 1, NULL, &set, NULL, &timeout); + setBlocking(sock); + + return ret; +} + + + +void Utility::setBindAny(int af, sock_t sock) +{ + const int one = 1; + + (void) one; // avoids 'unused var' warning on systems that have none of the defines checked below +#ifdef IP_FREEBIND + if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0) + g_log<pw_name, gid)<0) { + g_log<gr_gid; + } + return newgid; +} + + +// Retrieves an uid using a username. +int Utility::makeUidNumeric(const string &username) +{ + int newuid; + if(!(newuid=atoi(username.c_str()))) { + struct passwd *pw=getpwnam(username.c_str()); + if(!pw) { + g_log<pw_uid; + } + return newuid; +} + +// Sets the random seed. +void Utility::srandom(void) +{ + struct timeval tv; + gettimeofday(&tv, 0); + ::srandom(tv.tv_sec ^ tv.tv_usec ^ getpid()); +} + +// Writes a vector. +int Utility::writev(int socket, const iovec *vector, size_t count ) +{ + return ::writev(socket,vector,count); +} + +/* this is cut and pasted from dietlibc, gratefully copied! */ +static int isleap(int year) { + /* every fourth year is a leap year except for century years that are + * not divisible by 400. */ + return (!(year%4) && ((year%100) || !(year%400))); +} + +time_t Utility::timegm(struct tm *const t) +{ + const static short spm[13] = /* days per month -- nonleap! */ + { 0, + (31), + (31+28), + (31+28+31), + (31+28+31+30), + (31+28+31+30+31), + (31+28+31+30+31+30), + (31+28+31+30+31+30+31), + (31+28+31+30+31+30+31+31), + (31+28+31+30+31+30+31+31+30), + (31+28+31+30+31+30+31+31+30+31), + (31+28+31+30+31+30+31+31+30+31+30), + (31+28+31+30+31+30+31+31+30+31+30+31), + }; + + time_t day; + time_t i; + time_t years = t->tm_year - 70; + + if (t->tm_sec>60) { t->tm_min += t->tm_sec/60; t->tm_sec%=60; } + if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; } + if (t->tm_hour>60) { t->tm_mday += t->tm_hour/60; t->tm_hour%=60; } + if (t->tm_mon>11) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; } + + while (t->tm_mday>spm[1+t->tm_mon]) { + if (t->tm_mon==1 && isleap(t->tm_year+1900)) { + if (t->tm_mon==31+29) break; + --t->tm_mday; + } + t->tm_mday-=spm[t->tm_mon]; + ++t->tm_mon; + if (t->tm_mon>11) { t->tm_mon=0; ++t->tm_year; } + } + + if (t->tm_year < 70) + return (time_t) -1; + /* Days since 1970 is 365 * number of years + number of leap years since 1970 */ + day = years * 365 + (years + 1) / 4; + + /* After 2100 we have to subtract 3 leap years for every 400 years + This is not intuitive. Most mktime implementations do not support + dates after 2059, anyway, so we might leave this out for its + bloat. */ + if ((years -= 131) >= 0) { + years /= 100; + day -= (years >> 2) * 3 + 1; + if ((years &= 3) == 3) years--; + day -= years; + } + + day += t->tm_yday = spm [t->tm_mon] + t->tm_mday-1 + ( isleap (t->tm_year+1900) & (t->tm_mon > 1) ); + + /* day is now the number of days since 'Jan 1 1970' */ + i = 7; + t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */ + + i = 24; + day *= i; + i = 60; + return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec; +} + diff --git a/pdns/utility.hh b/pdns/utility.hh new file mode 100644 index 0000000..024fc08 --- /dev/null +++ b/pdns/utility.hh @@ -0,0 +1,155 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +// Utility class specification. + +#ifndef UTILITY_HH +#define UTILITY_HH + +#ifdef NEED_POSIX_TYPEDEF +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "namespaces.hh" + +//! A semaphore class. +class Semaphore +{ +private: + typedef int sem_value_t; + +#if defined(_AIX) || defined(__APPLE__) + uint32_t m_magic; + pthread_mutex_t m_lock; + pthread_cond_t m_gtzero; + sem_value_t m_count; + uint32_t m_nwaiters; +#else + sem_t *m_pSemaphore; +#endif + +protected: +public: + Semaphore(const Semaphore&) = delete; + void operator=(const Semaphore&) = delete; + //! Default constructor. + Semaphore( unsigned int value = 0 ); + + //! Destructor. + ~Semaphore( void ); + + //! Posts to a semaphore. + int post( void ); + + //! Waits for a semaphore. + int wait( void ); + + //! Tries to wait for a semaphore. + int tryWait( void ); + + //! Retrieves the semaphore value. + int getValue( Semaphore::sem_value_t *sval ); +}; + +//! This is a utility class used for platform independent abstraction. +class Utility +{ +public: + typedef ::iovec iovec; + typedef ::pid_t pid_t; + typedef int sock_t; + typedef ::socklen_t socklen_t; + + //! Connect with timeout + // Returns: + // > 0 on success + // -1 on error + // 0 on timeout + static int timed_connect(sock_t sock, + const sockaddr *addr, + socklen_t sockaddr_size, + int timeout_sec, + int timeout_usec); + + //! Returns the process id of the current process. + static pid_t getpid( void ); + + //! Gets the current time. + static int gettimeofday( struct timeval *tv, void *tz = NULL ); + + //! Converts an address from dot and numbers format to binary data. + static int inet_aton( const char *cp, struct in_addr *inp ); + + //! Converts an address from presentation format to network format. + static int inet_pton( int af, const char *src, void *dst ); + + //! The inet_ntop() function converts an address from network format (usually a struct in_addr or some other binary form, in network byte order) to presentation format. + static const char *inet_ntop( int af, const char *src, char *dst, size_t size ); + + //! Retrieves a gid using a groupname. + static int makeGidNumeric( const string & group ); + + //! Retrieves an uid using an username. + static int makeUidNumeric( const string & username ); + + //! Writes a vector. + static int writev( Utility::sock_t socket, const iovec *vector, size_t count ); + + //! Sets the random seed. + static void srandom(void); + + //! Drops the program's group privileges. + static void dropGroupPrivs( int uid, int gid ); + + //! Drops the program's user privileges. + static void dropUserPrivs( int uid ); + + //! Sets the socket into Bind-any mode + static void setBindAny ( int af, Utility::sock_t socket ); + + //! Sleeps for a number of seconds. + static unsigned int sleep( unsigned int seconds ); + + //! Sleeps for a number of microseconds. + static void usleep( unsigned long usec ); + + static time_t timegm(struct tm *tm); + +}; + + +#endif // UTILITY_HH diff --git a/pdns/uuid-utils.cc b/pdns/uuid-utils.cc new file mode 100644 index 0000000..12340ae --- /dev/null +++ b/pdns/uuid-utils.cc @@ -0,0 +1,47 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "uuid-utils.hh" + +// see https://github.com/boostorg/random/issues/49 +#if BOOST_VERSION == 106900 +#ifndef BOOST_PENDING_INTEGER_LOG2_HPP +#define BOOST_PENDING_INTEGER_LOG2_HPP +#include +#endif /* BOOST_PENDING_INTEGER_LOG2_HPP */ +#endif /* BOOST_VERSION */ + +#include + +thread_local boost::uuids::random_generator t_uuidGenerator; + +boost::uuids::uuid getUniqueID() +{ + return t_uuidGenerator(); +} + +boost::uuids::uuid getUniqueID(const std::string& str) +{ + boost::uuids::string_generator gen; + return gen(str); +} + diff --git a/pdns/uuid-utils.hh b/pdns/uuid-utils.hh new file mode 100644 index 0000000..3aa7844 --- /dev/null +++ b/pdns/uuid-utils.hh @@ -0,0 +1,28 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include + +boost::uuids::uuid getUniqueID(); +boost::uuids::uuid getUniqueID(const std::string& str); diff --git a/pdns/validate.cc b/pdns/validate.cc new file mode 100644 index 0000000..ab7fa3d --- /dev/null +++ b/pdns/validate.cc @@ -0,0 +1,1102 @@ +#include "validate.hh" +#include "misc.hh" +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include "rec-lua-conf.hh" +#include "base32.hh" +#include "logger.hh" +bool g_dnssecLOG{false}; +time_t g_signatureInceptionSkew{0}; +uint16_t g_maxNSEC3Iterations{0}; + +#define LOG(x) if(g_dnssecLOG) { g_log < > getByTag(const skeyset_t& keys, uint16_t tag, uint8_t algorithm) +{ + vector> ret; + for(const auto& key : keys) + if(key->d_protocol == 3 && key->getTag() == tag && key->d_algorithm == algorithm) + ret.push_back(key); + return ret; +} + +static bool isCoveredByNSEC3Hash(const std::string& h, const std::string& beginHash, const std::string& nextHash) +{ + return ((beginHash < h && h < nextHash) || // no wrap BEGINNING --- HASH -- END + (nextHash > h && beginHash > nextHash) || // wrap HASH --- END --- BEGINNING + (nextHash < beginHash && beginHash < h) || // wrap other case END --- BEGINNING --- HASH + (beginHash == nextHash && h != beginHash)); // "we have only 1 NSEC3 record, LOL!" +} + +static bool isCoveredByNSEC(const DNSName& name, const DNSName& begin, const DNSName& next) +{ + return ((begin.canonCompare(name) && name.canonCompare(next)) || // no wrap BEGINNING --- NAME --- NEXT + (name.canonCompare(next) && next.canonCompare(begin)) || // wrap NAME --- NEXT --- BEGINNING + (next.canonCompare(begin) && begin.canonCompare(name)) || // wrap other case NEXT --- BEGINNING --- NAME + (begin == next && name != begin)); // "we have only 1 NSEC record, LOL!" +} + +static bool nsecProvesENT(const DNSName& name, const DNSName& begin, const DNSName& next) +{ + /* if name is an ENT: + - begin < name + - next is a child of name + */ + return begin.canonCompare(name) && next != name && next.isPartOf(name); +} + +static std::string getHashFromNSEC3(const DNSName& qname, const std::shared_ptr& nsec3) +{ + std::string result; + + if (g_maxNSEC3Iterations && nsec3->d_iterations > g_maxNSEC3Iterations) { + return result; + } + + return hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname); +} + +/* There is no delegation at this exact point if: + - the name exists but the NS type is not set + - the name does not exist + One exception, if the name is covered by an opt-out NSEC3 + it doesn't prove that an insecure delegation doesn't exist. +*/ +bool denialProvesNoDelegation(const DNSName& zone, const std::vector& dsrecords) +{ + for (const auto& record : dsrecords) { + if (record.d_type == QType::NSEC) { + const auto nsec = getRR(record); + if (!nsec) { + continue; + } + + if (record.d_name == zone) { + return !nsec->isSet(QType::NS); + } + + if (isCoveredByNSEC(zone, record.d_name, nsec->d_next)) { + return true; + } + } + else if (record.d_type == QType::NSEC3) { + const auto nsec3 = getRR(record); + if (!nsec3) { + continue; + } + + const string h = getHashFromNSEC3(zone, nsec3); + if (h.empty()) { + return false; + } + + const string beginHash = fromBase32Hex(record.d_name.getRawLabels()[0]); + if (beginHash == h) { + return !nsec3->isSet(QType::NS); + } + + if (isCoveredByNSEC3Hash(h, beginHash, nsec3->d_nexthash)) { + return !(nsec3->d_flags & 1); + } + } + } + + return false; +} + +/* RFC 4035 section-5.3.4: + "If the number of labels in an RRset's owner name is greater than the + Labels field of the covering RRSIG RR, then the RRset and its + covering RRSIG RR were created as a result of wildcard expansion." +*/ +bool isWildcardExpanded(unsigned int labelCount, const std::shared_ptr& sign) +{ + if (sign && sign->d_labels < labelCount) { + return true; + } + + return false; +} + +static bool isWildcardExpanded(const DNSName& owner, const std::vector >& signatures) +{ + if (signatures.empty()) { + return false; + } + + const auto& sign = signatures.at(0); + unsigned int labelsCount = owner.countLabels(); + return isWildcardExpanded(labelsCount, sign); +} + +bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const std::shared_ptr& sign) +{ + if (owner.isWildcard() && (labelCount - 1) == sign->d_labels) { + /* this is a wildcard alright, but it has not been expanded */ + return true; + } + return false; +} + +static bool isWildcardExpandedOntoItself(const DNSName& owner, const std::vector >& signatures) +{ + if (signatures.empty()) { + return false; + } + + const auto& sign = signatures.at(0); + unsigned int labelsCount = owner.countLabels(); + return isWildcardExpandedOntoItself(owner, labelsCount, sign); +} + +/* if this is a wildcard NSEC, the owner name has been modified + to match the name. Make sure we use the original '*' form. */ +static DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector >& signatures) +{ + DNSName result = initialOwner; + + if (signatures.empty()) { + return result; + } + + const auto& sign = signatures.at(0); + unsigned int labelsCount = initialOwner.countLabels(); + if (sign && sign->d_labels < labelsCount) { + do { + result.chopOff(); + labelsCount--; + } + while (sign->d_labels < labelsCount); + + result = g_wildcarddnsname + result; + } + + return result; +} + +static bool isNSECAncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr& nsec) +{ + return nsec->isSet(QType::NS) && + !nsec->isSet(QType::SOA) && + signer.countLabels() < owner.countLabels(); +} + +static bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr& nsec3) +{ + return nsec3->isSet(QType::NS) && + !nsec3->isSet(QType::SOA) && + signer.countLabels() < owner.countLabels(); +} + +static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, const cspmap_t& validrrsets) +{ + LOG("Trying to prove that there is no data in wildcard for "<getZoneRepresentation()<(r); + if (!nsec) { + continue; + } + + if (!v.first.first.isWildcard()) { + continue; + } + DNSName wildcard = getNSECOwnerName(v.first.first, v.second.signatures); + if (qname.countLabels() < wildcard.countLabels()) { + continue; + } + + wildcard.chopOff(); + + if (qname.isPartOf(wildcard)) { + LOG("\tWildcard matches"); + if (qtype == 0 || !nsec->isSet(qtype)) { + LOG(" and proves that the type did not exist"<getZoneRepresentation()<(r); + if (!nsec) { + continue; + } + + const DNSName owner = getNSECOwnerName(v.first.first, v.second.signatures); + /* + A NSEC can only prove the non-existence of a wildcard with at least the same + number of labels than the intersection of its owner name and next name. + */ + const DNSName commonLabels = owner.getCommonLabels(nsec->d_next); + unsigned int commonLabelsCount = commonLabels.countLabels(); + + DNSName wildcard(qname); + unsigned int wildcardLabelsCount = wildcard.countLabels(); + while (wildcard.chopOff() && wildcardLabelsCount >= commonLabelsCount) { + DNSName target = g_wildcarddnsname + wildcard; + + LOG("Comparing owner: "<d_next)) { + LOG("\tWildcard is covered"<getZoneRepresentation()<(r); + if (!nsec3) { + continue; + } + + const DNSName signer = getSigner(v.second.signatures); + if (!v.first.first.isPartOf(signer)) + continue; + + string h = getHashFromNSEC3(wildcard, nsec3); + if (h.empty()) { + return false; + } + LOG("\tWildcard hash: "< "<d_nexthash)<isSet(qtype)) { + LOG(" and proves that the type did not exist"<d_nexthash)) { + LOG("\tWildcard hash is covered"<getZoneRepresentation()<(r); + if(!nsec) + continue; + + const DNSName signer = getSigner(v.second.signatures); + if (!v.first.first.isPartOf(signer)) + continue; + + const DNSName owner = getNSECOwnerName(v.first.first, v.second.signatures); + /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs": + Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume + nonexistence of any RRs below that zone cut, which include all RRs at + that (original) owner name other than DS RRs, and all RRs below that + owner name regardless of type. + */ + if (qtype != QType::DS && (qname == owner || qname.isPartOf(owner)) && isNSECAncestorDelegation(signer, owner, nsec)) { + LOG("type is "<isSet(QType::NS))<<", SOA is "<isSet(QType::SOA))<<", signer is "<isSet(qtype)) { + LOG("Does _not_ deny existence of type "<isSet(QType::CNAME)) { + LOG("However a CNAME exists"<isSet(QType::NS)) { + LOG("However, no NS record exists at this level!"<d_next)) { + LOG(qname<<" is covered "); + /* if the name is an ENT and we received a NODATA answer, + we are fine with a NSEC proving that the name does not exist. */ + if (wantsNoDataProof && nsecProvesENT(qname, owner, nsec->d_next)) { + LOG("Denies existence of type "<isSet(qtype)<<", next: "<d_next<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + const DNSName signer = getSigner(v.second.signatures); + if (!v.first.first.isPartOf(signer)) { + LOG("Owner "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<isSet(QType::NS))<<", SOA is "<isSet(QType::SOA))<<", signer is "<isSet(qtype)) { + LOG("Does _not_ deny existence of type "<isSet(QType::CNAME)) { + LOG("However a CNAME exists"<isSet(QType::NS)) { + LOG("However, no NS record exists at this level!"<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + const DNSName signer = getSigner(v.second.signatures); + if (!v.first.first.isPartOf(signer)) { + LOG("Owner "< 0 && closestEncloserLabelsCount > wildcardLabelsCount) { + closestEncloser.chopOff(); + closestEncloserLabelsCount--; + } + } + + bool nextCloserFound = false; + bool isOptOut = false; + + if (found == true) { + /* now that we have found the closest (provable) encloser, + we can construct the next closer (FRC7129 section-5.5) name + and look for a NSEC3 RR covering it */ + unsigned int labelIdx = qname.countLabels() - closestEncloser.countLabels(); + if (labelIdx >= 1) { + DNSName nextCloser(closestEncloser); + nextCloser.prependRawLabel(qname.getRawLabel(labelIdx - 1)); + LOG("Looking for a NSEC3 covering the next closer name "<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + string h = getHashFromNSEC3(nextCloser, nsec3); + if (h.empty()) { + return INSECURE; + } + + string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]); + + LOG("Comparing "< "<d_nexthash)<d_nexthash)) { + LOG("Denies existence of name "<d_flags & 1) { + LOG(" but is opt-out!"); + isOptOut = true; + } + LOG(endl); + break; + } + LOG("Did not cover us ("< getZoneCuts(const DNSName& begin, const DNSName& end, DNSRecordOracle& dro) +{ + vector ret; + if(!begin.isPartOf(end)) + throw PDNSException(end.toLogString() + "is not part of " + begin.toLogString()); + + DNSName qname(end); + vector labelsToAdd = begin.makeRelative(end).getRawLabels(); + + // The shortest name is assumed to a zone cut + ret.push_back(qname); + while(qname != begin) { + bool foundCut = false; + if (labelsToAdd.empty()) + break; + + qname.prependRawLabel(labelsToAdd.back()); + labelsToAdd.pop_back(); + auto records = dro.get(qname, (uint16_t)QType::NS); + for (const auto record : records) { + if(record.d_type != QType::NS || record.d_name != qname) + continue; + foundCut = true; + break; + } + if (foundCut) + ret.push_back(qname); + } + return ret; +} + +bool isRRSIGNotExpired(const time_t now, const shared_ptr sig) +{ + return sig->d_siginception - g_signatureInceptionSkew <= now && sig->d_sigexpire >= now; +} + +static bool checkSignatureWithKey(time_t now, const shared_ptr sig, const shared_ptr key, const std::string& msg) +{ + bool result = false; + try { + /* rfc4035: + - The validator's notion of the current time MUST be less than or equal to the time listed in the RRSIG RR's Expiration field. + - The validator's notion of the current time MUST be greater than or equal to the time listed in the RRSIG RR's Inception field. + */ + if(isRRSIGNotExpired(now, sig)) { + std::shared_ptr dke = shared_ptr(DNSCryptoKeyEngine::makeFromPublicKeyString(key->d_algorithm, key->d_key)); + result = dke->verify(msg, sig->d_signature); + LOG("signature by key with tag "<d_tag<<" and algorithm "<d_algorithm)<<" was " << (result ? "" : "NOT ")<<"valid"<d_siginception - g_signatureInceptionSkew > now) ? "not yet valid" : "expired")<<" (inception: "<d_siginception<<", inception skew: "<d_sigexpire<<", now: "< >& records, const vector >& signatures, const skeyset_t& keys, bool validateAllSigs) +{ + bool isValid = false; + + for(const auto& signature : signatures) { + unsigned int labelCount = name.countLabels(); + if (signature->d_labels > labelCount) { + LOG(name<<": Discarding invalid RRSIG whose label count is "<d_labels<<" while the RRset owner name has only "< > toSign = records; + + auto r = getByTag(keys, signature->d_tag, signature->d_algorithm); + + if(r.empty()) { + LOG("No key provided for "<d_tag<<" and algorithm "<d_algorithm)<d_type)<first.first<<"/"<<)<getTag()<<" -> "<getZoneRepresentation()<first.first)<<"/"<first.second)<<" with "<second.signatures.size()<<" sigs"<first.first, i->second.records, i->second.signatures, keys, true)) { + validated[i->first] = i->second; + } + } +} + +// returns vState +// should return vState, zone cut and validated keyset +// i.e. www.7bits.nl -> insecure/7bits.nl/[] +// www.powerdnssec.org -> secure/powerdnssec.org/[keys] +// www.dnssec-failed.org -> bogus/dnssec-failed.org/[] + +cspmap_t harvestCSPFromRecs(const vector& recs) +{ + cspmap_t cspmap; + for(const auto& rec : recs) { + // cerr<<"res "<(rec); + if (rrc) { + cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc); + } + } + else { + cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content); + } + } + return cspmap; +} + +bool getTrustAnchor(const map& anchors, const DNSName& zone, dsmap_t &res) +{ + const auto& it = anchors.find(zone); + + if (it == anchors.cend()) { + return false; + } + + res = it->second; + return true; +} + +bool haveNegativeTrustAnchor(const map& negAnchors, const DNSName& zone, std::string& reason) +{ + const auto& it = negAnchors.find(zone); + + if (it == negAnchors.cend()) { + return false; + } + + reason = it->second; + return true; +} + +void validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, vector >& toSign, const vector >& sigs, skeyset_t& validkeys) +{ + /* + * Check all DNSKEY records against all DS records and place all DNSKEY records + * that have DS records (that we support the algo for) in the tentative key storage + */ + for(auto const& dsrc : dsmap) + { + auto r = getByTag(tkeys, dsrc.d_tag, dsrc.d_algorithm); + // cerr<<"looking at DS with tag "<d_tag<<" matching "<d_tag).size()<<" keys of which "<d_tag).size()<<" valid"<d_tag, sig->d_algorithm); + + if (bytag.empty()) { + continue; + } + + string msg = getMessageForRRSET(zone, *sig, toSign); + for(const auto& key : bytag) { + // cerr<<"validating : "; + bool signIsValid = checkSignatureWithKey(now, sig, key, msg); + + if(signIsValid) + { + LOG("validation succeeded - whole DNSKEY set is valid"<dsAnchors; + if (anchors.empty()) // Nothing to do here + return Insecure; + + // Determine the lowest (i.e. with the most labels) Trust Anchor for zone + DNSName lowestTA("."); + for (auto const &anchor : anchors) + if (zone.isPartOf(anchor.first) && lowestTA.countLabels() < anchor.first.countLabels()) + lowestTA = anchor.first; + + // Before searching for the keys, see if we have a Negative Trust Anchor. If + // so, test if the NTA is valid and return an NTA state + const auto negAnchors = luaLocal->negAnchors; + + if (!negAnchors.empty()) { + DNSName lowestNTA; + + for (auto const &negAnchor : negAnchors) + if (zone.isPartOf(negAnchor.first) && lowestNTA.countLabels() <= negAnchor.first.countLabels()) + lowestNTA = negAnchor.first; + + if(!lowestNTA.empty()) { + LOG("Found a Negative Trust Anchor for "< "< > sigs; + vector > toSign; + + skeyset_t tkeys; // tentative keys + validkeys.clear(); + + // cerr<<"got DS for ["< (rec); + if(rrc) { + LOG("Got signature: "<getZoneRepresentation()<<" with tag "<d_tag<<", for type "<d_type)<d_type != QType::DNSKEY) + continue; + sigs.push_back(rrc); + } + } + else if(rec.d_type == QType::DNSKEY) + { + auto drc=getRR (rec); + if(drc) { + tkeys.insert(drc); + LOG("Inserting key with tag "<getTag()<<" and algorithm "<d_algorithm)<<": "<getZoneRepresentation()<second.records.cbegin(); j!=cspiter->second.records.cend(); j++) + { + const auto dsrc=std::dynamic_pointer_cast(*j); + if(dsrc) { + dsmap.insert(*dsrc); + } + } + } + } + // There were no zone cuts (aka, we should never get here) + return Bogus; +} + +bool isSupportedDS(const DSRecordContent& ds) +{ + if (!DNSCryptoKeyEngine::isAlgorithmSupported(ds.d_algorithm)) { + LOG("Discarding DS "< >& signatures) +{ + for (const auto sig : signatures) { + if (sig) { + return sig->d_signer; + } + } + + return DNSName(); +} diff --git a/pdns/validate.hh b/pdns/validate.hh new file mode 100644 index 0000000..b30fca1 --- /dev/null +++ b/pdns/validate.hh @@ -0,0 +1,81 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include "dnsparser.hh" +#include "dnsname.hh" +#include +#include "namespaces.hh" +#include "dnsrecords.hh" + +extern bool g_dnssecLOG; +extern time_t g_signatureInceptionSkew; +extern uint16_t g_maxNSEC3Iterations; + +// 4033 5 +enum vState { Indeterminate, Bogus, Insecure, Secure, NTA, TA }; +extern const char *vStates[]; + +// NSEC(3) results +enum dState { NODATA, NXDOMAIN, NXQTYPE, ENT, INSECURE, OPTOUT}; +extern const char *dStates[]; + +class DNSRecordOracle +{ +public: + virtual std::vector get(const DNSName& qname, uint16_t qtype)=0; +}; + + +struct ContentSigPair +{ + vector> records; + vector> signatures; + // ponder adding a validate method that accepts a key +}; +typedef map, ContentSigPair> cspmap_t; +typedef std::set dsmap_t; + +struct sharedDNSKeyRecordContentCompare +{ + bool operator() (const shared_ptr& a, const shared_ptr& b) const + { + return *a < *b; + } +}; + +typedef set, sharedDNSKeyRecordContentCompare > skeyset_t; + +bool validateWithKeySet(time_t now, const DNSName& name, const vector >& records, const vector >& signatures, const skeyset_t& keys, bool validateAllSigs=true); +void validateWithKeySet(const cspmap_t& rrsets, cspmap_t& validated, const skeyset_t& keys); +cspmap_t harvestCSPFromRecs(const vector& recs); +vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, skeyset_t& keyset); +bool getTrustAnchor(const map& anchors, const DNSName& zone, dsmap_t &res); +bool haveNegativeTrustAnchor(const map& negAnchors, const DNSName& zone, std::string& reason); +void validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, vector >& toSign, const vector >& sigs, skeyset_t& validkeys); +dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t qtype, bool referralToUnsigned, bool wantsNoDataProof, bool needsWildcardProof=true, unsigned int wildcardLabelsCount=0); +bool isSupportedDS(const DSRecordContent& ds); +DNSName getSigner(const std::vector >& signatures); +bool denialProvesNoDelegation(const DNSName& zone, const std::vector& dsrecords); +bool isRRSIGNotExpired(const time_t now, const shared_ptr sig); +bool isWildcardExpanded(unsigned int labelCount, const std::shared_ptr& sign); +bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const std::shared_ptr& sign); diff --git a/pdns/version.cc b/pdns/version.cc new file mode 100644 index 0000000..caef7d5 --- /dev/null +++ b/pdns/version.cc @@ -0,0 +1,175 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "logger.hh" +#include "version.hh" + +static ProductType productType; + +string compilerVersion() +{ +#if defined(__clang__) + return string("clang " __clang_version__ ); +#elif defined(__GNUC__) + return string("gcc " __VERSION__ ); +#else // add other compilers here + return string("Unknown compiler"); +#endif +} + +// Human-readable product name +string productName() { + switch (productType) { + case ProductAuthoritative: + return "PowerDNS Authoritative Server"; + case ProductRecursor: + return "PowerDNS Recursor"; + }; + return "Unknown"; +} + +string getPDNSVersion() +{ + return VERSION; +} + +// REST API product type +string productTypeApiType() { + switch (productType) { + case ProductAuthoritative: + return "authoritative"; + case ProductRecursor: + return "recursor"; + }; + return "unknown"; +} + +void showProductVersion() +{ + g_log< +#include "threadname.hh" +#include +#include "logger.hh" +#include +#include "dns.hh" +#include "base64.hh" +#include "json.hh" +#include "uuid-utils.hh" +#include + +json11::Json HttpRequest::json() +{ + string err; + if(this->body.empty()) { + g_log<body, err); + if (doc.is_null()) { + g_log<second).find("basic ") == 0) { + string cookie = header->second.substr(6); + + string plain; + B64Decode(cookie, plain); + + vector cparts; + stringtok(cparts, plain, ":"); + + // this gets rid of terminating zeros + auth_ok = (cparts.size()==2 && (0==strcmp(cparts[1].c_str(), expected_password.c_str()))); + } + return auth_ok; +} + +bool HttpRequest::compareHeader(const string &header_name, const string &expected_value) +{ + YaHTTP::strstr_map_t::iterator header = headers.find(header_name); + if (header == headers.end()) + return false; + + // this gets rid of terminating zeros + return (0==strcmp(header->second.c_str(), expected_value.c_str())); +} + + +void HttpResponse::setBody(const json11::Json& document) +{ + document.dump(this->body); +} + +void HttpResponse::setErrorResult(const std::string& message, const int status_) +{ + setBody(json11::Json::object { { "error", message } }); + this->status = status_; +} + +void HttpResponse::setSuccessResult(const std::string& message, const int status_) +{ + setBody(json11::Json::object { { "result", message } }); + this->status = status_; +} + +static void bareHandlerWrapper(WebServer::HandlerFunction handler, YaHTTP::Request* req, YaHTTP::Response* resp) +{ + // wrapper to convert from YaHTTP::* to our subclasses + handler(static_cast(req), static_cast(resp)); +} + +void WebServer::registerBareHandler(const string& url, HandlerFunction handler) +{ + YaHTTP::THandlerFunction f = boost::bind(&bareHandlerWrapper, handler, _1, _2); + YaHTTP::Router::Any(url, f); +} + +static bool optionsHandler(HttpRequest* req, HttpResponse* resp) { + if (req->method == "OPTIONS") { + resp->headers["access-control-allow-origin"] = "*"; + resp->headers["access-control-allow-headers"] = "Content-Type, X-API-Key"; + resp->headers["access-control-allow-methods"] = "GET, POST, PUT, PATCH, DELETE, OPTIONS"; + resp->headers["access-control-max-age"] = "3600"; + resp->status = 200; + resp->headers["content-type"]= "text/plain"; + resp->body = ""; + return true; + } + return false; +} + +void WebServer::apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp, bool allowPassword) { + if (optionsHandler(req, resp)) return; + + resp->headers["access-control-allow-origin"] = "*"; + + if (d_apikey.empty()) { + g_log<logprefix<<"HTTP API Request \"" << req->url.path << "\": Authentication failed, API Key missing in config" << endl; + throw HttpUnauthorizedException("X-API-Key"); + } + + bool auth_ok = req->compareHeader("x-api-key", d_apikey) || req->getvars["api-key"] == d_apikey; + + if (!auth_ok && allowPassword) { + if (!d_webserverPassword.empty()) { + auth_ok = req->compareAuthorization(d_webserverPassword); + } else { + auth_ok = true; + } + } + + if (!auth_ok) { + g_log<logprefix<<"HTTP Request \"" << req->url.path << "\": Authentication by API Key failed" << endl; + throw HttpUnauthorizedException("X-API-Key"); + } + + resp->headers["Content-Type"] = "application/json"; + + // security headers + resp->headers["X-Content-Type-Options"] = "nosniff"; + resp->headers["X-Frame-Options"] = "deny"; + resp->headers["X-Permitted-Cross-Domain-Policies"] = "none"; + resp->headers["X-XSS-Protection"] = "1; mode=block"; + resp->headers["Content-Security-Policy"] = "default-src 'self'; style-src 'self' 'unsafe-inline'"; + + req->getvars.erase("_"); // jQuery cache buster + + try { + resp->status = 200; + handler(req, resp); + } catch (ApiException &e) { + resp->setErrorResult(e.what(), 422); + return; + } catch (JsonException &e) { + resp->setErrorResult(e.what(), 422); + return; + } + + if (resp->status == 204) { + // No Content -> no Content-Type. + resp->headers.erase("Content-Type"); + } +} + +void WebServer::registerApiHandler(const string& url, HandlerFunction handler, bool allowPassword) { + HandlerFunction f = boost::bind(&WebServer::apiWrapper, this, handler, _1, _2, allowPassword); + registerBareHandler(url, f); +} + +void WebServer::webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) { + if (!d_webserverPassword.empty()) { + bool auth_ok = req->compareAuthorization(d_webserverPassword); + if (!auth_ok) { + g_log<logprefix<<"HTTP Request \"" << req->url.path << "\": Web Authentication failed" << endl; + throw HttpUnauthorizedException("Basic"); + } + } + + handler(req, resp); +} + +void WebServer::registerWebHandler(const string& url, HandlerFunction handler) { + HandlerFunction f = boost::bind(&WebServer::webWrapper, this, handler, _1, _2); + registerBareHandler(url, f); +} + +static void *WebServerConnectionThreadStart(const WebServer* webServer, std::shared_ptr client) { + setThreadName("pdns-r/webhndlr"); + webServer->serveConnection(client); + return nullptr; +} + +void WebServer::handleRequest(HttpRequest& req, HttpResponse& resp) const +{ + // set default headers + resp.headers["Content-Type"] = "text/html; charset=utf-8"; + + try { + if (!req.complete) { + g_log<second.find("application/json") != std::string::npos) { + req.accept_json = true; + } else if (header->second.find("text/html") != std::string::npos) { + req.accept_html = true; + } + } + + YaHTTP::THandlerFunction handler; + if (!YaHTTP::Router::Route(&req, handler)) { + g_log<

" + what + "

"; + } else if (req.accept_json) { + resp.headers["Content-Type"] = "application/json"; + if (resp.body.empty()) { + resp.setErrorResult(what, resp.status); + } + } else { + resp.headers["Content-Type"] = "text/plain; charset=utf-8"; + resp.body = what; + } + } + + // always set these headers + resp.headers["Server"] = "PowerDNS/" VERSION; + resp.headers["Connection"] = "close"; + + if (req.method == "HEAD") { + resp.body = ""; + } else { + resp.headers["Content-Length"] = std::to_string(resp.body.size()); + } +} + +void WebServer::logRequest(const HttpRequest& req, const ComboAddress& remote) const { + if (d_loglevel >= WebServer::LogLevel::Detailed) { + auto logprefix = req.logprefix; + g_log<= WebServer::LogLevel::Detailed) { + g_log< client) const { + const string logprefix = d_logprefix + to_string(getUniqueID()) + " "; + + HttpRequest req(logprefix); + HttpResponse resp; + resp.max_response_size=d_maxbodysize; + ComboAddress remote; + string reply; + + try { + YaHTTP::AsyncRequestLoader yarl; + yarl.initialize(&req); + req.max_request_size=d_maxbodysize; + int timeout = 5; + client->setNonBlocking(); + + try { + while(!req.complete) { + int bytes; + char buf[16000]; + bytes = client->readWithTimeout(buf, sizeof(buf), timeout); + if (bytes > 0) { + string data = string(buf, bytes); + req.complete = yarl.feed(data); + } else { + // read error OR EOF + break; + } + } + yarl.finalize(); + } catch (YaHTTP::ParseError &e) { + // request stays incomplete + g_log<= WebServer::LogLevel::None) { + client->getRemote(remote); + } + + logRequest(req, remote); + + WebServer::handleRequest(req, resp); + ostringstream ss; + resp.write(ss); + reply = ss.str(); + + logResponse(resp, remote, logprefix); + + client->writenWithTimeout(reply.c_str(), reply.size(), timeout); + } + catch(PDNSException &e) { + g_log<= WebServer::LogLevel::Normal) { + g_log<d_local.toStringWithPort()<accept(); + if (!client) { + continue; + } + if (client->acl(d_acl)) { + std::thread webHandler(WebServerConnectionThreadStart, this, client); + webHandler.detach(); + } else { + ComboAddress remote; + if (client->getRemote(remote)) + g_log< +#include +#include +#include +#include +#include "json11.hpp" +#include "namespaces.hh" +#include "sstuff.hh" + +class WebServer; + +class HttpRequest : public YaHTTP::Request { +public: + HttpRequest(const string& logprefix="") : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false), logprefix(logprefix) { }; + + bool accept_json; + bool accept_html; + bool complete; + string logprefix; + json11::Json json(); + + // checks password _only_. + bool compareAuthorization(const string &expected_password); + bool compareHeader(const string &header_name, const string &expected_value); +}; + +class HttpResponse: public YaHTTP::Response { +public: + HttpResponse() : YaHTTP::Response() { }; + HttpResponse(const YaHTTP::Response &resp) : YaHTTP::Response(resp) { }; + + void setBody(const json11::Json& document); + void setErrorResult(const std::string& message, const int status); + void setSuccessResult(const std::string& message, const int status = 200); +}; + + +class HttpException +{ +public: + HttpException(int status) : d_response() + { + d_response.status = status; + }; + + HttpException(int status, const string& msg) : d_response() + { + d_response.setErrorResult(msg, status); + }; + + HttpResponse response() + { + return d_response; + } + +protected: + HttpResponse d_response; +}; + +class HttpBadRequestException : public HttpException { +public: + HttpBadRequestException() : HttpException(400) { }; + HttpBadRequestException(const string& msg) : HttpException(400, msg) { }; +}; + +class HttpUnauthorizedException : public HttpException { +public: + HttpUnauthorizedException(string const &scheme) : HttpException(401) + { + d_response.headers["WWW-Authenticate"] = scheme + " realm=\"PowerDNS\""; + } +}; + +class HttpForbiddenException : public HttpException { +public: + HttpForbiddenException() : HttpException(403) { }; + HttpForbiddenException(const string& msg) : HttpException(403, msg) { }; +}; + +class HttpNotFoundException : public HttpException { +public: + HttpNotFoundException() : HttpException(404) { }; + HttpNotFoundException(const string& msg) : HttpException(404, msg) { }; +}; + +class HttpMethodNotAllowedException : public HttpException { +public: + HttpMethodNotAllowedException() : HttpException(405) { }; + HttpMethodNotAllowedException(const string& msg) : HttpException(405, msg) { }; +}; + +class HttpConflictException : public HttpException { +public: + HttpConflictException() : HttpException(409) { }; + HttpConflictException(const string& msg) : HttpException(409, msg) { }; +}; + +class HttpInternalServerErrorException : public HttpException { +public: + HttpInternalServerErrorException() : HttpException(500) { }; + HttpInternalServerErrorException(const string& msg) : HttpException(500, msg) { }; +}; + +class ApiException : public runtime_error +{ +public: + ApiException(const string& what) : runtime_error(what) { + } +}; + +class Server +{ +public: + Server(const string &localaddress, int port) : d_local(localaddress.empty() ? "0.0.0.0" : localaddress, port), d_server_socket(d_local.sin4.sin_family, SOCK_STREAM, 0) { + d_server_socket.setReuseAddr(); + d_server_socket.bind(d_local); + d_server_socket.listen(); + } + virtual ~Server() { }; + + ComboAddress d_local; + + std::shared_ptr accept() { + return std::shared_ptr(d_server_socket.accept()); + } + +protected: + Socket d_server_socket; +}; + +class WebServer : public boost::noncopyable +{ +public: + WebServer(const string &listenaddress, int port); + virtual ~WebServer() { }; + + void setApiKey(const string &apikey) { + d_apikey = apikey; + } + + void setPassword(const string &password) { + d_webserverPassword = password; + } + + void setMaxBodySize(ssize_t s) { // in megabytes + d_maxbodysize = s * 1024 * 1024; + } + + void setACL(const NetmaskGroup &nmg) { + d_acl = nmg; + } + + void bind(); + void go(); + + void serveConnection(std::shared_ptr client) const; + void handleRequest(HttpRequest& request, HttpResponse& resp) const; + + typedef boost::function HandlerFunction; + void registerApiHandler(const string& url, HandlerFunction handler, bool allowPassword=false); + void registerWebHandler(const string& url, HandlerFunction handler); + + enum class LogLevel : uint8_t { + None = 0, // No logs from requests at all + Normal = 10, // A "common log format"-like line e.g. '127.0.0.1 "GET /apache_pb.gif HTTP/1.0" 200 2326' + Detailed = 20, // The full request headers and body, and the full response headers and body + }; + + void setLogLevel(const string& level) { + if (level == "none") { + d_loglevel = LogLevel::None; + return; + } + + if (level == "normal") { + d_loglevel = LogLevel::Normal; + return; + } + + if (level == "detailed") { + d_loglevel = LogLevel::Detailed; + return; + } + + throw PDNSException("Unknown webserver log level: " + level); + } + + void setLogLevel(const LogLevel level) { + d_loglevel = level; + }; + + LogLevel getLogLevel() { + return d_loglevel; + }; + +protected: + void registerBareHandler(const string& url, HandlerFunction handler); + void logRequest(const HttpRequest& req, const ComboAddress& remote) const; + void logResponse(const HttpResponse& resp, const ComboAddress& remote, const string& logprefix) const; + + virtual std::shared_ptr createServer() { + return std::make_shared(d_listenaddress, d_port); + } + + string d_listenaddress; + int d_port; + string d_password; + std::shared_ptr d_server; + + std::string d_apikey; + void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp, bool allowPassword); + std::string d_webserverPassword; + void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp); + + ssize_t d_maxbodysize; // in bytes + + NetmaskGroup d_acl; + + const string d_logprefix = "[webserver] "; + + // Describes the amount of logging the webserver does + WebServer::LogLevel d_loglevel{WebServer::LogLevel::Detailed}; +}; + +#endif /* WEBSERVER_HH */ diff --git a/pdns/ws-api.cc b/pdns/ws-api.cc new file mode 100644 index 0000000..54dde00 --- /dev/null +++ b/pdns/ws-api.cc @@ -0,0 +1,372 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "namespaces.hh" +#include "ws-api.hh" +#include "json.hh" +#include "version.hh" +#include "arguments.hh" +#include "dnsparser.hh" +#include "responsestats.hh" +#ifndef RECURSOR +#include "statbag.hh" +#endif +#include +#include +#include +#include +#include + +using json11::Json; + +extern string s_programname; +extern ResponseStats g_rs; +#ifndef RECURSOR +extern StatBag S; +#endif + +#ifndef HAVE_STRCASESTR + +/* + * strcasestr() locates the first occurrence in the string s1 of the + * sequence of characters (excluding the terminating null character) + * in the string s2, ignoring case. strcasestr() returns a pointer + * to the located string, or a null pointer if the string is not found. + * If s2 is empty, the function returns s1. + */ + +static char * +strcasestr(const char *s1, const char *s2) +{ + int *cm = __trans_lower; + const uchar_t *us1 = (const uchar_t *)s1; + const uchar_t *us2 = (const uchar_t *)s2; + const uchar_t *tptr; + int c; + + if (us2 == NULL || *us2 == '\0') + return ((char *)us1); + + c = cm[*us2]; + while (*us1 != '\0') { + if (c == cm[*us1++]) { + tptr = us1; + while (cm[c = *++us2] == cm[*us1++] && c != '\0') + continue; + if (c == '\0') + return ((char *)tptr - 1); + us1 = tptr; + us2 = (const uchar_t *)s2; + c = cm[*us2]; + } + } + + return (NULL); +} + +#endif // HAVE_STRCASESTR + +static Json getServerDetail() { + return Json::object { + { "type", "Server" }, + { "id", "localhost" }, + { "url", "/api/v1/servers/localhost" }, + { "daemon_type", productTypeApiType() }, + { "version", getPDNSVersion() }, + { "config_url", "/api/v1/servers/localhost/config{/config_setting}" }, + { "zones_url", "/api/v1/servers/localhost/zones{/zone}" } + }; +} + +/* Return information about the supported API versions. + * The format of this MUST NEVER CHANGE at it's not versioned. + */ +void apiDiscovery(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + Json version1 = Json::object { + { "version", 1 }, + { "url", "/api/v1" } + }; + Json doc = Json::array { version1 }; + + resp->setBody(doc); +} + +void apiServer(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + Json doc = Json::array {getServerDetail()}; + resp->setBody(doc); +} + +void apiServerDetail(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + resp->setBody(getServerDetail()); +} + +void apiServerConfig(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + vector items = ::arg().list(); + string value; + Json::array doc; + for(const string& item : items) { + if(item.find("password") != string::npos || item.find("api-key") != string::npos) + value = "***"; + else + value = ::arg()[item]; + + doc.push_back(Json::object { + { "type", "ConfigSetting" }, + { "name", item }, + { "value", value }, + }); + } + resp->setBody(doc); +} + +void apiServerStatistics(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + Json::array doc; + string name = req->getvars["statistic"]; + if (!name.empty()) { + auto stat = productServerStatisticsFetch(name); + if (!stat) { + throw ApiException("Unknown statistic name"); + } + + doc.push_back(Json::object { + { "type", "StatisticItem" }, + { "name", name }, + { "value", std::to_string(*stat) }, + }); + + resp->setBody(doc); + + return; + } + + typedef map stat_items_t; + stat_items_t general_stats; + productServerStatisticsFetch(general_stats); + + for(const auto& item : general_stats) { + doc.push_back(Json::object { + { "type", "StatisticItem" }, + { "name", item.first }, + { "value", item.second }, + }); + } + + auto resp_qtype_stats = g_rs.getQTypeResponseCounts(); + auto resp_size_stats = g_rs.getSizeResponseCounts(); + auto resp_rcode_stats = g_rs.getRCodeResponseCounts(); + { + Json::array values; + for(const auto& item : resp_qtype_stats) { + if (item.second == 0) + continue; + values.push_back(Json::object { + { "name", DNSRecordContent::NumberToType(item.first) }, + { "value", std::to_string(item.second) }, + }); + } + + doc.push_back(Json::object { + { "type", "MapStatisticItem" }, + { "name", "response-by-qtype" }, + { "value", values }, + }); + } + + { + Json::array values; + for(const auto& item : resp_size_stats) { + if (item.second == 0) + continue; + + values.push_back(Json::object { + { "name", std::to_string(item.first) }, + { "value", std::to_string(item.second) }, + }); + } + + doc.push_back(Json::object { + { "type", "MapStatisticItem" }, + { "name", "response-sizes" }, + { "value", values }, + }); + } + + { + Json::array values; + for(const auto& item : resp_rcode_stats) { + if (item.second == 0) + continue; + values.push_back(Json::object { + { "name", RCode::to_s(item.first) }, + { "value", std::to_string(item.second) }, + }); + } + + doc.push_back(Json::object { + { "type", "MapStatisticItem" }, + { "name", "response-by-rcode" }, + { "value", values }, + }); + } + +#ifndef RECURSOR + for(const auto& ringName : S.listRings()) { + Json::array values; + const auto& ring = S.getRing(ringName); + for(const auto& item : ring) { + if (item.second == 0) + continue; + + values.push_back(Json::object { + { "name", item.first }, + { "value", std::to_string(item.second) }, + }); + } + + doc.push_back(Json::object { + { "type", "RingStatisticItem" }, + { "name", ringName }, + { "size", std::to_string(S.getRingSize(ringName)) }, + { "value", values }, + }); + } +#endif + + resp->setBody(doc); +} + +DNSName apiNameToDNSName(const string& name) { + if (!isCanonical(name)) { + throw ApiException("DNS Name '" + name + "' is not canonical"); + } + try { + return DNSName(name); + } catch (...) { + throw ApiException("Unable to parse DNS Name '" + name + "'"); + } +} + +DNSName apiZoneIdToName(const string& id) { + string zonename; + ostringstream ss; + + if(id.empty()) + throw HttpBadRequestException(); + + std::size_t lastpos = 0, pos = 0; + while ((pos = id.find('=', lastpos)) != string::npos) { + ss << id.substr(lastpos, pos-lastpos); + char c; + // decode tens + if (id[pos+1] >= '0' && id[pos+1] <= '9') { + c = id[pos+1] - '0'; + } else if (id[pos+1] >= 'A' && id[pos+1] <= 'F') { + c = id[pos+1] - 'A' + 10; + } else { + throw HttpBadRequestException(); + } + c = c * 16; + + // decode unit place + if (id[pos+2] >= '0' && id[pos+2] <= '9') { + c += id[pos+2] - '0'; + } else if (id[pos+2] >= 'A' && id[pos+2] <= 'F') { + c += id[pos+2] - 'A' + 10; + } else { + throw HttpBadRequestException(); + } + + ss << c; + + lastpos = pos+3; + } + if (lastpos < pos) { + ss << id.substr(lastpos, pos-lastpos); + } + + zonename = ss.str(); + + try { + return DNSName(zonename); + } catch (...) { + throw ApiException("Unable to parse DNS Name '" + zonename + "'"); + } +} + +string apiZoneNameToId(const DNSName& dname) { + string name=dname.toString(); + ostringstream ss; + + for(string::const_iterator iter = name.begin(); iter != name.end(); ++iter) { + if ((*iter >= 'A' && *iter <= 'Z') || + (*iter >= 'a' && *iter <= 'z') || + (*iter >= '0' && *iter <= '9') || + (*iter == '.') || (*iter == '-')) { + ss << *iter; + } else { + ss << (boost::format("=%02X") % (int)(*iter)); + } + } + + string id = ss.str(); + + // add trailing dot + if (id.size() == 0 || id.substr(id.size()-1) != ".") { + id += "."; + } + + // special handling for the root zone, as a dot on it's own doesn't work + // everywhere. + if (id == ".") { + id = (boost::format("=%02X") % (int)('.')).str(); + } + return id; +} + +void apiCheckNameAllowedCharacters(const string& name) { + if (name.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_/.-") != std::string::npos) + throw ApiException("Name '"+name+"' contains unsupported characters"); +} + +void apiCheckQNameAllowedCharacters(const string& qname) { + if (qname.compare(0, 2, "*.") == 0) apiCheckNameAllowedCharacters(qname.substr(2)); + else apiCheckNameAllowedCharacters(qname); +} diff --git a/pdns/ws-api.hh b/pdns/ws-api.hh new file mode 100644 index 0000000..e280a20 --- /dev/null +++ b/pdns/ws-api.hh @@ -0,0 +1,46 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef PDNS_WSAPI_HH +#define PDNS_WSAPI_HH + +#include +#include "webserver.hh" + +void apiDiscovery(HttpRequest* req, HttpResponse* resp); +void apiServer(HttpRequest* req, HttpResponse* resp); +void apiServerDetail(HttpRequest* req, HttpResponse* resp); +void apiServerConfig(HttpRequest* req, HttpResponse* resp); +void apiServerStatistics(HttpRequest* req, HttpResponse* resp); + +// helpers +DNSName apiZoneIdToName(const string& id); +string apiZoneNameToId(const DNSName& name); +void apiCheckNameAllowedCharacters(const string& name); +void apiCheckQNameAllowedCharacters(const string& name); +DNSName apiNameToDNSName(const string& name); + +// To be provided by product code. +void productServerStatisticsFetch(std::map& out); +boost::optional productServerStatisticsFetch(const std::string& name); + +#endif /* PDNS_WSAPI_HH */ diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc new file mode 100644 index 0000000..3fc8051 --- /dev/null +++ b/pdns/ws-auth.cc @@ -0,0 +1,2309 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "utility.hh" +#include "dynlistener.hh" +#include "ws-auth.hh" +#include "json.hh" +#include "webserver.hh" +#include "logger.hh" +#include "statbag.hh" +#include "misc.hh" +#include "base64.hh" +#include "arguments.hh" +#include "dns.hh" +#include "comment.hh" +#include "ueberbackend.hh" +#include + +#include "namespaces.hh" +#include "ws-api.hh" +#include "version.hh" +#include "dnsseckeeper.hh" +#include +#include "zoneparser-tng.hh" +#include "common_startup.hh" +#include "auth-caches.hh" +#include "threadname.hh" +#include "tsigutils.hh" + +using json11::Json; + +extern StatBag S; + +static void patchZone(UeberBackend& B, HttpRequest* req, HttpResponse* resp); +static void storeChangedPTRs(UeberBackend& B, vector& new_ptrs); +static void makePtr(const DNSResourceRecord& rr, DNSResourceRecord* ptr); + +// QTypes that MUST NOT have multiple records of the same type in a given RRset. +static const std::set onlyOneEntryTypes = { QType::CNAME, QType::DNAME, QType::SOA }; +// QTypes that MUST NOT be used with any other QType on the same name. +static const std::set exclusiveEntryTypes = { QType::CNAME, QType::DNAME }; + +AuthWebServer::AuthWebServer() : + d_tid(0), + d_start(time(nullptr)), + d_min10(0), + d_min5(0), + d_min1(0) +{ + if(arg().mustDo("webserver") || arg().mustDo("api")) { + d_ws = new WebServer(arg()["webserver-address"], arg().asNum("webserver-port")); + d_ws->setApiKey(arg()["api-key"]); + d_ws->setPassword(arg()["webserver-password"]); + d_ws->setLogLevel(arg()["webserver-loglevel"]); + + NetmaskGroup acl; + acl.toMasks(::arg()["webserver-allow-from"]); + d_ws->setACL(acl); + + d_ws->setMaxBodySize(::arg().asNum("webserver-max-bodysize")); + + d_ws->bind(); + } +} + +void AuthWebServer::go() +{ + S.doRings(); + pthread_create(&d_tid, 0, webThreadHelper, this); + pthread_create(&d_tid, 0, statThreadHelper, this); +} + +void AuthWebServer::statThread() +{ + try { + setThreadName("pdns/statHelper"); + for(;;) { + d_queries.submit(S.read("udp-queries")); + d_cachehits.submit(S.read("packetcache-hit")); + d_cachemisses.submit(S.read("packetcache-miss")); + d_qcachehits.submit(S.read("query-cache-hit")); + d_qcachemisses.submit(S.read("query-cache-miss")); + Utility::sleep(1); + } + } + catch(...) { + g_log<(p); + self->statThread(); + return 0; // never reached +} + +void *AuthWebServer::webThreadHelper(void *p) +{ + AuthWebServer *self=static_cast(p); + self->webThread(); + return 0; // never reached +} + +static string htmlescape(const string &s) { + string result; + for(string::const_iterator it=s.begin(); it!=s.end(); ++it) { + switch (*it) { + case '&': + result += "&"; + break; + case '<': + result += "<"; + break; + case '>': + result += ">"; + break; + case '"': + result += """; + break; + default: + result += *it; + } + } + return result; +} + +void printtable(ostringstream &ret, const string &ringname, const string &title, int limit=10) +{ + int tot=0; + int entries=0; + vector >ring=S.getRing(ringname); + + for(vector >::const_iterator i=ring.begin(); i!=ring.end();++i) { + tot+=i->second; + entries++; + } + + ret<<""; + + ret<<""; + int printed=0; + int total=max(1,tot); + for(vector >::const_iterator i=ring.begin();limit && i!=ring.end();++i,--limit) { + ret<<""<second; + } + ret<<""<"<"; + ret<<"
"<first)<<""<second<<""<< AuthWebServer::makePercentage(i->second*100.0/total)<<"
Rest:"<"<< AuthWebServer::makePercentage((tot-printed)*100.0/total)<<"Total:"<100%
"<

Variables

"<entries=S.getEntries(); + for(vector::const_iterator i=entries.begin();i!=entries.end();++i) { + ret<<""<entries=arg().list(); + for(vector::const_iterator i=entries.begin();i!=entries.end();++i) { + ret<<"
"<<*i<<""<"<"<"<
Arguments
"<<*i<<""<"<"<getvars["resetring"].empty()) { + if (S.ringExists(req->getvars["resetring"])) + S.resetRing(req->getvars["resetring"]); + resp->status = 302; + resp->headers["Location"] = req->url.path; + return; + } + if(!req->getvars["resizering"].empty()){ + int size=std::stoi(req->getvars["size"]); + if (S.ringExists(req->getvars["resizering"]) && size > 0 && size <= 500000) + S.resizeRing(req->getvars["resizering"], std::stoi(req->getvars["size"])); + resp->status = 302; + resp->headers["Location"] = req->url.path; + return; + } + + ostringstream ret; + + ret<<""<"<PowerDNS Authoritative Server Monitor"<"<"<"<"; + ret<<"PowerDNS "<"<"; + ret<<"
"; + + time_t passed=time(0)-s_starttime; + + ret<<"

Uptime: "<< + humanDuration(passed)<< + "
"<"<0) + ret<<"Cache hitrate, 1, 5, 10 minute averages: "<< + makePercentage((d_cachehits.get1()*100.0)/((d_cachehits.get1())+(d_cachemisses.get1())))<<", "<< + makePercentage((d_cachehits.get5()*100.0)/((d_cachehits.get5())+(d_cachemisses.get5())))<<", "<< + makePercentage((d_cachehits.get10()*100.0)/((d_cachehits.get10())+(d_cachemisses.get10())))<< + "
"<0) + ret<<"Backend query cache hitrate, 1, 5, 10 minute averages: "<"<"<
"<getvars["ring"].empty()) { + auto entries = S.listRings(); + for(const auto &i: entries) { + printtable(ret, i, S.getRingTitle(i)); + } + + printvars(ret); + if(arg().mustDo("webserver-print-arguments")) + printargs(ret); + } + else if(S.ringExists(req->getvars["ring"])) + printtable(ret,req->getvars["ring"],S.getRingTitle(req->getvars["ring"]),100); + + ret<<"

"<"<© 2013 - 2019
PowerDNS.COM BV."<"<body = ret.str(); + resp->status = 200; +} + +/** Helper to build a record content as needed. */ +static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot) { + // noDot: for backend storage, pass true. for API users, pass false. + auto drc = DNSRecordContent::mastermake(qtype.getCode(), QClass::IN, content); + return drc->getZoneRepresentation(noDot); +} + +/** "Normalize" record content for API consumers. */ +static inline string makeApiRecordContent(const QType& qtype, const string& content) { + return makeRecordContent(qtype, content, false); +} + +/** "Normalize" record content for backend storage. */ +static inline string makeBackendRecordContent(const QType& qtype, const string& content) { + return makeRecordContent(qtype, content, true); +} + +static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) { + string zoneId = apiZoneNameToId(di.zone); + vector masters; + for(const auto& m : di.masters) + masters.push_back(m.toStringWithPortExcept(53)); + + auto obj = Json::object { + // id is the canonical lookup key, which doesn't actually match the name (in some cases) + { "id", zoneId }, + { "url", "/api/v1/servers/localhost/zones/" + zoneId }, + { "name", di.zone.toString() }, + { "kind", di.getKindString() }, + { "account", di.account }, + { "masters", masters }, + { "serial", (double)di.serial }, + { "notified_serial", (double)di.notified_serial }, + { "last_check", (double)di.last_check } + }; + if (dk) { + obj["dnssec"] = dk->isSecuredZone(di.zone); + obj["edited_serial"] = (double)calculateEditSOA(di.serial, *dk, di.zone); + } + return obj; +} + +static bool shouldDoRRSets(HttpRequest* req) { + if (req->getvars.count("rrsets") == 0 || req->getvars["rrsets"] == "true") + return true; + if (req->getvars["rrsets"] == "false") + return false; + throw ApiException("'rrsets' request parameter value '"+req->getvars["rrsets"]+"' is not supported"); +} + +static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* resp, bool doRRSets) { + DomainInfo di; + if(!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + DNSSECKeeper dk(&B); + Json::object doc = getZoneInfo(di, &dk); + // extra stuff getZoneInfo doesn't do for us (more expensive) + string soa_edit_api; + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api); + doc["soa_edit_api"] = soa_edit_api; + string soa_edit; + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit); + doc["soa_edit"] = soa_edit; + string nsec3param; + di.backend->getDomainMetadataOne(zonename, "NSEC3PARAM", nsec3param); + doc["nsec3param"] = nsec3param; + string nsec3narrow; + bool nsec3narrowbool = false; + di.backend->getDomainMetadataOne(zonename, "NSEC3NARROW", nsec3narrow); + if (nsec3narrow == "1") + nsec3narrowbool = true; + doc["nsec3narrow"] = nsec3narrowbool; + doc["dnssec"] = dk.isSecuredZone(zonename); + + string api_rectify; + di.backend->getDomainMetadataOne(zonename, "API-RECTIFY", api_rectify); + doc["api_rectify"] = (api_rectify == "1"); + + // TSIG + vector tsig_master, tsig_slave; + di.backend->getDomainMetadata(zonename, "TSIG-ALLOW-AXFR", tsig_master); + di.backend->getDomainMetadata(zonename, "AXFR-MASTER-TSIG", tsig_slave); + + Json::array tsig_master_keys; + for (const auto& keyname : tsig_master) { + tsig_master_keys.push_back(apiZoneNameToId(DNSName(keyname))); + } + doc["master_tsig_key_ids"] = tsig_master_keys; + + Json::array tsig_slave_keys; + for (const auto& keyname : tsig_slave) { + tsig_slave_keys.push_back(apiZoneNameToId(DNSName(keyname))); + } + doc["slave_tsig_key_ids"] = tsig_slave_keys; + + if (doRRSets) { + vector records; + vector comments; + + // load all records + sort + { + DNSResourceRecord rr; + di.backend->list(zonename, di.id, true); // incl. disabled + while(di.backend->get(rr)) { + if (!rr.qtype.getCode()) + continue; // skip empty non-terminals + records.push_back(rr); + } + sort(records.begin(), records.end(), [](const DNSResourceRecord& a, const DNSResourceRecord& b) { + /* if you ever want to update this comparison function, + please be aware that you will also need to update the conditions in the code merging + the records and comments below */ + if (a.qname == b.qname) { + return b.qtype < a.qtype; + } + return b.qname < a.qname; + }); + } + + // load all comments + sort + { + Comment comment; + di.backend->listComments(di.id); + while(di.backend->getComment(comment)) { + comments.push_back(comment); + } + sort(comments.begin(), comments.end(), [](const Comment& a, const Comment& b) { + /* if you ever want to update this comparison function, + please be aware that you will also need to update the conditions in the code merging + the records and comments below */ + if (a.qname == b.qname) { + return b.qtype < a.qtype; + } + return b.qname < a.qname; + }); + } + + Json::array rrsets; + Json::object rrset; + Json::array rrset_records; + Json::array rrset_comments; + DNSName current_qname; + QType current_qtype; + uint32_t ttl; + auto rit = records.begin(); + auto cit = comments.begin(); + + while (rit != records.end() || cit != comments.end()) { + // if you think this should be rit < cit instead of cit < rit, note the b < a instead of a < b in the sort comparison functions above + if (cit == comments.end() || (rit != records.end() && (rit->qname == cit->qname ? (cit->qtype < rit->qtype || cit->qtype == rit->qtype) : cit->qname < rit->qname))) { + current_qname = rit->qname; + current_qtype = rit->qtype; + ttl = rit->ttl; + } else { + current_qname = cit->qname; + current_qtype = cit->qtype; + ttl = 0; + } + + while(rit != records.end() && rit->qname == current_qname && rit->qtype == current_qtype) { + ttl = min(ttl, rit->ttl); + rrset_records.push_back(Json::object { + { "disabled", rit->disabled }, + { "content", makeApiRecordContent(rit->qtype, rit->content) } + }); + rit++; + } + while (cit != comments.end() && cit->qname == current_qname && cit->qtype == current_qtype) { + rrset_comments.push_back(Json::object { + { "modified_at", (double)cit->modified_at }, + { "account", cit->account }, + { "content", cit->content } + }); + cit++; + } + + rrset["name"] = current_qname.toString(); + rrset["type"] = current_qtype.getName(); + rrset["records"] = rrset_records; + rrset["comments"] = rrset_comments; + rrset["ttl"] = (double)ttl; + rrsets.push_back(rrset); + rrset.clear(); + rrset_records.clear(); + rrset_comments.clear(); + } + + doc["rrsets"] = rrsets; + } + + resp->setBody(doc); +} + +void productServerStatisticsFetch(map& out) +{ + vector items = S.getEntries(); + for(const string& item : items) { + out[item] = std::to_string(S.read(item)); + } + + // add uptime + out["uptime"] = std::to_string(time(0) - s_starttime); +} + +boost::optional productServerStatisticsFetch(const std::string& name) +{ + try { + // ::read() calls ::exists() which throws a PDNSException when the key does not exist + return S.read(name); + } + catch(...) { + return boost::none; + } +} + +static void validateGatheredRRType(const DNSResourceRecord& rr) { + if (rr.qtype.getCode() == QType::OPT || rr.qtype.getCode() == QType::TSIG) { + throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.getName()+": invalid type given"); + } +} + +static void gatherRecords(UeberBackend& B, const string& logprefix, const Json container, const DNSName& qname, const QType qtype, const int ttl, vector& new_records, vector& new_ptrs) { + DNSResourceRecord rr; + rr.qname = qname; + rr.qtype = qtype; + rr.auth = 1; + rr.ttl = ttl; + + validateGatheredRRType(rr); + const auto& items = container["records"].array_items(); + for(const auto& record : items) { + string content = stringFromJson(record, "content"); + rr.disabled = boolFromJson(record, "disabled"); + + // validate that the client sent something we can actually parse, and require that data to be dotted. + try { + if (rr.qtype.getCode() != QType::AAAA) { + string tmp = makeApiRecordContent(rr.qtype, content); + if (!pdns_iequals(tmp, content)) { + throw std::runtime_error("Not in expected format (parsed as '"+tmp+"')"); + } + } else { + struct in6_addr tmpbuf; + if (inet_pton(AF_INET6, content.c_str(), &tmpbuf) != 1 || content.find('.') != string::npos) { + throw std::runtime_error("Invalid IPv6 address"); + } + } + rr.content = makeBackendRecordContent(rr.qtype, content); + } + catch(std::exception& e) + { + throw ApiException("Record "+rr.qname.toString()+"/"+rr.qtype.getName()+" '"+content+"': "+e.what()); + } + + if ((rr.qtype.getCode() == QType::A || rr.qtype.getCode() == QType::AAAA) && + boolFromJson(record, "set-ptr", false) == true) { + + g_log<& new_comments) { + Comment c; + c.qname = qname; + c.qtype = qtype; + + time_t now = time(0); + for (auto comment : container["comments"].array_items()) { + c.modified_at = intFromJson(comment, "modified_at", now); + c.content = stringFromJson(comment, "content"); + c.account = stringFromJson(comment, "account"); + new_comments.push_back(c); + } +} + +static void checkDefaultDNSSECAlgos() { + int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]); + int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]); + int k_size = arg().asNum("default-ksk-size"); + int z_size = arg().asNum("default-zsk-size"); + + // Sanity check DNSSEC parameters + if (::arg()["default-zsk-algorithm"] != "") { + if (k_algo == -1) + throw ApiException("default-ksk-algorithm setting is set to unknown algorithm: " + ::arg()["default-ksk-algorithm"]); + else if (k_algo <= 10 && k_size == 0) + throw ApiException("default-ksk-algorithm is set to an algorithm("+::arg()["default-ksk-algorithm"]+") that requires a non-zero default-ksk-size!"); + } + + if (::arg()["default-zsk-algorithm"] != "") { + if (z_algo == -1) + throw ApiException("default-zsk-algorithm setting is set to unknown algorithm: " + ::arg()["default-zsk-algorithm"]); + else if (z_algo <= 10 && z_size == 0) + throw ApiException("default-zsk-algorithm is set to an algorithm("+::arg()["default-zsk-algorithm"]+") that requires a non-zero default-zsk-size!"); + } +} + +static void throwUnableToSecure(const DNSName& zonename) { + throw ApiException("No backend was able to secure '" + zonename.toString() + "', most likely because no DNSSEC" + + "capable backends are loaded, or because the backends have DNSSEC disabled. Check your configuration."); +} + +static void updateDomainSettingsFromDocument(UeberBackend& B, const DomainInfo& di, const DNSName& zonename, const Json document, bool rectifyTransaction=true) { + vector zonemaster; + bool shouldRectify = false; + for(auto value : document["masters"].array_items()) { + string master = value.string_value(); + if (master.empty()) + throw ApiException("Master can not be an empty string"); + try { + ComboAddress m(master); + } catch (const PDNSException &e) { + throw ApiException("Master (" + master + ") is not an IP address: " + e.reason); + } + zonemaster.push_back(master); + } + + if (zonemaster.size()) { + di.backend->setMaster(zonename, boost::join(zonemaster, ",")); + } + if (document["kind"].is_string()) { + di.backend->setKind(zonename, DomainInfo::stringToKind(stringFromJson(document, "kind"))); + } + if (document["soa_edit_api"].is_string()) { + di.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", document["soa_edit_api"].string_value()); + } + if (document["soa_edit"].is_string()) { + di.backend->setDomainMetadataOne(zonename, "SOA-EDIT", document["soa_edit"].string_value()); + } + try { + bool api_rectify = boolFromJson(document, "api_rectify"); + di.backend->setDomainMetadataOne(zonename, "API-RECTIFY", api_rectify ? "1" : "0"); + } + catch (const JsonException&) {} + + if (document["account"].is_string()) { + di.backend->setAccount(zonename, document["account"].string_value()); + } + + DNSSECKeeper dk(&B); + bool dnssecInJSON = false; + bool dnssecDocVal = false; + + try { + dnssecDocVal = boolFromJson(document, "dnssec"); + dnssecInJSON = true; + } + catch (const JsonException&) {} + + bool isDNSSECZone = dk.isSecuredZone(zonename); + + if (dnssecInJSON) { + if (dnssecDocVal) { + if (!isDNSSECZone) { + checkDefaultDNSSECAlgos(); + + int k_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-ksk-algorithm"]); + int z_algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-zsk-algorithm"]); + int k_size = arg().asNum("default-ksk-size"); + int z_size = arg().asNum("default-zsk-size"); + + if (k_algo != -1) { + int64_t id; + if (!dk.addKey(zonename, true, k_algo, id, k_size)) { + throwUnableToSecure(zonename); + } + } + + if (z_algo != -1) { + int64_t id; + if (!dk.addKey(zonename, false, z_algo, id, z_size)) { + throwUnableToSecure(zonename); + } + } + + // Used later for NSEC3PARAM + isDNSSECZone = dk.isSecuredZone(zonename); + + if (!isDNSSECZone) { + throwUnableToSecure(zonename); + } + shouldRectify = true; + } + } else { + // "dnssec": false in json + if (isDNSSECZone) { + string info, error; + if (!dk.unSecureZone(zonename, error, info)) { + throw ApiException("Error while un-securing zone '"+ zonename.toString()+"': " + error); + } + isDNSSECZone = dk.isSecuredZone(zonename); + if (isDNSSECZone) { + throw ApiException("Unable to un-secure zone '"+ zonename.toString()+"'"); + } + shouldRectify = true; + } + } + } + + if(document["nsec3param"].string_value().length() > 0) { + shouldRectify = true; + NSEC3PARAMRecordContent ns3pr(document["nsec3param"].string_value()); + string error_msg = ""; + if (!isDNSSECZone) { + throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"', but zone is not DNSSEC secured."); + } + if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) { + throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg); + } + if (!dk.setNSEC3PARAM(zonename, ns3pr, boolFromJson(document, "nsec3narrow", false))) { + throw ApiException("NSEC3PARAMs provided for zone '" + zonename.toString() + + "' passed our basic sanity checks, but cannot be used with the current backend."); + } + } + + if (shouldRectify && !dk.isPresigned(zonename)) { + // Rectify + string api_rectify; + di.backend->getDomainMetadataOne(zonename, "API-RECTIFY", api_rectify); + if (api_rectify.empty()) { + if (::arg().mustDo("default-api-rectify")) { + api_rectify = "1"; + } + } + if (api_rectify == "1") { + string info; + string error_msg; + if (!dk.rectifyZone(zonename, error_msg, info, rectifyTransaction)) { + throw ApiException("Failed to rectify '" + zonename.toString() + "' " + error_msg); + } + } + + // Increase serial + string soa_edit_api_kind; + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api_kind); + if (!soa_edit_api_kind.empty()) { + SOAData sd; + if (!B.getSOAUncached(zonename, sd)) + return; + + string soa_edit_kind; + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit_kind); + + DNSResourceRecord rr; + if (makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, rr)) { + if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector(1, rr))) { + throw ApiException("Hosting backend does not support editing records."); + } + } + } + } + + if (!document["master_tsig_key_ids"].is_null()) { + vector metadata; + DNSName keyAlgo; + string keyContent; + for(auto value : document["master_tsig_key_ids"].array_items()) { + auto keyname(apiZoneIdToName(value.string_value())); + B.getTSIGKey(keyname, &keyAlgo, &keyContent); + if (keyAlgo.empty() || keyContent.empty()) { + throw ApiException("A TSIG key with the name '"+keyname.toLogString()+"' does not exist"); + } + metadata.push_back(keyname.toString()); + } + if (!di.backend->setDomainMetadata(zonename, "TSIG-ALLOW-AXFR", metadata)) { + throw HttpInternalServerErrorException("Unable to set new TSIG master keys for zone '" + zonename.toLogString() + "'"); + } + } + if (!document["slave_tsig_key_ids"].is_null()) { + vector metadata; + DNSName keyAlgo; + string keyContent; + for(auto value : document["slave_tsig_key_ids"].array_items()) { + auto keyname(apiZoneIdToName(value.string_value())); + B.getTSIGKey(keyname, &keyAlgo, &keyContent); + if (keyAlgo.empty() || keyContent.empty()) { + throw ApiException("A TSIG key with the name '"+keyname.toLogString()+"' does not exist"); + } + metadata.push_back(keyname.toString()); + } + if (!di.backend->setDomainMetadata(zonename, "AXFR-MASTER-TSIG", metadata)) { + throw HttpInternalServerErrorException("Unable to set new TSIG slave keys for zone '" + zonename.toLogString() + "'"); + } + } +} + +static bool isValidMetadataKind(const string& kind, bool readonly) { + static vector builtinOptions { + "ALLOW-AXFR-FROM", + "AXFR-SOURCE", + "ALLOW-DNSUPDATE-FROM", + "TSIG-ALLOW-DNSUPDATE", + "FORWARD-DNSUPDATE", + "SOA-EDIT-DNSUPDATE", + "NOTIFY-DNSUPDATE", + "ALSO-NOTIFY", + "AXFR-MASTER-TSIG", + "GSS-ALLOW-AXFR-PRINCIPAL", + "GSS-ACCEPTOR-PRINCIPAL", + "IXFR", + "LUA-AXFR-SCRIPT", + "NSEC3NARROW", + "NSEC3PARAM", + "PRESIGNED", + "PUBLISH-CDNSKEY", + "PUBLISH-CDS", + "SLAVE-RENOTIFY", + "SOA-EDIT", + "TSIG-ALLOW-AXFR", + "TSIG-ALLOW-DNSUPDATE" + }; + + // the following options do not allow modifications via API + static vector protectedOptions { + "API-RECTIFY", + "AXFR-MASTER-TSIG", + "NSEC3NARROW", + "NSEC3PARAM", + "PRESIGNED", + "LUA-AXFR-SCRIPT", + "TSIG-ALLOW-AXFR" + }; + + if (kind.find("X-") == 0) + return true; + + bool found = false; + + for (const string& s : builtinOptions) { + if (kind == s) { + for (const string& s2 : protectedOptions) { + if (!readonly && s == s2) + return false; + } + found = true; + break; + } + } + + return found; +} + +static void apiZoneMetadata(HttpRequest* req, HttpResponse *resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + if (req->method == "GET") { + map > md; + Json::array document; + + if (!B.getAllDomainMetadata(zonename, md)) + throw HttpNotFoundException(); + + for (const auto& i : md) { + Json::array entries; + for (string j : i.second) + entries.push_back(j); + + Json::object key { + { "type", "Metadata" }, + { "kind", i.first }, + { "metadata", entries } + }; + + document.push_back(key); + } + + resp->setBody(document); + } else if (req->method == "POST") { + auto document = req->json(); + string kind; + vector entries; + + try { + kind = stringFromJson(document, "kind"); + } catch (const JsonException&) { + throw ApiException("kind is not specified or not a string"); + } + + if (!isValidMetadataKind(kind, false)) + throw ApiException("Unsupported metadata kind '" + kind + "'"); + + vector vecMetadata; + + if (!B.getDomainMetadata(zonename, kind, vecMetadata)) + throw ApiException("Could not retrieve metadata entries for domain '" + + zonename.toString() + "'"); + + auto& metadata = document["metadata"]; + if (!metadata.is_array()) + throw ApiException("metadata is not specified or not an array"); + + for (const auto& i : metadata.array_items()) { + if (!i.is_string()) + throw ApiException("metadata must be strings"); + else if (std::find(vecMetadata.cbegin(), + vecMetadata.cend(), + i.string_value()) == vecMetadata.cend()) { + vecMetadata.push_back(i.string_value()); + } + } + + if (!B.setDomainMetadata(zonename, kind, vecMetadata)) + throw ApiException("Could not update metadata entries for domain '" + + zonename.toString() + "'"); + + Json::array respMetadata; + for (const string& s : vecMetadata) + respMetadata.push_back(s); + + Json::object key { + { "type", "Metadata" }, + { "kind", document["kind"] }, + { "metadata", respMetadata } + }; + + resp->status = 201; + resp->setBody(key); + } else + throw HttpMethodNotAllowedException(); +} + +static void apiZoneMetadataKind(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + string kind = req->parameters["kind"]; + + if (req->method == "GET") { + vector metadata; + Json::object document; + Json::array entries; + + if (!B.getDomainMetadata(zonename, kind, metadata)) + throw HttpNotFoundException(); + else if (!isValidMetadataKind(kind, true)) + throw ApiException("Unsupported metadata kind '" + kind + "'"); + + document["type"] = "Metadata"; + document["kind"] = kind; + + for (const string& i : metadata) + entries.push_back(i); + + document["metadata"] = entries; + resp->setBody(document); + } else if (req->method == "PUT") { + auto document = req->json(); + + if (!isValidMetadataKind(kind, false)) + throw ApiException("Unsupported metadata kind '" + kind + "'"); + + vector vecMetadata; + auto& metadata = document["metadata"]; + if (!metadata.is_array()) + throw ApiException("metadata is not specified or not an array"); + + for (const auto& i : metadata.array_items()) { + if (!i.is_string()) + throw ApiException("metadata must be strings"); + vecMetadata.push_back(i.string_value()); + } + + if (!B.setDomainMetadata(zonename, kind, vecMetadata)) + throw ApiException("Could not update metadata entries for domain '" + zonename.toString() + "'"); + + Json::object key { + { "type", "Metadata" }, + { "kind", kind }, + { "metadata", metadata } + }; + + resp->setBody(key); + } else if (req->method == "DELETE") { + if (!isValidMetadataKind(kind, false)) + throw ApiException("Unsupported metadata kind '" + kind + "'"); + + vector md; // an empty vector will do it + if (!B.setDomainMetadata(zonename, kind, md)) + throw ApiException("Could not delete metadata for domain '" + zonename.toString() + "' (" + kind + ")"); + } else + throw HttpMethodNotAllowedException(); +} + +// Throws 404 if the key with inquireKeyId does not exist +static void apiZoneCryptoKeysCheckKeyExists(DNSName zonename, int inquireKeyId, DNSSECKeeper *dk) { + DNSSECKeeper::keyset_t keyset=dk->getKeys(zonename, false); + bool found = false; + for(const auto& value : keyset) { + if (value.second.id == (unsigned) inquireKeyId) { + found = true; + break; + } + } + if (!found) { + throw HttpNotFoundException(); + } +} + +static void apiZoneCryptokeysGET(DNSName zonename, int inquireKeyId, HttpResponse *resp, DNSSECKeeper *dk) { + DNSSECKeeper::keyset_t keyset=dk->getKeys(zonename, false); + + bool inquireSingleKey = inquireKeyId >= 0; + + Json::array doc; + for(const auto& value : keyset) { + if (inquireSingleKey && (unsigned)inquireKeyId != value.second.id) { + continue; + } + + string keyType; + switch (value.second.keyType) { + case DNSSECKeeper::KSK: keyType="ksk"; break; + case DNSSECKeeper::ZSK: keyType="zsk"; break; + case DNSSECKeeper::CSK: keyType="csk"; break; + } + + Json::object key { + { "type", "Cryptokey" }, + { "id", (int)value.second.id }, + { "active", value.second.active }, + { "keytype", keyType }, + { "flags", (uint16_t)value.first.d_flags }, + { "dnskey", value.first.getDNSKEY().getZoneRepresentation() }, + { "algorithm", DNSSECKeeper::algorithm2name(value.first.d_algorithm) }, + { "bits", value.first.getKey()->getBits() } + }; + + if (value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK) { + Json::array dses; + for(const uint8_t keyid : { DNSSECKeeper::SHA1, DNSSECKeeper::SHA256, DNSSECKeeper::GOST, DNSSECKeeper::SHA384 }) + try { + dses.push_back(makeDSFromDNSKey(zonename, value.first.getDNSKEY(), keyid).getZoneRepresentation()); + } catch (...) {} + key["ds"] = dses; + } + + if (inquireSingleKey) { + key["privatekey"] = value.first.getKey()->convertToISC(); + resp->setBody(key); + return; + } + doc.push_back(key); + } + + if (inquireSingleKey) { + // we came here because we couldn't find the requested key. + throw HttpNotFoundException(); + } + resp->setBody(doc); + +} + +/* + * This method handles DELETE requests for URL /api/v1/servers/:server_id/zones/:zone_name/cryptokeys/:cryptokey_id . + * It deletes a key from :zone_name specified by :cryptokey_id. + * Server Answers: + * Case 1: the backend returns true on removal. This means the key is gone. + * The server returns 204 No Content, no body. + * Case 2: the backend returns false on removal. An error occurred. + * The server returns 422 Unprocessable Entity with message "Could not DELETE :cryptokey_id". + * Case 3: the key or zone does not exist. + * The server returns 404 Not Found + * */ +static void apiZoneCryptokeysDELETE(DNSName zonename, int inquireKeyId, HttpRequest *req, HttpResponse *resp, DNSSECKeeper *dk) { + if (dk->removeKey(zonename, inquireKeyId)) { + resp->body = ""; + resp->status = 204; + } else { + resp->setErrorResult("Could not DELETE " + req->parameters["key_id"], 422); + } +} + +/* + * This method adds a key to a zone by generate it or content parameter. + * Parameter: + * { + * "privatekey" : "key The format used is compatible with BIND and NSD/LDNS" + * "keytype" : "ksk|zsk" + * "active" : "true|false" + * "algorithm" : "key generation algorithm name as default" https://doc.powerdns.com/md/authoritative/dnssec/#supported-algorithms + * "bits" : number of bits + * } + * + * Response: + * Case 1: keytype isn't ksk|zsk + * The server returns 422 Unprocessable Entity {"error" : "Invalid keytype 'keytype'"} + * Case 2: 'bits' must be a positive integer value. + * The server returns 422 Unprocessable Entity {"error" : "'bits' must be a positive integer value."} + * Case 3: The "algorithm" isn't supported + * The server returns 422 Unprocessable Entity {"error" : "Unknown algorithm: 'algo'"} + * Case 4: Algorithm <= 10 and no bits were passed + * The server returns 422 Unprocessable Entity {"error" : "Creating an algorithm algo key requires the size (in bits) to be passed"} + * Case 5: The wrong keysize was passed + * The server returns 422 Unprocessable Entity {"error" : "The algorithm does not support the given bit size."} + * Case 6: If the server cant guess the keysize + * The server returns 422 Unprocessable Entity {"error" : "Can not guess key size for algorithm"} + * Case 7: The key-creation failed + * The server returns 422 Unprocessable Entity {"error" : "Adding key failed, perhaps DNSSEC not enabled in configuration?"} + * Case 8: The key in content has the wrong format + * The server returns 422 Unprocessable Entity {"error" : "Key could not be parsed. Make sure your key format is correct."} + * Case 9: The wrong combination of fields is submitted + * The server returns 422 Unprocessable Entity {"error" : "Either you submit just the 'content' field or you leave 'content' empty and submit the other fields."} + * Case 10: No content and everything was fine + * The server returns 201 Created and all public data about the new cryptokey + * Case 11: With specified content + * The server returns 201 Created and all public data about the added cryptokey + */ + +static void apiZoneCryptokeysPOST(DNSName zonename, HttpRequest *req, HttpResponse *resp, DNSSECKeeper *dk) { + auto document = req->json(); + string privatekey_fieldname = "privatekey"; + auto privatekey = document["privatekey"]; + if (privatekey.is_null()) { + // Fallback to the old "content" behaviour + privatekey = document["content"]; + privatekey_fieldname = "content"; + } + bool active = boolFromJson(document, "active", false); + bool keyOrZone; + + if (stringFromJson(document, "keytype") == "ksk" || stringFromJson(document, "keytype") == "csk") { + keyOrZone = true; + } else if (stringFromJson(document, "keytype") == "zsk") { + keyOrZone = false; + } else { + throw ApiException("Invalid keytype " + stringFromJson(document, "keytype")); + } + + int64_t insertedId = -1; + + if (privatekey.is_null()) { + int bits = keyOrZone ? ::arg().asNum("default-ksk-size") : ::arg().asNum("default-zsk-size"); + auto docbits = document["bits"]; + if (!docbits.is_null()) { + if (!docbits.is_number() || (fmod(docbits.number_value(), 1.0) != 0) || docbits.int_value() < 0) { + throw ApiException("'bits' must be a positive integer value"); + } else { + bits = docbits.int_value(); + } + } + int algorithm = DNSSECKeeper::shorthand2algorithm(keyOrZone ? ::arg()["default-ksk-algorithm"] : ::arg()["default-zsk-algorithm"]); + auto providedAlgo = document["algorithm"]; + if (providedAlgo.is_string()) { + algorithm = DNSSECKeeper::shorthand2algorithm(providedAlgo.string_value()); + if (algorithm == -1) + throw ApiException("Unknown algorithm: " + providedAlgo.string_value()); + } else if (providedAlgo.is_number()) { + algorithm = providedAlgo.int_value(); + } else if (!providedAlgo.is_null()) { + throw ApiException("Unknown algorithm: " + providedAlgo.string_value()); + } + + try { + if (!dk->addKey(zonename, keyOrZone, algorithm, insertedId, bits, active)) { + throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); + } + } catch (std::runtime_error& error) { + throw ApiException(error.what()); + } + if (insertedId < 0) + throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); + } else if (document["bits"].is_null() && document["algorithm"].is_null()) { + auto keyData = stringFromJson(document, privatekey_fieldname); + DNSKEYRecordContent dkrc; + DNSSECPrivateKey dpk; + try { + shared_ptr dke(DNSCryptoKeyEngine::makeFromISCString(dkrc, keyData)); + dpk.d_algorithm = dkrc.d_algorithm; + // TODO remove in 4.2.0 + if(dpk.d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1) + dpk.d_algorithm = DNSSECKeeper::RSASHA1; + + if (keyOrZone) + dpk.d_flags = 257; + else + dpk.d_flags = 256; + + dpk.setKey(dke); + } + catch (std::runtime_error& error) { + throw ApiException("Key could not be parsed. Make sure your key format is correct."); + } try { + if (!dk->addKey(zonename, dpk,insertedId, active)) { + throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); + } + } catch (std::runtime_error& error) { + throw ApiException(error.what()); + } + if (insertedId < 0) + throw ApiException("Adding key failed, perhaps DNSSEC not enabled in configuration?"); + } else { + throw ApiException("Either you submit just the 'privatekey' field or you leave 'privatekey' empty and submit the other fields."); + } + apiZoneCryptokeysGET(zonename, insertedId, resp, dk); + resp->status = 201; +} + +/* + * This method handles PUT (execute) requests for URL /api/v1/servers/:server_id/zones/:zone_name/cryptokeys/:cryptokey_id . + * It de/activates a key from :zone_name specified by :cryptokey_id. + * Server Answers: + * Case 1: invalid JSON data + * The server returns 400 Bad Request + * Case 2: the backend returns true on de/activation. This means the key is de/active. + * The server returns 204 No Content + * Case 3: the backend returns false on de/activation. An error occurred. + * The sever returns 422 Unprocessable Entity with message "Could not de/activate Key: :cryptokey_id in Zone: :zone_name" + * */ +static void apiZoneCryptokeysPUT(DNSName zonename, int inquireKeyId, HttpRequest *req, HttpResponse *resp, DNSSECKeeper *dk) { + //throws an exception if the Body is empty + auto document = req->json(); + //throws an exception if the key does not exist or is not a bool + bool active = boolFromJson(document, "active"); + if (active) { + if (!dk->activateKey(zonename, inquireKeyId)) { + resp->setErrorResult("Could not activate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); + return; + } + } else { + if (!dk->deactivateKey(zonename, inquireKeyId)) { + resp->setErrorResult("Could not deactivate Key: " + req->parameters["key_id"] + " in Zone: " + zonename.toString(), 422); + return; + } + } + resp->body = ""; + resp->status = 204; + return; +} + +/* + * This method chooses the right functionality for the request. It also checks for a cryptokey_id which has to be passed + * by URL /api/v1/servers/:server_id/zones/:zone_name/cryptokeys/:cryptokey_id . + * If the the HTTP-request-method isn't supported, the function returns a response with the 405 code (method not allowed). + * */ +static void apiZoneCryptokeys(HttpRequest *req, HttpResponse *resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + UeberBackend B; + DNSSECKeeper dk(&B); + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + int inquireKeyId = -1; + if (req->parameters.count("key_id")) { + inquireKeyId = std::stoi(req->parameters["key_id"]); + apiZoneCryptoKeysCheckKeyExists(zonename, inquireKeyId, &dk); + } + + if (req->method == "GET") { + apiZoneCryptokeysGET(zonename, inquireKeyId, resp, &dk); + } else if (req->method == "DELETE") { + if (inquireKeyId == -1) + throw HttpBadRequestException(); + apiZoneCryptokeysDELETE(zonename, inquireKeyId, req, resp, &dk); + } else if (req->method == "POST") { + apiZoneCryptokeysPOST(zonename, req, resp, &dk); + } else if (req->method == "PUT") { + if (inquireKeyId == -1) + throw HttpBadRequestException(); + apiZoneCryptokeysPUT(zonename, inquireKeyId, req, resp, &dk); + } else { + throw HttpMethodNotAllowedException(); //Returns method not allowed + } +} + +static void gatherRecordsFromZone(const std::string& zonestring, vector& new_records, DNSName zonename) { + DNSResourceRecord rr; + vector zonedata; + stringtok(zonedata, zonestring, "\r\n"); + + ZoneParserTNG zpt(zonedata, zonename); + + bool seenSOA=false; + + string comment = "Imported via the API"; + + try { + while(zpt.get(rr, &comment)) { + if(seenSOA && rr.qtype.getCode() == QType::SOA) + continue; + if(rr.qtype.getCode() == QType::SOA) + seenSOA=true; + validateGatheredRRType(rr); + + new_records.push_back(rr); + } + } + catch(std::exception& ae) { + throw ApiException("An error occurred while parsing the zonedata: "+string(ae.what())); + } +} + +/** Throws ApiException if records which violate RRset contraints are present. + * NOTE: sorts records in-place. + * + * Constraints being checked: + * *) no exact duplicates + * *) no duplicates for QTypes that can only be present once per RRset + * *) hostnames are hostnames + */ +static void checkNewRecords(vector& records) { + sort(records.begin(), records.end(), + [](const DNSResourceRecord& rec_a, const DNSResourceRecord& rec_b) -> bool { + /* we need _strict_ weak ordering */ + return std::tie(rec_a.qname, rec_a.qtype, rec_a.content) < std::tie(rec_b.qname, rec_b.qtype, rec_b.content); + } + ); + + DNSResourceRecord previous; + for(const auto& rec : records) { + if (previous.qname == rec.qname) { + if (previous.qtype == rec.qtype) { + if (onlyOneEntryTypes.count(rec.qtype.getCode()) != 0) { + throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.getName()+" has more than one record"); + } + if (previous.content == rec.content) { + throw ApiException("Duplicate record in RRset " + rec.qname.toString() + " IN " + rec.qtype.getName() + " with content \"" + rec.content + "\""); + } + } else if (exclusiveEntryTypes.count(rec.qtype.getCode()) != 0 || exclusiveEntryTypes.count(previous.qtype.getCode()) != 0) { + throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.getName()+": Conflicts with another RRset"); + } + } + + // Check if the DNSNames that should be hostnames, are hostnames + try { + checkHostnameCorrectness(rec); + } catch (const std::exception& e) { + throw ApiException("RRset "+rec.qname.toString()+" IN "+rec.qtype.getName() + " " + e.what()); + } + + previous = rec; + } +} + +static void checkTSIGKey(UeberBackend& B, const DNSName& keyname, const DNSName& algo, const string& content) { + DNSName algoFromDB; + string contentFromDB; + B.getTSIGKey(keyname, &algoFromDB, &contentFromDB); + if (!contentFromDB.empty() || !algoFromDB.empty()) { + throw HttpConflictException("A TSIG key with the name '"+keyname.toLogString()+"' already exists"); + } + + TSIGHashEnum the; + if (!getTSIGHashEnum(algo, the)) { + throw ApiException("Unknown TSIG algorithm: " + algo.toLogString()); + } + + string b64out; + if (B64Decode(content, b64out) == -1) { + throw ApiException("TSIG content '" + content + "' cannot be base64-decoded"); + } +} + +static Json::object makeJSONTSIGKey(const DNSName& keyname, const DNSName& algo, const string& content) { + Json::object tsigkey = { + { "name", keyname.toStringNoDot() }, + { "id", apiZoneNameToId(keyname) }, + { "algorithm", algo.toStringNoDot() }, + { "key", content }, + { "type", "TSIGKey" } + }; + return tsigkey; +} + +static Json::object makeJSONTSIGKey(const struct TSIGKey& key, bool doContent=true) { + return makeJSONTSIGKey(key.name, key.algorithm, doContent ? key.key : ""); +} + +static void apiServerTSIGKeys(HttpRequest* req, HttpResponse* resp) { + UeberBackend B; + if (req->method == "GET") { + vector keys; + + if (!B.getTSIGKeys(keys)) { + throw HttpInternalServerErrorException("Unable to retrieve TSIG keys"); + } + + Json::array doc; + + for(const auto &key : keys) { + doc.push_back(makeJSONTSIGKey(key, false)); + } + resp->setBody(doc); + } else if (req->method == "POST") { + auto document = req->json(); + DNSName keyname(stringFromJson(document, "name")); + DNSName algo(stringFromJson(document, "algorithm")); + string content = document["key"].string_value(); + + if (content.empty()) { + try { + content = makeTSIGKey(algo); + } catch (const PDNSException& e) { + throw HttpBadRequestException(e.reason); + } + } + + // Will throw an ApiException or HttpConflictException on error + checkTSIGKey(B, keyname, algo, content); + + if(!B.setTSIGKey(keyname, algo, content)) { + throw HttpInternalServerErrorException("Unable to add TSIG key"); + } + + resp->status = 201; + resp->setBody(makeJSONTSIGKey(keyname, algo, content)); + } else { + throw HttpMethodNotAllowedException(); + } +} + +static void apiServerTSIGKeyDetail(HttpRequest* req, HttpResponse* resp) { + UeberBackend B; + DNSName keyname = apiZoneIdToName(req->parameters["id"]); + DNSName algo; + string content; + + if (!B.getTSIGKey(keyname, &algo, &content)) { + throw HttpNotFoundException("TSIG key with name '"+keyname.toLogString()+"' not found"); + } + + struct TSIGKey tsk; + tsk.name = keyname; + tsk.algorithm = algo; + tsk.key = content; + + if (req->method == "GET") { + resp->setBody(makeJSONTSIGKey(tsk)); + } else if (req->method == "PUT") { + json11::Json document; + if (!req->body.empty()) { + document = req->json(); + } + if (document["name"].is_string()) { + tsk.name = DNSName(document["name"].string_value()); + } + if (document["algorithm"].is_string()) { + tsk.algorithm = DNSName(document["algorithm"].string_value()); + + TSIGHashEnum the; + if (!getTSIGHashEnum(tsk.algorithm, the)) { + throw ApiException("Unknown TSIG algorithm: " + tsk.algorithm.toLogString()); + } + } + if (document["key"].is_string()) { + string new_content = document["key"].string_value(); + string decoded; + if (B64Decode(new_content, decoded) == -1) { + throw ApiException("Can not base64 decode key content '" + new_content + "'"); + } + tsk.key = new_content; + } + if (!B.setTSIGKey(tsk.name, tsk.algorithm, tsk.key)) { + throw HttpInternalServerErrorException("Unable to save TSIG Key"); + } + if (tsk.name != keyname) { + // Remove the old key + if (!B.deleteTSIGKey(keyname)) { + throw HttpInternalServerErrorException("Unable to remove TSIG key '" + keyname.toStringNoDot() + "'"); + } + } + resp->setBody(makeJSONTSIGKey(tsk)); + } else if (req->method == "DELETE") { + if (!B.deleteTSIGKey(keyname)) { + throw HttpInternalServerErrorException("Unable to remove TSIG key '" + keyname.toStringNoDot() + "'"); + } else { + resp->body = ""; + resp->status = 204; + } + } else { + throw HttpMethodNotAllowedException(); + } +} + +static void apiServerZones(HttpRequest* req, HttpResponse* resp) { + UeberBackend B; + DNSSECKeeper dk(&B); + if (req->method == "POST") { + DomainInfo di; + auto document = req->json(); + DNSName zonename = apiNameToDNSName(stringFromJson(document, "name")); + apiCheckNameAllowedCharacters(zonename.toString()); + zonename.makeUsLowerCase(); + + bool exists = B.getDomainInfo(zonename, di); + if(exists) + throw HttpConflictException(); + + // validate 'kind' is set + DomainInfo::DomainKind zonekind = DomainInfo::stringToKind(stringFromJson(document, "kind")); + + string zonestring = document["zone"].string_value(); + auto rrsets = document["rrsets"]; + if (rrsets.is_array() && zonestring != "") + throw ApiException("You cannot give rrsets AND zone data as text"); + + auto nameservers = document["nameservers"]; + if (!nameservers.is_array() && zonekind != DomainInfo::Slave) + throw ApiException("Nameservers list must be given (but can be empty if NS records are supplied)"); + + string soa_edit_api_kind; + if (document["soa_edit_api"].is_string()) { + soa_edit_api_kind = document["soa_edit_api"].string_value(); + } + else { + soa_edit_api_kind = "DEFAULT"; + } + string soa_edit_kind = document["soa_edit"].string_value(); + + // if records/comments are given, load and check them + bool have_soa = false; + bool have_zone_ns = false; + vector new_records; + vector new_comments; + vector new_ptrs; + + if (rrsets.is_array()) { + for (const auto& rrset : rrsets.array_items()) { + DNSName qname = apiNameToDNSName(stringFromJson(rrset, "name")); + apiCheckQNameAllowedCharacters(qname.toString()); + QType qtype; + qtype = stringFromJson(rrset, "type"); + if (qtype.getCode() == 0) { + throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given"); + } + if (rrset["records"].is_array()) { + int ttl = intFromJson(rrset, "ttl"); + gatherRecords(B, req->logprefix, rrset, qname, qtype, ttl, new_records, new_ptrs); + } + if (rrset["comments"].is_array()) { + gatherComments(rrset, qname, qtype, new_comments); + } + } + } else if (zonestring != "") { + gatherRecordsFromZone(zonestring, new_records, zonename); + } + + for(auto& rr : new_records) { + rr.qname.makeUsLowerCase(); + if (!rr.qname.isPartOf(zonename) && rr.qname != zonename) + throw ApiException("RRset "+rr.qname.toString()+" IN "+rr.qtype.getName()+": Name is out of zone"); + apiCheckQNameAllowedCharacters(rr.qname.toString()); + + if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) { + have_soa = true; + increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind); + } + if (rr.qtype.getCode() == QType::NS && rr.qname==zonename) { + have_zone_ns = true; + } + } + + // synthesize RRs as needed + DNSResourceRecord autorr; + autorr.qname = zonename; + autorr.auth = 1; + autorr.ttl = ::arg().asNum("default-ttl"); + + if (!have_soa && zonekind != DomainInfo::Slave) { + // synthesize a SOA record so the zone "really" exists + string soa = (boost::format("%s %s %ul") + % ::arg()["default-soa-name"] + % (::arg().isEmpty("default-soa-mail") ? (DNSName("hostmaster.") + zonename).toString() : ::arg()["default-soa-mail"]) + % document["serial"].int_value() + ).str(); + SOAData sd; + fillSOAData(soa, sd); // fills out default values for us + autorr.qtype = QType::SOA; + autorr.content = makeSOAContent(sd)->getZoneRepresentation(true); + increaseSOARecord(autorr, soa_edit_api_kind, soa_edit_kind); + new_records.push_back(autorr); + } + + // create NS records if nameservers are given + for (auto value : nameservers.array_items()) { + string nameserver = value.string_value(); + if (nameserver.empty()) + throw ApiException("Nameservers must be non-empty strings"); + if (!isCanonical(nameserver)) + throw ApiException("Nameserver is not canonical: '" + nameserver + "'"); + try { + // ensure the name parses + autorr.content = DNSName(nameserver).toStringRootDot(); + } catch (...) { + throw ApiException("Unable to parse DNS Name for NS '" + nameserver + "'"); + } + autorr.qtype = QType::NS; + new_records.push_back(autorr); + if (have_zone_ns) { + throw ApiException("Nameservers list MUST NOT be mixed with zone-level NS in rrsets"); + } + } + + checkNewRecords(new_records); + + if (boolFromJson(document, "dnssec", false)) { + checkDefaultDNSSECAlgos(); + + if(document["nsec3param"].string_value().length() > 0) { + NSEC3PARAMRecordContent ns3pr(document["nsec3param"].string_value()); + string error_msg = ""; + if (!dk.checkNSEC3PARAM(ns3pr, error_msg)) { + throw ApiException("NSEC3PARAMs provided for zone '"+zonename.toString()+"' are invalid. " + error_msg); + } + } + } + + // no going back after this + if(!B.createDomain(zonename)) + throw ApiException("Creating domain '"+zonename.toString()+"' failed"); + + if(!B.getDomainInfo(zonename, di)) + throw ApiException("Creating domain '"+zonename.toString()+"' failed: lookup of domain ID failed"); + + di.backend->startTransaction(zonename, di.id); + + // updateDomainSettingsFromDocument does NOT fill out the default we've established above. + if (!soa_edit_api_kind.empty()) { + di.backend->setDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api_kind); + } + + for(auto rr : new_records) { + rr.domain_id = di.id; + di.backend->feedRecord(rr, DNSName()); + } + for(Comment& c : new_comments) { + c.domain_id = di.id; + di.backend->feedComment(c); + } + + updateDomainSettingsFromDocument(B, di, zonename, document, false); + + di.backend->commitTransaction(); + + storeChangedPTRs(B, new_ptrs); + + fillZone(B, zonename, resp, shouldDoRRSets(req)); + resp->status = 201; + return; + } + + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + vector domains; + + if (req->getvars.count("zone")) { + string zone = req->getvars["zone"]; + apiCheckNameAllowedCharacters(zone); + DNSName zonename = apiNameToDNSName(zone); + zonename.makeUsLowerCase(); + DomainInfo di; + if (B.getDomainInfo(zonename, di)) { + domains.push_back(di); + } + } else { + try { + B.getAllDomains(&domains, true); // incl. disabled + } catch(const PDNSException &e) { + throw HttpInternalServerErrorException("Could not retrieve all domain information: " + e.reason); + } + } + + bool with_dnssec = true; + if (req->getvars.count("dnssec")) { + // can send ?dnssec=false to improve performance. + string dnssec_flag = req->getvars["dnssec"]; + if (dnssec_flag == "false") { + with_dnssec = false; + } + } + + Json::array doc; + for(const DomainInfo& di : domains) { + doc.push_back(getZoneInfo(di, with_dnssec ? &dk : nullptr)); + } + resp->setBody(doc); +} + +static void apiServerZoneDetail(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + UeberBackend B; + DomainInfo di; + try { + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + } catch(const PDNSException &e) { + throw HttpInternalServerErrorException("Could not retrieve Domain Info: " + e.reason); + } + + if(req->method == "PUT") { + // update domain settings + + di.backend->startTransaction(zonename, -1); + updateDomainSettingsFromDocument(B, di, zonename, req->json(), false); + di.backend->commitTransaction(); + + resp->body = ""; + resp->status = 204; // No Content, but indicate success + return; + } + else if(req->method == "DELETE") { + // delete domain + if(!di.backend->deleteDomain(zonename)) + throw ApiException("Deleting domain '"+zonename.toString()+"' failed: backend delete failed/unsupported"); + + // clear caches + DNSSECKeeper dk(&B); + dk.clearCaches(zonename); + purgeAuthCaches(zonename.toString() + "$"); + + // empty body on success + resp->body = ""; + resp->status = 204; // No Content: declare that the zone is gone now + return; + } else if (req->method == "PATCH") { + patchZone(B, req, resp); + return; + } else if (req->method == "GET") { + fillZone(B, zonename, resp, shouldDoRRSets(req)); + return; + } + throw HttpMethodNotAllowedException(); +} + +static void apiServerZoneExport(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + ostringstream ss; + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + DNSResourceRecord rr; + SOAData sd; + di.backend->list(zonename, di.id); + while(di.backend->get(rr)) { + if (!rr.qtype.getCode()) + continue; // skip empty non-terminals + + ss << + rr.qname.toString() << "\t" << + rr.ttl << "\t" << + "IN" << "\t" << + rr.qtype.getName() << "\t" << + makeApiRecordContent(rr.qtype, rr.content) << + endl; + } + + if (req->accept_json) { + resp->setBody(Json::object { { "zone", ss.str() } }); + } else { + resp->headers["Content-Type"] = "text/plain; charset=us-ascii"; + resp->body = ss.str(); + } +} + +static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + if(req->method != "PUT") + throw HttpMethodNotAllowedException(); + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + if(di.masters.empty()) + throw ApiException("Domain '"+zonename.toString()+"' is not a slave domain (or has no master defined)"); + + random_shuffle(di.masters.begin(), di.masters.end()); + Communicator.addSuckRequest(zonename, di.masters.front()); + resp->setSuccessResult("Added retrieval request for '"+zonename.toString()+"' from master "+di.masters.front().toLogString()); +} + +static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + if(req->method != "PUT") + throw HttpMethodNotAllowedException(); + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + if(!Communicator.notifyDomain(zonename, &B)) + throw ApiException("Failed to add to the queue - see server log"); + + resp->setSuccessResult("Notification queued"); +} + +static void apiServerZoneRectify(HttpRequest* req, HttpResponse* resp) { + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + + if(req->method != "PUT") + throw HttpMethodNotAllowedException(); + + UeberBackend B; + DomainInfo di; + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + DNSSECKeeper dk(&B); + + if (!dk.isSecuredZone(zonename)) + throw ApiException("Zone '" + zonename.toString() + "' is not DNSSEC signed, not rectifying."); + + if (di.kind == DomainInfo::Slave) + throw ApiException("Zone '" + zonename.toString() + "' is a slave zone, not rectifying."); + + string error_msg = ""; + string info; + if (!dk.rectifyZone(zonename, error_msg, info, true)) + throw ApiException("Failed to rectify '" + zonename.toString() + "' " + error_msg); + + resp->setSuccessResult("Rectified"); +} + +static void makePtr(const DNSResourceRecord& rr, DNSResourceRecord* ptr) { + if (rr.qtype.getCode() == QType::A) { + uint32_t ip; + if (!IpToU32(rr.content, &ip)) { + throw ApiException("PTR: Invalid IP address given"); + } + ptr->qname = DNSName((boost::format("%u.%u.%u.%u.in-addr.arpa.") + % ((ip >> 24) & 0xff) + % ((ip >> 16) & 0xff) + % ((ip >> 8) & 0xff) + % ((ip ) & 0xff) + ).str()); + } else if (rr.qtype.getCode() == QType::AAAA) { + ComboAddress ca(rr.content); + char buf[3]; + ostringstream ss; + for (int octet = 0; octet < 16; ++octet) { + if (snprintf(buf, sizeof(buf), "%02x", ca.sin6.sin6_addr.s6_addr[octet]) != (sizeof(buf)-1)) { + // this should be impossible: no byte should give more than two digits in hex format + throw PDNSException("Formatting IPv6 address failed"); + } + ss << buf[0] << '.' << buf[1] << '.'; + } + string tmp = ss.str(); + tmp.resize(tmp.size()-1); // remove last dot + // reverse and append arpa domain + ptr->qname = DNSName(string(tmp.rbegin(), tmp.rend())) + DNSName("ip6.arpa."); + } else { + throw ApiException("Unsupported PTR source '" + rr.qname.toString() + "' type '" + rr.qtype.getName() + "'"); + } + + ptr->qtype = "PTR"; + ptr->ttl = rr.ttl; + ptr->disabled = rr.disabled; + ptr->content = rr.qname.toStringRootDot(); +} + +static void storeChangedPTRs(UeberBackend& B, vector& new_ptrs) { + for(const DNSResourceRecord& rr : new_ptrs) { + SOAData sd; + if (!B.getAuth(rr.qname, QType(QType::PTR), &sd, false)) + throw ApiException("Could not find domain for PTR '"+rr.qname.toString()+"' requested for '"+rr.content+"' (while saving)"); + + string soa_edit_api_kind; + string soa_edit_kind; + bool soa_changed = false; + DNSResourceRecord soarr; + sd.db->getDomainMetadataOne(sd.qname, "SOA-EDIT-API", soa_edit_api_kind); + sd.db->getDomainMetadataOne(sd.qname, "SOA-EDIT", soa_edit_kind); + if (!soa_edit_api_kind.empty()) { + soa_changed = makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, soarr); + } + + sd.db->startTransaction(sd.qname); + if (!sd.db->replaceRRSet(sd.domain_id, rr.qname, rr.qtype, vector(1, rr))) { + sd.db->abortTransaction(); + throw ApiException("PTR-Hosting backend for "+rr.qname.toString()+"/"+rr.qtype.getName()+" does not support editing records."); + } + + if (soa_changed) { + sd.db->replaceRRSet(sd.domain_id, soarr.qname, soarr.qtype, vector(1, soarr)); + } + + sd.db->commitTransaction(); + purgeAuthCachesExact(rr.qname); + } +} + +static void patchZone(UeberBackend& B, HttpRequest* req, HttpResponse* resp) { + bool zone_disabled; + SOAData sd; + DomainInfo di; + DNSName zonename = apiZoneIdToName(req->parameters["id"]); + if (!B.getDomainInfo(zonename, di)) { + throw HttpNotFoundException(); + } + + vector new_records; + vector new_comments; + vector new_ptrs; + + Json document = req->json(); + + auto rrsets = document["rrsets"]; + if (!rrsets.is_array()) + throw ApiException("No rrsets given in update request"); + + di.backend->startTransaction(zonename); + + try { + string soa_edit_api_kind; + string soa_edit_kind; + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api_kind); + di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit_kind); + bool soa_edit_done = false; + + set> seen; + + for (const auto& rrset : rrsets.array_items()) { + string changetype = toUpper(stringFromJson(rrset, "changetype")); + DNSName qname = apiNameToDNSName(stringFromJson(rrset, "name")); + apiCheckQNameAllowedCharacters(qname.toString()); + QType qtype; + qtype = stringFromJson(rrset, "type"); + if (qtype.getCode() == 0) { + throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given"); + } + + if(seen.count({qname, qtype})) + { + throw ApiException("Duplicate RRset "+qname.toString()+" IN "+qtype.getName()); + } + seen.insert({qname, qtype}); + + if (changetype == "DELETE") { + // delete all matching qname/qtype RRs (and, implicitly comments). + if (!di.backend->replaceRRSet(di.id, qname, qtype, vector())) { + throw ApiException("Hosting backend does not support editing records."); + } + } + else if (changetype == "REPLACE") { + // we only validate for REPLACE, as DELETE can be used to "fix" out of zone records. + if (!qname.isPartOf(zonename) && qname != zonename) + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Name is out of zone"); + + bool replace_records = rrset["records"].is_array(); + bool replace_comments = rrset["comments"].is_array(); + + if (!replace_records && !replace_comments) { + throw ApiException("No change for RRset " + qname.toString() + " IN " + qtype.getName()); + } + + new_records.clear(); + new_comments.clear(); + + if (replace_records) { + // ttl shouldn't be part of DELETE, and it shouldn't be required if we don't get new records. + int ttl = intFromJson(rrset, "ttl"); + // new_ptrs is merged. + gatherRecords(B, req->logprefix, rrset, qname, qtype, ttl, new_records, new_ptrs); + + for(DNSResourceRecord& rr : new_records) { + rr.domain_id = di.id; + if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) { + soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind); + } + } + checkNewRecords(new_records); + } + + if (replace_comments) { + gatherComments(rrset, qname, qtype, new_comments); + + for(Comment& c : new_comments) { + c.domain_id = di.id; + } + } + + if (replace_records) { + bool ent_present = false; + di.backend->lookup(QType(QType::ANY), qname, nullptr, di.id); + DNSResourceRecord rr; + while (di.backend->get(rr)) { + if (rr.qtype.getCode() == QType::ENT) { + ent_present = true; + /* that's fine, we will override it */ + continue; + } + if (qtype.getCode() != rr.qtype.getCode() + && (exclusiveEntryTypes.count(qtype.getCode()) != 0 + || exclusiveEntryTypes.count(rr.qtype.getCode()) != 0)) { + + // leave database handle in a consistent state + while (di.backend->get(rr)) + ; + + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Conflicts with pre-existing RRset"); + } + } + + if (!new_records.empty() && ent_present) { + QType qt_ent{0}; + if (!di.backend->replaceRRSet(di.id, qname, qt_ent, new_records)) { + throw ApiException("Hosting backend does not support editing records."); + } + } + if (!di.backend->replaceRRSet(di.id, qname, qtype, new_records)) { + throw ApiException("Hosting backend does not support editing records."); + } + } + if (replace_comments) { + if (!di.backend->replaceComments(di.id, qname, qtype, new_comments)) { + throw ApiException("Hosting backend does not support editing comments."); + } + } + } + else + throw ApiException("Changetype not understood"); + } + + zone_disabled = (!B.getSOAUncached(zonename, sd)); + + // edit SOA (if needed) + if (!zone_disabled && !soa_edit_api_kind.empty() && !soa_edit_done) { + DNSResourceRecord rr; + if (makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, rr)) { + if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector(1, rr))) { + throw ApiException("Hosting backend does not support editing records."); + } + } + + // return old and new serials in headers + resp->headers["X-PDNS-Old-Serial"] = std::to_string(sd.serial); + fillSOAData(rr.content, sd); + resp->headers["X-PDNS-New-Serial"] = std::to_string(sd.serial); + } + + } catch(...) { + di.backend->abortTransaction(); + throw; + } + + // Rectify + DNSSECKeeper dk(&B); + if (!zone_disabled && !dk.isPresigned(zonename)) { + string api_rectify; + if (!di.backend->getDomainMetadataOne(zonename, "API-RECTIFY", api_rectify) && ::arg().mustDo("default-api-rectify")) { + api_rectify = "1"; + } + if (api_rectify == "1") { + string info; + string error_msg; + if (!dk.rectifyZone(zonename, error_msg, info, false)) { + throw ApiException("Failed to rectify '" + zonename.toString() + "' " + error_msg); + } + } + } + + di.backend->commitTransaction(); + + purgeAuthCaches(zonename.toString() + "$"); + + // now the PTRs + storeChangedPTRs(B, new_ptrs); + + resp->body = ""; + resp->status = 204; // No Content, but indicate success + return; +} + +static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { + if(req->method != "GET") + throw HttpMethodNotAllowedException(); + + string q = req->getvars["q"]; + string sMax = req->getvars["max"]; + string sObjectType = req->getvars["object_type"]; + + int maxEnts = 100; + int ents = 0; + + // the following types of data can be searched for using the api + enum class ObjectType + { + ALL, + ZONE, + RECORD, + COMMENT + } objectType; + + if (q.empty()) + throw ApiException("Query q can't be blank"); + if (!sMax.empty()) + maxEnts = std::stoi(sMax); + if (maxEnts < 1) + throw ApiException("Maximum entries must be larger than 0"); + + if (sObjectType.empty()) + objectType = ObjectType::ALL; + else if (sObjectType == "all") + objectType = ObjectType::ALL; + else if (sObjectType == "zone") + objectType = ObjectType::ZONE; + else if (sObjectType == "record") + objectType = ObjectType::RECORD; + else if (sObjectType == "comment") + objectType = ObjectType::COMMENT; + else + throw ApiException("object_type must be one of the following options: all, zone, record, comment"); + + SimpleMatch sm(q,true); + UeberBackend B; + vector domains; + vector result_rr; + vector result_c; + map zoneIdZone; + map::iterator val; + Json::array doc; + + B.getAllDomains(&domains, true); + + for(const DomainInfo di: domains) + { + if ((objectType == ObjectType::ALL || objectType == ObjectType::ZONE) && ents < maxEnts && sm.match(di.zone)) { + doc.push_back(Json::object { + { "object_type", "zone" }, + { "zone_id", apiZoneNameToId(di.zone) }, + { "name", di.zone.toString() } + }); + ents++; + } + zoneIdZone[di.id] = di; // populate cache + } + + if ((objectType == ObjectType::ALL || objectType == ObjectType::RECORD) && B.searchRecords(q, maxEnts, result_rr)) + { + for(const DNSResourceRecord& rr: result_rr) + { + if (!rr.qtype.getCode()) + continue; // skip empty non-terminals + + auto object = Json::object { + { "object_type", "record" }, + { "name", rr.qname.toString() }, + { "type", rr.qtype.getName() }, + { "ttl", (double)rr.ttl }, + { "disabled", rr.disabled }, + { "content", makeApiRecordContent(rr.qtype, rr.content) } + }; + if ((val = zoneIdZone.find(rr.domain_id)) != zoneIdZone.end()) { + object["zone_id"] = apiZoneNameToId(val->second.zone); + object["zone"] = val->second.zone.toString(); + } + doc.push_back(object); + } + } + + if ((objectType == ObjectType::ALL || objectType == ObjectType::COMMENT) && B.searchComments(q, maxEnts, result_c)) + { + for(const Comment &c: result_c) + { + auto object = Json::object { + { "object_type", "comment" }, + { "name", c.qname.toString() }, + { "content", c.content } + }; + if ((val = zoneIdZone.find(c.domain_id)) != zoneIdZone.end()) { + object["zone_id"] = apiZoneNameToId(val->second.zone); + object["zone"] = val->second.zone.toString(); + } + doc.push_back(object); + } + } + + resp->setBody(doc); +} + +void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) { + if(req->method != "PUT") + throw HttpMethodNotAllowedException(); + + DNSName canon = apiNameToDNSName(req->getvars["domain"]); + + uint64_t count = purgeAuthCachesExact(canon); + resp->setBody(Json::object { + { "count", (int) count }, + { "result", "Flushed cache." } + }); +} + +void AuthWebServer::cssfunction(HttpRequest* req, HttpResponse* resp) +{ + resp->headers["Cache-Control"] = "max-age=86400"; + resp->headers["Content-Type"] = "text/css"; + + ostringstream ret; + ret<<"* { box-sizing: border-box; margin: 0; padding: 0; }"<body = ret.str(); + resp->status = 200; +} + +void AuthWebServer::webThread() +{ + try { + setThreadName("pdns/webserver"); + if(::arg().mustDo("api")) { + d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", &apiServerCacheFlush); + d_ws->registerApiHandler("/api/v1/servers/localhost/config", &apiServerConfig); + d_ws->registerApiHandler("/api/v1/servers/localhost/search-data", &apiServerSearchData); + d_ws->registerApiHandler("/api/v1/servers/localhost/statistics", &apiServerStatistics); + d_ws->registerApiHandler("/api/v1/servers/localhost/tsigkeys/", &apiServerTSIGKeyDetail); + d_ws->registerApiHandler("/api/v1/servers/localhost/tsigkeys", &apiServerTSIGKeys); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//axfr-retrieve", &apiServerZoneAxfrRetrieve); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//cryptokeys/", &apiZoneCryptokeys); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//cryptokeys", &apiZoneCryptokeys); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//export", &apiServerZoneExport); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//metadata/", &apiZoneMetadataKind); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//metadata", &apiZoneMetadata); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//notify", &apiServerZoneNotify); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones//rectify", &apiServerZoneRectify); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones/", &apiServerZoneDetail); + d_ws->registerApiHandler("/api/v1/servers/localhost/zones", &apiServerZones); + d_ws->registerApiHandler("/api/v1/servers/localhost", &apiServerDetail); + d_ws->registerApiHandler("/api/v1/servers", &apiServer); + d_ws->registerApiHandler("/api", &apiDiscovery); + } + if (::arg().mustDo("webserver")) { + d_ws->registerWebHandler("/style.css", boost::bind(&AuthWebServer::cssfunction, this, _1, _2)); + d_ws->registerWebHandler("/", boost::bind(&AuthWebServer::indexfunction, this, _1, _2)); + } + d_ws->go(); + } + catch(...) { + g_log< +#include +#include +#include +#include "misc.hh" +#include "namespaces.hh" + +class Ewma +{ +public: + Ewma() : d_last(0), d_10(0), d_5(0), d_1(0), d_max(0){dt.set();} + void submit(int val) + { + int rate=val-d_last; + double difft=dt.udiff()/1000000.0; + dt.set(); + + d_10=((600.0-difft)*d_10+(difft*rate))/600.0; + d_5=((300.0-difft)*d_5+(difft*rate))/300.0; + d_1=((60.0-difft)*d_1+(difft*rate))/60.0; + d_max=max(d_1,d_max); + + d_last=val; + } + double get10() + { + return d_10; + } + double get5() + { + return d_5; + } + double get1() + { + return d_1; + } + double getMax() + { + return d_max; + } +private: + DTime dt; + int d_last; + double d_10, d_5, d_1, d_max; +}; + +class WebServer; +class HttpRequest; +class HttpResponse; + +class AuthWebServer +{ +public: + AuthWebServer(); + void go(); + static string makePercentage(const double& val); + +private: + static void *webThreadHelper(void *); + static void *statThreadHelper(void *p); + void indexfunction(HttpRequest* req, HttpResponse* resp); + void cssfunction(HttpRequest* req, HttpResponse* resp); + void jsonstat(HttpRequest* req, HttpResponse* resp); + void registerApiHandler(const string& url, boost::function handler); + void printvars(ostringstream &ret); + void printargs(ostringstream &ret); + void webThread(); + void statThread(); + pthread_t d_tid; + + time_t d_start; + double d_min10, d_min5, d_min1; + Ewma d_queries, d_cachehits, d_cachemisses; + Ewma d_qcachehits, d_qcachemisses; + WebServer *d_ws{nullptr}; +}; + +#endif diff --git a/pdns/zone2json.cc b/pdns/zone2json.cc new file mode 100644 index 0000000..8a01a21 --- /dev/null +++ b/pdns/zone2json.cc @@ -0,0 +1,241 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* accepts a named.conf or a zone as parameter and outputs heaps of sql */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include +#include +#include "namespaces.hh" + +#include "dns.hh" +#include "arguments.hh" +#include "bindparserclasses.hh" +#include "statbag.hh" +#include "misc.hh" +#include "dnspacket.hh" +#include "zoneparser-tng.hh" +#include "dnsrecords.hh" +#include +#include +#include +#include + +#include "json11.hpp" + +using namespace json11; + +StatBag S; +static int g_numRecords; + +static Json::object emitRecord(const string& zoneName, const DNSName &DNSqname, const string &qtype, const string &ocontent, int ttl) +{ + int prio=0; + string retval; + g_numRecords++; + string content(ocontent); + if(qtype == "MX" || qtype == "SRV") { + prio=pdns_stou(content); + + string::size_type pos = content.find_first_not_of("0123456789"); + if(pos != string::npos) + boost::erase_head(content, pos); + trim_left(content); + } + + Json::object dict; + + dict["name"] = DNSqname.toString(); + dict["type"] = qtype; + dict["ttl"] = ttl; + dict["prio"] = prio; + dict["content"] = content; + + return dict; +} + +/* 2 modes of operation, either --named or --zone (the latter needs $ORIGIN) + 2 further modes: --mysql or --oracle +*/ + +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} + + +int main(int argc, char **argv) +try +{ + vector lines; + + reportAllTypes(); + std::ios_base::sync_with_stdio(false); + + ::arg().setSwitch("verbose","Verbose comments on operation")="no"; + ::arg().setSwitch("on-error-resume-next","Continue after errors")="no"; + ::arg().set("zone","Zonefile to parse")=""; + ::arg().set("zone-name","Specify an $ORIGIN in case it is not present")=""; + ::arg().set("named-conf","Bind 8/9 named.conf to parse")=""; + + ::arg().set("soa-minimum-ttl","Do not change")="0"; + ::arg().set("soa-refresh-default","Do not change")="0"; + ::arg().set("soa-retry-default","Do not change")="0"; + ::arg().set("soa-expire-default","Do not change")="0"; + + ::arg().setCmd("help","Provide a helpful message"); + ::arg().setCmd("version","Print the version"); + + S.declare("logmessages"); + + string namedfile=""; + string zonefile=""; + + ::arg().parse(argc, argv); + + if(::arg().mustDo("version")){ + cerr<<"zone2json "< domains=BP.getDomains(); + struct stat st; + for(vector::iterator i=domains.begin(); i!=domains.end(); ++i) { + if(stat(i->filename.c_str(), &st) == 0) { + i->d_dev = st.st_dev; + i->d_ino = st.st_ino; + } + } + + sort(domains.begin(), domains.end()); // put stuff in inode order + + int numdomains=domains.size(); + int tick=numdomains/100; + cout << "["; + + for(vector::const_iterator i=domains.begin(); + i!=domains.end(); + ++i) + { + if(i->type!="master" && i->type!="slave") { + cerr<<" Warning! Skipping '"<type<<"' zone '"<name<<"'"<filename, i->name, BP.getDirectory()); + DNSResourceRecord rr; + obj["name"] = i->name.toString(); + + while(zpt.get(rr)) + recs.push_back(emitRecord(i->name.toString(), rr.qname, rr.qtype.getName(), rr.content, rr.ttl)); + obj["records"] = recs; + Json tmp = obj; + cout<filename<<")\033\133\113"; + } + cout << "]" << endl; + cerr<<"\r100% done\033\133\113"< +#include +#include +#include +#include +#include "arguments.hh" +#include "bindparserclasses.hh" +#include "statbag.hh" +#include +#include "dnsrecords.hh" +#include "misc.hh" +#include "dns.hh" +#include "zoneparser-tng.hh" + +using std::map; +using std::string; +using std::vector; + +StatBag S; +ArgvMap args; +bool g_dnsttl; +bool g_pdnsinfo; +unsigned int g_domainid; +string g_basedn; +string g_metadatadn; +DNSName g_zonename; +map g_objects; +map g_entries; +map g_recorddata; +map > g_recordttl; + +std::string encode_non_ascii( const std::string &input ) { + std::ostringstream out; + + for ( auto i : input ) { + if ( (unsigned char)i > 0x7F ) + out << '\\' << int( (unsigned char)i ); + else + out << i; + } + + return out.str(); +} + +static void callback_simple( unsigned int domain_id, const DNSName &domain, const string &qtype, const string &content, int ttl ) +{ + DNSName host; + + if( ! domain.isPartOf(g_zonename) ) + { + cerr << "Domain '" << domain << "'' not part of '" << g_zonename << "'"<< endl; + return; + } + + host = domain.makeRelative(g_zonename); + + if( g_pdnsinfo && qtype == "SOA" ) { + cout << "dn: ou=" << domain << "," << g_metadatadn << endl; + cout << "changetype: add" << endl; + cout << "objectclass: organizationalUnit" << endl; + cout << "ou: " << domain.toStringNoDot() << endl; + cout << endl; + } + + std::string stripped=stripDot(content); + std::string rrvalue = stripped + ((stripped.empty() || stripped[stripped.size()-1]==' ') ? "." : ""); + std::string dn = "dc="; + if( host.countLabels() ) { dn += host.toStringNoDot() + ",dc="; } + dn += g_zonename.toStringNoDot() + "," + g_basedn; + cout << "dn: " << dn << endl; + + if( host.countLabels() == 0 ) { host = g_zonename; } + + if( !g_entries[dn] ) + { + g_entries[dn] = true; + g_recorddata[domain] = true; + + cout << "changetype: add" << endl; + cout << "objectclass: dnsdomain2" << endl; + cout << "objectclass: domainrelatedobject" << endl; + cout << "objectclass: PdnsRecordData" << endl; + if( g_pdnsinfo && qtype == "SOA" ) { + cout << "objectclass: PdnsDomain" << endl; + cout << "PdnsDomainId: " << domain_id << endl; + } + cout << "dc: " << host.toStringNoDot() << endl; + if( g_dnsttl ) { cout << "dnsttl: " << ttl << endl; } + cout << "associateddomain: " << domain.toStringNoDot() << endl; + } + else + { + cout << "changetype: modify" << endl; + if ( !g_recorddata[domain] ) { + g_recorddata[domain] = true; + cout << "add: objectClass" << endl; + cout << "objectClass: PdnsRecordData" << endl; + cout << "-" << endl; + } + if ( !g_recordttl.count( domain ) || !g_recordttl[domain].count( qtype ) ) { + g_recordttl[domain][qtype] = true; + cout << "add: PdnsRecordTTL" << endl; + cout << "PdnsRecordTTL: " << qtype << "|" << ttl << endl; + cout << "-" << endl; + } + cout << "add: " << qtype << "Record" << endl; + } + cout << qtype << "Record: " << rrvalue << endl << endl; +} + + + +static void callback_tree( unsigned int domain_id, const DNSName &domain, const string &qtype, const string &content, int ttl ) +{ + unsigned int i; + string dn; + DNSName net; + vector parts; + + stringtok( parts, domain.toStringNoDot(), "." ); + if( parts.empty() ) { return; } + + for( i = parts.size() - 1; i > 0; i-- ) + { + net.prependRawLabel(parts[i]); + dn = "dc=" + parts[i] + "," + dn; + + if( !g_objects[net] ) + { + g_objects[net] = true; + + cout << "dn: " << dn << g_basedn << endl; + cout << "changetype: add" << endl; + cout << "objectclass: dnsdomain2" << endl; + cout << "objectclass: domainrelatedobject" << endl; + cout << "dc: " << parts[i] << endl; + cout << "associateddomain: " << net.toStringNoDot() << endl << endl; + } + + } + + if( g_pdnsinfo && qtype == "SOA" ) { + cout << "dn: ou=" << domain << "," << g_metadatadn << endl; + cout << "changetype: add" << endl; + cout << "objectclass: organizationalUnit" << endl; + cout << "ou: " << domain.toStringNoDot() << endl; + cout << endl; + } + + std::string stripped=stripDot(content); + std::string rrvalue = stripped + ((stripped.empty() || stripped[stripped.size()-1]==' ') ? "." : ""); + cout << "dn: " << "dc=" << parts[0] << "," << dn << g_basedn << endl; + + if( !g_objects[domain] ) + { + g_objects[domain] = true; + g_recorddata[domain] = true; + + cout << "changetype: add" << endl; + cout << "objectclass: dnsdomain2" << endl; + cout << "objectclass: domainrelatedobject" << endl; + cout << "objectclass: PdnsRecordData" << endl; + if( g_pdnsinfo && qtype == "SOA" ) { + cout << "objectclass: PdnsDomain" << endl; + cout << "PdnsDomainId: " << domain_id << endl; + } + cout << "dc: " << parts[0] << endl; + if( g_dnsttl ) { cout << "dnsttl: " << ttl << endl; } + cout << "associateddomain: " << domain.toStringNoDot() << endl; + } + else + { + cout << "changetype: modify" << endl; + if( g_pdnsinfo && qtype == "SOA" ) { + cout << "add: objectclass" << endl; + cout << "objectclass: PdnsDomain" << endl; + cout << "-" << endl; + cout << "add: PdnsDomainId" << endl; + cout << "PdnsDomainId: " << domain_id << endl; + cout << "-" << endl; + } + if ( !g_recorddata[domain] ) { + g_recorddata[domain] = true; + cout << "add: objectClass" << endl; + cout << "objectClass: PdnsRecordData" << endl; + cout << "-" << endl; + } + if ( !g_recordttl.count( domain ) || !g_recordttl[domain].count( qtype ) ) { + g_recordttl[domain][qtype] = true; + cout << "add: PdnsRecordTTL" << endl; + cout << "PdnsRecordTTL: " << qtype << "|" << ttl << endl; + cout << "-" << endl; + } + cout << "add: " << qtype << "Record" << endl; + } + cout << qtype << "Record: " << rrvalue << endl << endl; +} + + + +int main( int argc, char* argv[] ) +{ + BindParser BP; + vector parts; + + + try + { + std::ios_base::sync_with_stdio( false ); + reportAllTypes(); + args.setCmd( "help", "Provide a helpful message" ); + args.setCmd( "version", "Print the version" ); + args.setSwitch( "verbose", "Verbose comments on operation" ) = "no"; + args.setSwitch( "resume", "Continue after errors" ) = "no"; + args.setSwitch( "dnsttl", "Add dnsttl attribute to every entry" ) = "no"; + args.setSwitch( "pdns-info", "Add the PDNS domain info attributes (this mandates setting --metadata-dn)" ) = "no"; + args.set( "named-conf", "Bind 8 named.conf to parse" ) = ""; + args.set( "zone-file", "Zone file to parse" ) = ""; + args.set( "zone-name", "Specify a zone name if zone is set" ) = ""; + args.set( "basedn", "Base DN to store objects below" ) = "ou=hosts,o=mycompany,c=de"; + args.set( "layout", "How to arrange entries in the directory (simple or as tree)" ) = "simple"; + args.set( "domainid", "Domain ID of the first domain found (incremented afterwards)" ) = "1"; + args.set( "metadata-dn", "DN under which to store the domain metadata" ) = ""; + + args.parse( argc, argv ); + + if(args.mustDo("version")) { + cerr<<"zone2ldap "< callback_t; + callback_t callback = callback_simple; + if( args["layout"] == "tree" ) + { + callback=callback_tree; + } + + if ( args.mustDo( "pdns-info" ) ) { + g_pdnsinfo = true; + if( args["metadata-dn"].empty() ) { + cerr << "You must set --metadata-dn when using --pdns-info" << endl; + exit( 1 ); + } + g_metadatadn = args["metadata-dn"]; + } + else { + g_pdnsinfo = false; + } + + if ( !args["domainid"].empty() ) + g_domainid = pdns_stou( args["domainid"] ); + else + g_domainid = 1; + + if( !args["named-conf"].empty() ) + { + BP.setVerbose( args.mustDo( "verbose" ) ); + BP.parse( args["named-conf"] ); +// ZP.setDirectory( BP.getDirectory() ); + const vector &domains = BP.getDomains(); + + for(const auto& i: domains) + { + if(i.type!="master" && i.type!="slave") { + cerr<<" Warning! Skipping '"< +#include +#include + +#include +#include +#include "json11.hpp" +#include "namespaces.hh" +#include "dns.hh" +#include "arguments.hh" +#include "bindparserclasses.hh" +#include "statbag.hh" +#include "misc.hh" +#include "dnspacket.hh" +#include "zoneparser-tng.hh" +#include "dnsrecords.hh" +#include +#include +#include +#include + + + +StatBag S; + +enum dbmode_t {MYSQL, GORACLE, POSTGRES, SQLITE, MYDNS, ORACLE}; +static dbmode_t g_mode; +static bool g_intransaction; +static int g_numRecords; + + +/* this is an official wart. We don't terminate domains on a . in PowerDNS, + which is fine as it goes, except for encoding the root, it would end up as '', + which leads to ambiguities in the content field. Therefore, if we encounter + the root as a . in a BIND zone, we leave it as a ., and don't replace it by + an empty string. Back in 1999 we made the wrong choice. */ + +static string stripDotContent(const string& content) +{ + if(boost::ends_with(content, " .") || content==".") + return content; + return stripDot(content); +} + +static string sqlstr(const string &name) +{ + if(g_mode == SQLITE || g_mode==GORACLE || g_mode==ORACLE) + return "'"+boost::replace_all_copy(name, "'", "''")+"'"; + + string a; + + for(string::const_iterator i=name.begin();i!=name.end();++i) { + if(*i=='\'' || *i=='\\'){ + a+='\\'; + a+=*i; + } + else + a+=*i; + } + if(g_mode == POSTGRES) + return "E'"+a+"'"; + else + return "'"+a+"'"; +} + +static void startNewTransaction() +{ + if(!::arg().mustDo("transactions")) + return; + + if(g_intransaction) { + if(g_mode==POSTGRES) { + cout<<"COMMIT WORK;"< *masters = 0) { + string iDomain = domain.toStringRootDot(); + if(!::arg().mustDo("slave")) { + if(g_mode==POSTGRES || g_mode==MYSQL || g_mode==SQLITE) { + cout<<"insert into domains (name,type) values ("<empty()) { + for(const auto& mstr : *masters) { + mstrs.append(mstr.toStringWithPortExcept(53)); + mstrs.append(1, ' '); + } + } + if (mstrs.empty()) + cout<<"insert into domains (name,type) values ("< parts; + stringtok(parts, content); + + cout<<"INSERT INTO soa(origin, ns, mbox, serial, refresh, retry, expire, minimum, ttl) VALUES("<< + sqlstr(toLower(zoneNameDot))<<", "< domains=BP.getDomains(); + struct stat st; + for(vector::iterator i=domains.begin(); i!=domains.end(); ++i) { + if(stat(i->filename.c_str(), &st) == 0) { + i->d_dev = st.st_dev; + i->d_ino = st.st_ino; + } + } + + sort(domains.begin(), domains.end()); // put stuff in inode order + + int numdomains=domains.size(); + int tick=numdomains/100; + + for(vector::const_iterator i=domains.begin(); + i!=domains.end(); + ++i) + { + if(i->type!="master" && i->type!="slave") { + cerr<<" Warning! Skipping '"<type<<"' zone '"<name<<"'"<name, &(i->masters)); + + ZoneParserTNG zpt(i->filename, i->name, BP.getDirectory()); + DNSResourceRecord rr; + bool seenSOA=false; + string comment; + while(zpt.get(rr, &comment)) { + if(filterDupSOA && seenSOA && rr.qtype.getCode() == QType::SOA) + continue; + if(rr.qtype.getCode() == QType::SOA) + seenSOA=true; + + emitRecord(i->name, rr.qname, rr.qtype.getName(), rr.content, rr.ttl, comment); + } + num_domainsdone++; + } + catch(std::exception &ae) { + if(!::arg().mustDo("on-error-resume-next")) + throw; + else + cerr<filename<<")\033\133\113"; + } + cerr<<"\r100% done\033\133\113"< +#include "dns.hh" +#include "zoneparser-tng.hh" +#include +#include +#include + +static string g_INstr("IN"); + +ZoneParserTNG::ZoneParserTNG(const string& fname, const DNSName& zname, const string& reldir) : d_reldir(reldir), + d_zonename(zname), d_defaultttl(3600), + d_templatecounter(0), d_templatestop(0), + d_templatestep(0), d_havedollarttl(false){ + stackFile(fname); +} + +ZoneParserTNG::ZoneParserTNG(const vector zonedata, const DNSName& zname): + d_zonename(zname), d_zonedata(zonedata), d_defaultttl(3600), + d_templatecounter(0), d_templatestop(0), d_templatestep(0), + d_havedollarttl(false), d_fromfile(false) +{ + d_zonedataline = d_zonedata.begin(); +} + +void ZoneParserTNG::stackFile(const std::string& fname) +{ + FILE *fp=fopen(fname.c_str(), "r"); + if(!fp) { + std::error_code ec (errno,std::generic_category()); + throw std::system_error(ec, "Unable to open file '"+fname+"': "+stringerror()); + } + + filestate fs(fp, fname); + d_filestates.push(fs); + d_fromfile = true; +} + +ZoneParserTNG::~ZoneParserTNG() +{ + while(!d_filestates.empty()) { + fclose(d_filestates.top().d_fp); + d_filestates.pop(); + } +} + +static string makeString(const string& line, const pair& range) +{ + return string(line.c_str() + range.first, range.second - range.first); +} + +static bool isTimeSpec(const string& nextpart) +{ + if(nextpart.empty()) + return false; + for(string::const_iterator iter = nextpart.begin(); iter != nextpart.end(); ++iter) { + if(isdigit(*iter)) + continue; + if(iter+1 != nextpart.end()) + return false; + char c=tolower(*iter); + return (c=='s' || c=='m' || c=='h' || c=='d' || c=='w' || c=='y'); + } + return true; +} + + +unsigned int ZoneParserTNG::makeTTLFromZone(const string& str) +{ + if(str.empty()) + return 0; + + unsigned int val; + try { + val=pdns_stou(str); + } + catch (const std::out_of_range& oor) { + throw PDNSException("Unable to parse time specification '"+str+"' "+getLineOfFile()); + } + + char lc=dns_tolower(str[str.length()-1]); + if(!isdigit(lc)) + switch(lc) { + case 's': + break; + case 'm': + val*=60; // minutes, not months! + break; + case 'h': + val*=3600; + break; + case 'd': + val*=3600*24; + break; + case 'w': + val*=3600*24*7; + break; + case 'y': // ? :-) + val*=3600*24*365; + break; + + default: + throw PDNSException("Unable to parse time specification '"+str+"' "+getLineOfFile()); + } + return val; +} + +bool ZoneParserTNG::getTemplateLine() +{ + if(d_templateparts.empty() || d_templatecounter > d_templatestop) // no template, or done with + return false; + + string retline; + for(parts_t::const_iterator iter = d_templateparts.begin() ; iter != d_templateparts.end(); ++iter) { + if(iter != d_templateparts.begin()) + retline+=" "; + + string part=makeString(d_templateline, *iter); + + /* a part can contain a 'naked' $, an escaped $ (\$), or ${offset,width,radix}, with width defaulting to 0, + and radix being 'd', 'o', 'x' or 'X', defaulting to 'd'. + + The width is zero-padded, so if the counter is at 1, the offset is 15, with is 3, and the radix is 'x', + output will be '010', from the input of ${15,3,x} + */ + + string outpart; + outpart.reserve(part.size()+5); + bool inescape=false; + + for(string::size_type pos = 0; pos < part.size() ; ++pos) { + char c=part[pos]; + if(inescape) { + outpart.append(1, c); + inescape=false; + continue; + } + + if(part[pos]=='\\') { + inescape=true; + continue; + } + if(c=='$') { + if(pos + 1 == part.size() || part[pos+1]!='{') { // a trailing $, or not followed by { + outpart.append(std::to_string(d_templatecounter)); + continue; + } + + // need to deal with { case + + pos+=2; + string::size_type startPos=pos; + for(; pos < part.size() && part[pos]!='}' ; ++pos) + ; + + if(pos == part.size()) // partial spec + break; + + // we are on the '}' + + string spec(part.c_str() + startPos, part.c_str() + pos); + int offset=0, width=0; + char radix='d'; + sscanf(spec.c_str(), "%d,%d,%c", &offset, &width, &radix); // parse format specifier + + char sformat[12]; + snprintf(sformat, sizeof(sformat), "%%0%d%c", width, radix); // make into printf-style format + + char tmp[80]; + snprintf(tmp, sizeof(tmp), sformat, d_templatecounter + offset); // and do the actual printing + outpart+=tmp; + } + else + outpart.append(1, c); + } + retline+=outpart; + } + d_templatecounter+=d_templatestep; + + d_line = retline; + return true; +} + +void chopComment(string& line) +{ + if(line.find(';')==string::npos) + return; + string::size_type pos, len = line.length(); + bool inQuote=false; + for(pos = 0 ; pos < len; ++pos) { + if(line[pos]=='\\') + pos++; + else if(line[pos]=='"') + inQuote=!inQuote; + else if(line[pos]==';' && !inQuote) + break; + } + if(pos != len) + line.resize(pos); +} + +bool findAndElide(string& line, char c) +{ + string::size_type pos, len = line.length(); + bool inQuote=false; + for(pos = 0 ; pos < len; ++pos) { + if(line[pos]=='\\') + pos++; + else if(line[pos]=='"') + inQuote=!inQuote; + else if(line[pos]==c && !inQuote) + break; + } + if(pos != len) { + line.erase(pos, 1); + return true; + } + return false; +} + +DNSName ZoneParserTNG::getZoneName() +{ + return d_zonename; +} + +string ZoneParserTNG::getLineOfFile() +{ + if (d_zonedata.size() > 0) + return "on line "+std::to_string(std::distance(d_zonedata.begin(), d_zonedataline))+" of given string"; + + if (d_filestates.empty()) + return ""; + + return "on line "+std::to_string(d_filestates.top().d_lineno)+" of file '"+d_filestates.top().d_filename+"'"; +} + +pair ZoneParserTNG::getLineNumAndFile() +{ + if (d_filestates.empty()) + return {"", 0}; + else + return {d_filestates.top().d_filename, d_filestates.top().d_lineno}; +} + +bool ZoneParserTNG::get(DNSResourceRecord& rr, std::string* comment) +{ + retry:; + if(!getTemplateLine() && !getLine()) + return false; + + boost::trim_right_if(d_line, is_any_of(" \t\r\n\x1a")); + if(comment) + comment->clear(); + if(comment && d_line.find(';') != string::npos) + *comment = d_line.substr(d_line.find(';')); + parts_t parts; + vstringtok(parts, d_line); + + if(parts.empty()) + goto retry; + + if(parts[0].first != parts[0].second && d_line[parts[0].first]==';') // line consisting of nothing but comments + goto retry; + + if(d_line[0]=='$') { + string command=makeString(d_line, parts[0]); + if(pdns_iequals(command,"$TTL") && parts.size() > 1) { + d_defaultttl=makeTTLFromZone(trim_right_copy_if(makeString(d_line, parts[1]), is_any_of(";"))); + d_havedollarttl=true; + } + else if(pdns_iequals(command,"$INCLUDE") && parts.size() > 1 && d_fromfile) { + string fname=unquotify(makeString(d_line, parts[1])); + if(!fname.empty() && fname[0]!='/' && !d_reldir.empty()) + fname=d_reldir+"/"+fname; + stackFile(fname); + } + else if(pdns_iequals(command, "$ORIGIN") && parts.size() > 1) { + d_zonename = DNSName(makeString(d_line, parts[1])); + } + else if(pdns_iequals(command, "$GENERATE") && parts.size() > 2) { + // $GENERATE 1-127 $ CNAME $.0 + string range=makeString(d_line, parts[1]); + d_templatestep=1; + d_templatestop=0; + sscanf(range.c_str(),"%u-%u/%u", &d_templatecounter, &d_templatestop, &d_templatestep); + if (d_templatestep < 1 || + d_templatestop < d_templatecounter) { + throw exception("Illegal $GENERATE parameters"); + } + d_templateline=d_line; + parts.pop_front(); + parts.pop_front(); + + d_templateparts=parts; + goto retry; + } + else + throw exception("Can't parse zone line '"+d_line+"' "+getLineOfFile()); + goto retry; + } + + bool prevqname=false; + string qname = makeString(d_line, parts[0]); // Don't use DNSName here! + if(dns_isspace(d_line[0])) { + rr.qname=d_prevqname; + prevqname=true; + }else { + rr.qname=DNSName(qname); + parts.pop_front(); + if(qname.empty() || qname[0]==';') + goto retry; + } + if(qname=="@") + rr.qname=d_zonename; + else if(!prevqname && !isCanonical(qname)) + rr.qname += d_zonename; + d_prevqname=rr.qname; + + if(parts.empty()) + throw exception("Line with too little parts "+getLineOfFile()); + + string nextpart; + + rr.ttl=d_defaultttl; + bool haveTTL=0, haveQTYPE=0; + pair range; + + while(!parts.empty()) { + range=parts.front(); + parts.pop_front(); + nextpart=makeString(d_line, range); + if(nextpart.empty()) + break; + + if(nextpart.find(';')!=string::npos) { + break; + } + + // cout<<"Next part: '"< recparts; + switch(rr.qtype.getCode()) { + case QType::MX: + stringtok(recparts, rr.content); + if(recparts.size()==2) { + if (recparts[1]!=".") { + try { + recparts[1] = toCanonic(d_zonename, recparts[1]).toStringRootDot(); + } catch (std::exception &e) { + throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); + } + } + rr.content=recparts[0]+" "+recparts[1]; + } + break; + + case QType::RP: + stringtok(recparts, rr.content); + if(recparts.size()==2) { + recparts[0] = toCanonic(d_zonename, recparts[0]).toStringRootDot(); + recparts[1] = toCanonic(d_zonename, recparts[1]).toStringRootDot(); + rr.content=recparts[0]+" "+recparts[1]; + } + break; + + case QType::SRV: + stringtok(recparts, rr.content); + if(recparts.size()==4) { + if(recparts[3]!=".") { + try { + recparts[3] = toCanonic(d_zonename, recparts[3]).toStringRootDot(); + } catch (std::exception &e) { + throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); + } + } + rr.content=recparts[0]+" "+recparts[1]+" "+recparts[2]+" "+recparts[3]; + } + break; + + + case QType::NS: + case QType::CNAME: + case QType::DNAME: + case QType::PTR: + try { + rr.content = toCanonic(d_zonename, rr.content).toStringRootDot(); + } catch (std::exception &e) { + throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); + } + break; + case QType::AFSDB: + stringtok(recparts, rr.content); + if(recparts.size() == 2) { + try { + recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot(); + } catch (std::exception &e) { + throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); + } + } else { + throw PDNSException("AFSDB record for "+rr.qname.toLogString()+" invalid"); + } + rr.content.clear(); + for(string::size_type n = 0; n < recparts.size(); ++n) { + if(n) + rr.content.append(1,' '); + + rr.content+=recparts[n]; + } + break; + case QType::SOA: + stringtok(recparts, rr.content); + if(recparts.size() > 7) + throw PDNSException("SOA record contents for "+rr.qname.toLogString()+" contains too many parts"); + if(recparts.size() > 1) { + try { + recparts[0]=toCanonic(d_zonename, recparts[0]).toStringRootDot(); + recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot(); + } catch (std::exception &e) { + throw PDNSException("Error in record '" + rr.qname.toLogString() + " " + rr.qtype.getName() + "': " + e.what()); + } + } + rr.content.clear(); + for(string::size_type n = 0; n < recparts.size(); ++n) { + if(n) + rr.content.append(1,' '); + + if(n > 1) + rr.content+=std::to_string(makeTTLFromZone(recparts[n])); + else + rr.content+=recparts[n]; + } + break; + default:; + } + return true; +} + + +bool ZoneParserTNG::getLine() +{ + if (d_zonedata.size() > 0) { + if (d_zonedataline != d_zonedata.end()) { + d_line = *d_zonedataline; + ++d_zonedataline; + return true; + } + return false; + } + while(!d_filestates.empty()) { + if(stringfgets(d_filestates.top().d_fp, d_line)) { + d_filestates.top().d_lineno++; + return true; + } + fclose(d_filestates.top().d_fp); + d_filestates.pop(); + } + return false; +} diff --git a/pdns/zoneparser-tng.hh b/pdns/zoneparser-tng.hh new file mode 100644 index 0000000..36d58f9 --- /dev/null +++ b/pdns/zoneparser-tng.hh @@ -0,0 +1,72 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef PDNS_ZONEPARSER_TNG +#define PDNS_ZONEPARSER_TNG +#include +#include +#include +#include + +#include "namespaces.hh" + +class ZoneParserTNG +{ +public: + ZoneParserTNG(const string& fname, const DNSName& zname=DNSName("."), const string& reldir=""); + ZoneParserTNG(const vector zonedata, const DNSName& zname); + + ~ZoneParserTNG(); + bool get(DNSResourceRecord& rr, std::string* comment=0); + typedef runtime_error exception; + typedef deque > parts_t; + DNSName getZoneName(); + string getLineOfFile(); // for error reporting purposes + pair getLineNumAndFile(); // idem +private: + bool getLine(); + bool getTemplateLine(); + void stackFile(const std::string& fname); + unsigned makeTTLFromZone(const std::string& str); + + struct filestate { + filestate(FILE* fp, string filename) : d_fp(fp), d_filename(filename), d_lineno(0){} + FILE *d_fp; + string d_filename; + int d_lineno; + }; + + string d_reldir; + string d_line; + DNSName d_prevqname; + DNSName d_zonename; + string d_templateline; + vector d_zonedata; + vector::iterator d_zonedataline; + std::stack d_filestates; + parts_t d_templateparts; + int d_defaultttl; + uint32_t d_templatecounter, d_templatestop, d_templatestep; + bool d_havedollarttl; + bool d_fromfile; +}; + +#endif diff --git a/regression-tests/zones/unit.test b/regression-tests/zones/unit.test new file mode 100644 index 0000000..b72acfc --- /dev/null +++ b/regression-tests/zones/unit.test @@ -0,0 +1,10 @@ +unit.test. 300 IN SOA ns.unit.test. hostmaster.unit.test. 1 3600 1200 604800 300 +unit.test. 300 IN NS ns.unit.test. +unit.test. 300 IN MX 30 mx.unit.test. +unit.test. 300 IN A 1.2.3.4 +root.mx.unit.test. 300 IN MX 20 . +root.srv.unit.test. 300 IN SRV 10 10 5060 . +naptr-a.unit.test. 300 IN NAPTR 100 10 "" "" "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i" . +naptr-b.unit.test. 300 IN NAPTR 100 50 "s" "http+I2L+I2C+I2R" "" _http._tcp.rec.test. +unit.test. 300 IN SOA ns.unit.test. hostmaster.unit.test. 1 3600 1200 604800 300 +unit.test. 300 IN AFSDB 1 afsdb.unit.test. -- 2.30.2