From f1fcec3d45b48d586a2d1e0ced25c8f16b63d04e Mon Sep 17 00:00:00 2001 From: Nathan Freitas Date: Mon, 4 Jan 2016 01:38:36 -0500 Subject: [PATCH] add support for PDNSD DNS Daemon for VPN DNS resolution Tor's DNS port doesn't work well with the VPN mode, so we will use PDSND to resolve DNS over Tor using OpenDNS. This is a hack/solution that we learned from SocksDroid. --- external/Makefile | 4 + jni/Android.mk | 14 + jni/Application.mk | 2 +- jni/pdnsd/AUTHORS | 58 + jni/pdnsd/COPYING | 674 + jni/pdnsd/COPYING.BSD | 26 + jni/pdnsd/ChangeLog | 3304 +++++ jni/pdnsd/ChangeLog.old | 161 + jni/pdnsd/INSTALL | 190 + jni/pdnsd/Makefile.am | 40 + jni/pdnsd/Makefile.in | 734 + jni/pdnsd/NEWS | 324 + jni/pdnsd/PKGBUILD.in | 24 + jni/pdnsd/README | 22 + jni/pdnsd/README.par | 216 + jni/pdnsd/README.par.old | 249 + jni/pdnsd/THANKS | 66 + jni/pdnsd/TODO | 20 + jni/pdnsd/acconfig.h | 191 + jni/pdnsd/aclocal.m4 | 1021 ++ jni/pdnsd/compile | 142 + jni/pdnsd/config.h | 437 + jni/pdnsd/config.h.in | 430 + jni/pdnsd/configure | 11389 ++++++++++++++++ jni/pdnsd/configure.in | 548 + jni/pdnsd/contrib/Makefile.am | 2 + jni/pdnsd/contrib/Makefile.in | 323 + jni/pdnsd/contrib/README | 30 + jni/pdnsd/contrib/change_pdnsd_server_ip.pl | 124 + jni/pdnsd/contrib/dhcp2pdnsd | 45 + jni/pdnsd/contrib/pdnsd_dhcp.pl | 246 + jni/pdnsd/depcomp | 530 + jni/pdnsd/doc/Makefile.am | 28 + jni/pdnsd/doc/Makefile.in | 483 + jni/pdnsd/doc/doc_makefile | 38 + jni/pdnsd/doc/html/dl.html | 96 + jni/pdnsd/doc/html/dl.html.in | 96 + jni/pdnsd/doc/html/doc.html | 2630 ++++ jni/pdnsd/doc/html/doc_makefile | 23 + jni/pdnsd/doc/html/faq.html | 412 + jni/pdnsd/doc/html/htmlsubst.pl | 36 + jni/pdnsd/doc/html/index.html | 686 + jni/pdnsd/doc/html2confman.pl | 161 + jni/pdnsd/doc/pdnsd-ctl.8 | 198 + jni/pdnsd/doc/pdnsd.8.in | 326 + jni/pdnsd/doc/pdnsd.conf.5.in | 1328 ++ jni/pdnsd/doc/pdnsd.conf.in | 143 + jni/pdnsd/doc/txt/doc_makefile | 21 + jni/pdnsd/doc/txt/faq.txt | 227 + jni/pdnsd/doc/txt/intro.txt | 305 + jni/pdnsd/doc/txt/manual.txt | 2017 +++ jni/pdnsd/file-list.base.in | 5 + jni/pdnsd/install-sh | 323 + jni/pdnsd/missing | 360 + jni/pdnsd/pdnsd.spec.in | 244 + jni/pdnsd/src/Makefile.am | 24 + jni/pdnsd/src/Makefile.in | 921 ++ jni/pdnsd/src/cache.c | 2723 ++++ jni/pdnsd/src/cache.h | 306 + jni/pdnsd/src/conf-keywords.h | 238 + jni/pdnsd/src/conf-parser.c | 2118 +++ jni/pdnsd/src/conf-parser.h | 29 + jni/pdnsd/src/conff.c | 544 + jni/pdnsd/src/conff.h | 190 + jni/pdnsd/src/consts.c | 133 + jni/pdnsd/src/consts.h | 69 + jni/pdnsd/src/debug.c | 64 + jni/pdnsd/src/debug.h | 52 + jni/pdnsd/src/dns.c | 617 + jni/pdnsd/src/dns.h | 309 + jni/pdnsd/src/dns_answer.c | 2170 +++ jni/pdnsd/src/dns_answer.h | 40 + jni/pdnsd/src/dns_query.c | 3798 ++++++ jni/pdnsd/src/dns_query.h | 51 + jni/pdnsd/src/error.c | 142 + jni/pdnsd/src/error.h | 115 + jni/pdnsd/src/freebsd_netinet_ip_icmp.h | 187 + jni/pdnsd/src/hash.c | 322 + jni/pdnsd/src/hash.h | 83 + jni/pdnsd/src/helpers.c | 795 ++ jni/pdnsd/src/helpers.h | 319 + jni/pdnsd/src/icmp.c | 544 + jni/pdnsd/src/icmp.h | 43 + jni/pdnsd/src/ipvers.h | 297 + jni/pdnsd/src/list.c | 171 + jni/pdnsd/src/list.h | 170 + jni/pdnsd/src/main.c | 710 + jni/pdnsd/src/make_rr_types_h.pl | 309 + jni/pdnsd/src/netdev.c | 363 + jni/pdnsd/src/netdev.h | 32 + jni/pdnsd/src/pdnsd-ctl/Makefile.am | 18 + jni/pdnsd/src/pdnsd-ctl/Makefile.in | 470 + jni/pdnsd/src/pdnsd-ctl/pdnsd-ctl.c | 799 ++ jni/pdnsd/src/pdnsd_assert.h | 51 + jni/pdnsd/src/rc/ArchLinux/Makefile.am | 7 + jni/pdnsd/src/rc/ArchLinux/Makefile.in | 332 + jni/pdnsd/src/rc/ArchLinux/pdnsd.in | 45 + jni/pdnsd/src/rc/Debian/Makefile.am | 8 + jni/pdnsd/src/rc/Debian/Makefile.in | 334 + jni/pdnsd/src/rc/Debian/pdnsd.in | 52 + jni/pdnsd/src/rc/Makefile.am | 5 + jni/pdnsd/src/rc/Makefile.in | 526 + jni/pdnsd/src/rc/README | 104 + jni/pdnsd/src/rc/RedHat/Makefile.am | 12 + jni/pdnsd/src/rc/RedHat/Makefile.in | 337 + jni/pdnsd/src/rc/RedHat/pdnsd.in | 88 + jni/pdnsd/src/rc/Slackware/Makefile.am | 3 + jni/pdnsd/src/rc/Slackware/Makefile.in | 330 + jni/pdnsd/src/rc/Slackware/rc.pdnsd.in | 74 + jni/pdnsd/src/rc/SuSE/Makefile.am | 22 + jni/pdnsd/src/rc/SuSE/Makefile.in | 345 + jni/pdnsd/src/rc/SuSE/pdnsd.in | 68 + jni/pdnsd/src/rr_types.c | 172 + jni/pdnsd/src/rr_types.h | 536 + jni/pdnsd/src/rr_types.in | 99 + jni/pdnsd/src/servers.c | 856 ++ jni/pdnsd/src/servers.h | 68 + jni/pdnsd/src/sort_namevalues.pl | 25 + jni/pdnsd/src/status.c | 824 ++ jni/pdnsd/src/status.h | 59 + jni/pdnsd/src/test/Makefile.am | 35 + jni/pdnsd/src/test/Makefile.in | 464 + jni/pdnsd/src/test/if_up.c | 36 + jni/pdnsd/src/test/is_local_addr.c | 57 + jni/pdnsd/src/test/random.c | 33 + jni/pdnsd/src/test/tping.c | 59 + jni/pdnsd/src/thread.c | 85 + jni/pdnsd/src/thread.h | 143 + jni/pdnsd/version | 1 + libs/arm64-v8a/libtun2socks.so | Bin 200432 -> 200432 bytes libs/arm64-v8a/pdnsd | Bin 0 -> 202752 bytes libs/armeabi-v7a/libtun2socks.so | Bin 121308 -> 121308 bytes libs/armeabi-v7a/pdnsd | Bin 0 -> 153252 bytes libs/armeabi/libtun2socks.so | Bin 0 -> 129492 bytes libs/armeabi/pdnsd | Bin 0 -> 161312 bytes libs/mips/libtun2socks.so | Bin 284032 -> 284000 bytes libs/mips/pdnsd | Bin 0 -> 334632 bytes libs/x86/libtun2socks.so | Bin 211356 -> 215452 bytes libs/x86/pdnsd | Bin 0 -> 214736 bytes res/values/pdnsd.xml | 32 + src/org/torproject/android/OrbotApp.java | 5 + .../android/service/TorResourceInstaller.java | 4 +- .../android/service/TorService.java | 5 +- .../android/service/TorServiceConstants.java | 13 +- .../android/vpn/OrbotVpnService.java | 86 +- 145 files changed, 58475 insertions(+), 22 deletions(-) create mode 100644 jni/pdnsd/AUTHORS create mode 100644 jni/pdnsd/COPYING create mode 100644 jni/pdnsd/COPYING.BSD create mode 100644 jni/pdnsd/ChangeLog create mode 100644 jni/pdnsd/ChangeLog.old create mode 100644 jni/pdnsd/INSTALL create mode 100644 jni/pdnsd/Makefile.am create mode 100644 jni/pdnsd/Makefile.in create mode 100644 jni/pdnsd/NEWS create mode 100644 jni/pdnsd/PKGBUILD.in create mode 100644 jni/pdnsd/README create mode 100644 jni/pdnsd/README.par create mode 100644 jni/pdnsd/README.par.old create mode 100644 jni/pdnsd/THANKS create mode 100644 jni/pdnsd/TODO create mode 100644 jni/pdnsd/acconfig.h create mode 100644 jni/pdnsd/aclocal.m4 create mode 100644 jni/pdnsd/compile create mode 100644 jni/pdnsd/config.h create mode 100644 jni/pdnsd/config.h.in create mode 100644 jni/pdnsd/configure create mode 100644 jni/pdnsd/configure.in create mode 100644 jni/pdnsd/contrib/Makefile.am create mode 100644 jni/pdnsd/contrib/Makefile.in create mode 100644 jni/pdnsd/contrib/README create mode 100644 jni/pdnsd/contrib/change_pdnsd_server_ip.pl create mode 100644 jni/pdnsd/contrib/dhcp2pdnsd create mode 100644 jni/pdnsd/contrib/pdnsd_dhcp.pl create mode 100644 jni/pdnsd/depcomp create mode 100644 jni/pdnsd/doc/Makefile.am create mode 100644 jni/pdnsd/doc/Makefile.in create mode 100644 jni/pdnsd/doc/doc_makefile create mode 100644 jni/pdnsd/doc/html/dl.html create mode 100644 jni/pdnsd/doc/html/dl.html.in create mode 100644 jni/pdnsd/doc/html/doc.html create mode 100644 jni/pdnsd/doc/html/doc_makefile create mode 100644 jni/pdnsd/doc/html/faq.html create mode 100644 jni/pdnsd/doc/html/htmlsubst.pl create mode 100644 jni/pdnsd/doc/html/index.html create mode 100644 jni/pdnsd/doc/html2confman.pl create mode 100644 jni/pdnsd/doc/pdnsd-ctl.8 create mode 100644 jni/pdnsd/doc/pdnsd.8.in create mode 100644 jni/pdnsd/doc/pdnsd.conf.5.in create mode 100644 jni/pdnsd/doc/pdnsd.conf.in create mode 100644 jni/pdnsd/doc/txt/doc_makefile create mode 100644 jni/pdnsd/doc/txt/faq.txt create mode 100644 jni/pdnsd/doc/txt/intro.txt create mode 100644 jni/pdnsd/doc/txt/manual.txt create mode 100644 jni/pdnsd/file-list.base.in create mode 100644 jni/pdnsd/install-sh create mode 100644 jni/pdnsd/missing create mode 100644 jni/pdnsd/pdnsd.spec.in create mode 100644 jni/pdnsd/src/Makefile.am create mode 100644 jni/pdnsd/src/Makefile.in create mode 100644 jni/pdnsd/src/cache.c create mode 100644 jni/pdnsd/src/cache.h create mode 100644 jni/pdnsd/src/conf-keywords.h create mode 100644 jni/pdnsd/src/conf-parser.c create mode 100644 jni/pdnsd/src/conf-parser.h create mode 100644 jni/pdnsd/src/conff.c create mode 100644 jni/pdnsd/src/conff.h create mode 100644 jni/pdnsd/src/consts.c create mode 100644 jni/pdnsd/src/consts.h create mode 100644 jni/pdnsd/src/debug.c create mode 100644 jni/pdnsd/src/debug.h create mode 100644 jni/pdnsd/src/dns.c create mode 100644 jni/pdnsd/src/dns.h create mode 100644 jni/pdnsd/src/dns_answer.c create mode 100644 jni/pdnsd/src/dns_answer.h create mode 100644 jni/pdnsd/src/dns_query.c create mode 100644 jni/pdnsd/src/dns_query.h create mode 100644 jni/pdnsd/src/error.c create mode 100644 jni/pdnsd/src/error.h create mode 100644 jni/pdnsd/src/freebsd_netinet_ip_icmp.h create mode 100644 jni/pdnsd/src/hash.c create mode 100644 jni/pdnsd/src/hash.h create mode 100644 jni/pdnsd/src/helpers.c create mode 100644 jni/pdnsd/src/helpers.h create mode 100644 jni/pdnsd/src/icmp.c create mode 100644 jni/pdnsd/src/icmp.h create mode 100644 jni/pdnsd/src/ipvers.h create mode 100644 jni/pdnsd/src/list.c create mode 100644 jni/pdnsd/src/list.h create mode 100644 jni/pdnsd/src/main.c create mode 100644 jni/pdnsd/src/make_rr_types_h.pl create mode 100644 jni/pdnsd/src/netdev.c create mode 100644 jni/pdnsd/src/netdev.h create mode 100644 jni/pdnsd/src/pdnsd-ctl/Makefile.am create mode 100644 jni/pdnsd/src/pdnsd-ctl/Makefile.in create mode 100644 jni/pdnsd/src/pdnsd-ctl/pdnsd-ctl.c create mode 100644 jni/pdnsd/src/pdnsd_assert.h create mode 100644 jni/pdnsd/src/rc/ArchLinux/Makefile.am create mode 100644 jni/pdnsd/src/rc/ArchLinux/Makefile.in create mode 100644 jni/pdnsd/src/rc/ArchLinux/pdnsd.in create mode 100644 jni/pdnsd/src/rc/Debian/Makefile.am create mode 100644 jni/pdnsd/src/rc/Debian/Makefile.in create mode 100644 jni/pdnsd/src/rc/Debian/pdnsd.in create mode 100644 jni/pdnsd/src/rc/Makefile.am create mode 100644 jni/pdnsd/src/rc/Makefile.in create mode 100644 jni/pdnsd/src/rc/README create mode 100644 jni/pdnsd/src/rc/RedHat/Makefile.am create mode 100644 jni/pdnsd/src/rc/RedHat/Makefile.in create mode 100644 jni/pdnsd/src/rc/RedHat/pdnsd.in create mode 100644 jni/pdnsd/src/rc/Slackware/Makefile.am create mode 100644 jni/pdnsd/src/rc/Slackware/Makefile.in create mode 100644 jni/pdnsd/src/rc/Slackware/rc.pdnsd.in create mode 100644 jni/pdnsd/src/rc/SuSE/Makefile.am create mode 100644 jni/pdnsd/src/rc/SuSE/Makefile.in create mode 100644 jni/pdnsd/src/rc/SuSE/pdnsd.in create mode 100644 jni/pdnsd/src/rr_types.c create mode 100644 jni/pdnsd/src/rr_types.h create mode 100644 jni/pdnsd/src/rr_types.in create mode 100644 jni/pdnsd/src/servers.c create mode 100644 jni/pdnsd/src/servers.h create mode 100644 jni/pdnsd/src/sort_namevalues.pl create mode 100644 jni/pdnsd/src/status.c create mode 100644 jni/pdnsd/src/status.h create mode 100644 jni/pdnsd/src/test/Makefile.am create mode 100644 jni/pdnsd/src/test/Makefile.in create mode 100644 jni/pdnsd/src/test/if_up.c create mode 100644 jni/pdnsd/src/test/is_local_addr.c create mode 100644 jni/pdnsd/src/test/random.c create mode 100644 jni/pdnsd/src/test/tping.c create mode 100644 jni/pdnsd/src/thread.c create mode 100644 jni/pdnsd/src/thread.h create mode 100644 jni/pdnsd/version create mode 100755 libs/arm64-v8a/pdnsd create mode 100755 libs/armeabi-v7a/pdnsd create mode 100755 libs/armeabi/libtun2socks.so create mode 100755 libs/armeabi/pdnsd create mode 100755 libs/mips/pdnsd create mode 100755 libs/x86/pdnsd create mode 100644 res/values/pdnsd.xml diff --git a/external/Makefile b/external/Makefile index eba90639..1a148694 100644 --- a/external/Makefile +++ b/external/Makefile @@ -329,6 +329,9 @@ assets: tor polipo jtorctl iptables pluto -zip ../assets/$(APP_ABI)/meek-client.mp3 bin/meek-client -$(STRIP) bin/obfs4proxy -zip ../assets/$(APP_ABI)/obfs4proxy.mp3 bin/obfs4proxy + -$(STRIP) ../libs/$(APP_ABI)/pdnsd + -zip ../assets/$(APP_ABI)/pdnsd.mp3 ../libs/$(APP_ABI)/pdnsd + -rm ../libs/$(APP_ABI)/pdnsd assets-clean: -rm ../assets/$(APP_ABI)/polipo.mp3 @@ -336,6 +339,7 @@ assets-clean: -rm ../assets/$(APP_ABI)/xtables.mp3 -rm ../assets/$(APP_ABI)/meek-client.mp3 -rm ../assets/$(APP_ABI)/obfs4proxy.mp3 + -rm ../assets/$(APP_ABI)/pdnsd.mp3 -rm ../libs/jtorctl.jar #------------------------------------------------------------------------------# diff --git a/jni/Android.mk b/jni/Android.mk index 2dd3ef90..f4af1d97 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -17,6 +17,20 @@ LOCAL_PATH := $(call my-dir) ROOT_PATH := $(LOCAL_PATH) EXTERN_PATH := $(LOCAL_PATH)/../external +######################################################## +## pdnsd library +######################################################## + +include $(CLEAR_VARS) + +PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c) + +LOCAL_MODULE := pdnsd +LOCAL_SRC_FILES := $(PDNSD_SOURCES:$(LOCAL_PATH)/%=%) +LOCAL_CFLAGS := -Wall -O2 -I$(LOCAL_PATH)/pdnsd -DHAVE_STPCPY + +include $(BUILD_EXECUTABLE) + ######################################################## ## libancillary ######################################################## diff --git a/jni/Application.mk b/jni/Application.mk index 3ac89c03..3e5c8225 100644 --- a/jni/Application.mk +++ b/jni/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := armeabi-v7a arm64-v8a mips x86 +APP_ABI := armeabi armeabi-v7a arm64-v8a mips x86 APP_PLATFORM := android-21 APP_STL := stlport_static NDK_TOOLCHAIN_VERSION := 4.9 diff --git a/jni/pdnsd/AUTHORS b/jni/pdnsd/AUTHORS new file mode 100644 index 00000000..fa0454e4 --- /dev/null +++ b/jni/pdnsd/AUTHORS @@ -0,0 +1,58 @@ +Most of pdnsd was written by Thomas Moestl (tmoestl@gmx.net). +In the "par" versions large parts of the code have been revised +and several features have been added by Paul Rombouts. + +Small parts of this program are based on code that was taken from nmap (IP +checksumming), the isdn4k-utils (ippp interface uptest), glibc 2.1.2 (some +definitions for kernel 2.2.x missing in 2.0 glibcs) and FreeBSD +(SIZEOF_ADDR_IFREQ in netdev.c). +nmap was written by Fyodor. The insd4k-utils were written by Fritz Elfert and +others. The GNU C library (glibc) is copyright by the Free Software +Foundation. + +The following people have contributed code: +Andrew M. Bishop contributed support for server labels +Carsten Block contributed 'configure'-able rc scripts +Stephan Boettcher contributed the SCHEME= option. +P.J. Bostley contributed patches to get pdnsd working on + alpha +Frank Elsner contributed rc script fixes +Christian Engstler contributed patches for SuSE compatability +Bjoern Fischer contributed code to make pdnsd leave the case of names + in the cache unchanged +Torben Janssen contributed RedHat rc scripts +Olaf Kirch contributed a security fix for the run_as() + function +Bernd Leibing contributed fixes to the spec file. +Sourav K. Mandal contributed the autoconf/automake code, gdbm + caching facility and many suggestions +Markus Mohr contributed Debian rc scripts +Alexandre Nunes contributed autoconf fixes +Wolfgang Ocker contributed the server_ip option +Soenke J. Peters contributed patches and suggestions for RedHat + compatability +Roman Shterenzon contributed many helpful hints and patches for + FreeBSD compatability. +Andreas Steinmetz contributed the code for the query_port_start and + query_port_end options (which I changed slightly, + so blame any breakage on me ;) +Marko Stolle contributed the contrib/pdnsd_update.pl script that + makes pdnsd usable in a DHCP setup. +Lyonel Vincent extended the serve_aliases option to support an + arbitrary number of aliases +Paul Wagland contributed a patches for bind9-compatability + and for some memory leaks on error paths. +Sverker Wiberg contributed IPv6 build fixes +Michael Wiedmann contributed the pdnsd-ctl.8 man page. +Ron Yorston contributed the dev-uptest for Linux ppp dial- + on-demand devices +Nikita V. Youshchenko contributed extensions to the "if" uptest +Mahesh T. Pai contributed the pdnsd.8 man page. +Nikola Kotur contributed the Slackware start-up script. +Kiyo Kelvin Lee contributed a patch for Cygwin support. +Rodney Brown contributed a patch for Darwin (Apple Mac OS X) support. +Jan-Marek Glogowski contributed a patch implementing the "use_nss" option. + +Please look into the THANKS file for people who helped me in various ways on +this project. +If this list is incomplete, pease drop me a mail! diff --git a/jni/pdnsd/COPYING b/jni/pdnsd/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/jni/pdnsd/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/jni/pdnsd/COPYING.BSD b/jni/pdnsd/COPYING.BSD new file mode 100644 index 00000000..99fe14ae --- /dev/null +++ b/jni/pdnsd/COPYING.BSD @@ -0,0 +1,26 @@ +A small part of the pdnsd source is licensed under the following BSD-style +license: + +Copyright (C) 2001 Thomas Moestl + +This file is part of the pdnsd package. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR CONTRIBUTORS 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. diff --git a/jni/pdnsd/ChangeLog b/jni/pdnsd/ChangeLog new file mode 100644 index 00000000..fe774653 --- /dev/null +++ b/jni/pdnsd/ChangeLog @@ -0,0 +1,3304 @@ +2012-04-23 Paul A. Rombouts + + * src/dns_query.c + Refine the return values of p_dns_cached_resolve(), p_dns_resolve() and + p_recursive_query() so that they distinguish between answers found in + the cache and replies obtained by querying other servers. + This, among other things, can be used to prevent data that was recently + obtained from the cache needlessly being added back to the cache. + +2012-04-22 Paul A. Rombouts + + * configure.in + On the Linux platform, check if we can compile and link with the + -pthread flag instead of linking with -lpthread. + +2012-04-21 Paul A. Rombouts + + * src/dns_query.c + When following the delegation chain trying to get an authoritative + answer, pdnsd would answer with SERVFAIL if it failed to get a reply + from the last server in the chain. Instead pdnsd will now use the last + reply in the chain with RCode=0 that raised the AA or RA flag, if there + is one. + +2012-04-19 Paul A. Rombouts + + * src/cache.c + In report_cache_stat(), make copies of volatile data to get a + consistent data set before making calculations with cache size and + entry numbers. + +2012-04-16 Paul A. Rombouts + + * src/netdev.c + If we can't open /proc/net/if_inet6 in is_local_addr() log a warning + message. + +2012-04-15 Paul A. Rombouts + + * src/dns_query.c + The code checking for duplicate IP addresses obtained from NS records + in auth_ok() has been slightly optimized. + +2012-04-12 Paul A. Rombouts + + * src/dns_query.c + When resolving nameservers obtained from NS records, allow pdnsd to use + more than one IP address per nameserver. + In rare cases, using just one IP address for each nameserver will cause + unnecessary resolve failures if the address chosen for each nameserver + happens to be unreachable while the other addresses would lead to + successful resolution, as demonstrated by Yuri Vorobyev. + +2012-03-16 Paul A. Rombouts + + * src/cache.c + When adding RR records one by one to a cache entry using add_cent_rr(), + use the smallest ttl value in case of conflicting ttls. + Code for local/nonlocal conflict resolution has been taken out of + add_cent_rr_int() and put into add_cent_rr() and cr_check_add() + which should be slightly more efficient. + +2012-03-15 Paul A. Rombouts + + * src/dns_query.c + Enforcing strict RFC 2181 compliance by rejecting all the answers + with inconsistent ttl timestamps can cause undesirable resolve failures. + I have tried to implement a more compromising solution, whereby + inconsistent answers that should be normally rejected are still never + cached, but are nevertheless used as intermediary or temporary results + if all else fails. + +2012-03-13 Paul A. Rombouts + + * src/dns_query.c + Fixed a typo in rr_to_cache() that caused pdnsd to fail to compile when + configured with the --enable-strict-rfc2181 option. + Thanks to Gonzalo L. R. for reporting this problem. + Also changed the return value of rr_to_cache() from a simple boolean to + an RC code in order to properly distinguish between memory allocation + errors and time-stamp inconsistencies. + +2012-02-21 Paul A. Rombouts + + * src/dns_query.c + If we have used EDNS in a query and the remote server answered + with rcode "format error", try again with the OPT pseudo-record + removed from the additional section of the query. + + Also fixed a bug in p_exec_query() that caused pdnsd to behave + as if every reply with a non-empty additional section contained + an OPT record. + +2012-02-15 Paul A. Rombouts + + * src/dns_answer.c,src/helpers.c,src/helpers.h,src/icmp.c, + src/ipvers.h,src/main.c,src/netdev.c + Introduced a new macro SEL_IPVER() to reduce some of the clutter in the + code caused by having to support both IPv4 and IPv6. + +2012-01-31 Paul A. Rombouts + + * configure.in + Add AM_PROG_CC_C_O line to configure.in to prevent automake warning. + +2012-01-29 Paul A. Rombouts + + * src/cache.c + In report_cache_stat(), add the average number of bytes used per cache + entry when reporting the cache status, as suggested by M. Galabant. + +2012-01-28 Paul A. Rombouts + + * src/dns_answer.c,src/dns_query.c + Cleaned up the code a bit to avoid warning messages when + compiling with '-Wall -Winline' flags. + +2012-01-18 Paul A. Rombouts + + * src/conff.c + Set the default of the edns_query option to false. + +2011-07-31 Paul Rombouts + + * src/cache.c + Use a slightly more sophisticated merge-sort algorithm in sort_rrl(). + +2011-05-09 Paul Rombouts + + * src/dns_answer.c + In compose_answer(), also add an OPT pseudo-RR to the additional section + of a NXDOMAIN reply when appropriate. + +2011-05-08 Paul Rombouts + + * src/cache.c,src/cache.h,src/dns_query.c,src/status.c + Make the dns_cent_t struct more compact by putting the fields that are + only used for either non-existent or existent domains, but not both, + into a union so that these fields can share memory. + When saving the cache to file, only write the TTL and time-stamp for + a whole domain when it is negatively cached. + +2011-05-06 Paul Rombouts + + * src/cache.c,src/cache.h,src/dns_query.c + At the request of Andrei Caraman, the TTL of a negatively cached domain + is now adjusted in accordance with the min_ttl and max_ttl options, just + as it is done for (negatively) cached records. + Additional change to the TTL policy is that for negative records (and + negative domains) the neg_ttl setting overrides min_ttl if + neg_ttl < min_ttl. + +2011-04-26 Paul Rombouts + + * src/conf-parser.c + Fixed memory leak that can occur when the configuration file is reloaded + and an error is encountered while parsing the definition of a TXT + record. + +2011-03-21 Paul Rombouts + + * src/make_rr_types_h.pl,src/cache.h,src/cache.c,src/dns_answer.c + Introduced arrays rrmuiterlist and rrcachiterlist to make iterating + over all possible RR types in a cache entry in strict ascending order + a little more efficient. + +2011-03-09 Paul Rombouts + + * src/dns_query.c,src/conf-parser.c,src/conf-keywords.h + Implemented a new config option "outgoing_ip", which + makes it possible to bind outgoing connections to + a specific interface. + +2011-02-21 Paul Rombouts + + * src/netdev.c + Fixed UDP socket descriptors leak in the implementation of + is_local_addr() for the FreeBSD platform. Thanks to Ashish Shukla for + reporting this bug. + +2011-02-14 Paul Rombouts + + * src/cache.c + In purge_all_rrsets(), also free the rrext array if it has become empty after + purging all the RR sets. + +2011-02-04 Paul Rombouts + + * src/conff.c,src/conff.h,src/conf-parser.c,src/conf-keywords.h, + src/dns_query.c,src/dns_query.h,src/servers.c + Changed "edns_query" from a "global" option to a "server" + configuration option. + +2011-02-04 Paul Rombouts + + * src/conff.c,src/conff.h,src/dns_query.c,src/dns_query.h,src/servers.c, + src/conf-parser.c + The query uptest sometimes fails because some DNS servers are configured + to ignore empty queries. The new config option "query_test_name" makes + it possible to query for a specific name instead. + +2011-02-01 Paul Rombouts + + * src/dns_query.c + When processing a reply from a remote name server which seems to delegate + to other name servers, check if the names for which NS records have + been supplied have locally defined NS records. If so, the local + records will now override those supplied by the remote server. + +2011-01-31 Paul Rombouts + + * src/conf-parser.c + Added support for defining TXT records in the configuration file. + +2011-01-30 Paul Rombouts + + * src/dns_query.c + Do not cache additional records from a response that is rejected because + it contains IP addresses in the reject list, even when the reply + is processed as a NXDOMAIN reply. + +2011-01-25 Paul Rombouts + + * src/conf-parser.c + Modified the function scan_string() to allow back-slashed escape + sequences in strings. + +2011-01-21 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c,src/conff.h,src/conff.c, + src/conf-parser.c + Added support for EDNS (Extension mechanisms for DNS). + Currently this is only useful for allowing UDP message sizes + to be larger than 512 bytes. + +2011-01-20 Paul Rombouts + + * src/dns_answer.c + To avoid frequent reallocs when composing a DNS reply message, + grow the message buffer in multiples of a certain minimum chunk size. + +2011-01-19 Paul Rombouts + + * src/dns.c,src/dns.h,src/dns_answer.c + Extended debugging info with DNS-message lengths and flags of incoming + messages. + +2011-01-17 Paul Rombouts + + * src/conff.c,src/conff.h,src/conf-parser.c,src/dns_answer.c + Made "ignore_cd" option obsolete. It is now effectively always on. + +2010-12-27 Paul Rombouts + + * src/cache.c,src/cache.h,src/dns_answer.c,src/dns_query.c, + src/make_rr_types.pl,src/rr_types.in,src/rr_types.c + The array of pointers to rr_set_t structs in the dns_cent_t struct + contains mostly null pointers in practice, so is somewhat + inefficient in storage usage. This problem is exacerbated if we add + support for caching more RR-types. To ameliorate to the problem + I have decided to split the array in two, with one part fixed in the + dns_cent_t struct as before, and an extension part that will be + separately allocated, if necessary. If the extension part is used only + for very rarely cached types, in most cases the extension array will not + need to be allocated thus hopefully saving memory overall. + The lookup tables which are necessary to support the new cache entry + structure are cumbersome to write by hand, so I have written a perl + script to do this automatically. As an additional benefit, which RR + types are cache-able is now configurable for each type separately via + rr_types.in. + +2010-03-14 Paul Rombouts + + * src/dns_query.c + Using randomized source ports for outgoing queries in IPv6 mode failed + with the warning "Out of ports in the range 1024-65535, dropping query!", + because the pdnsd tried to bind to the fixed port for incoming queries, + instead of the dynamically chosen port. This is a very old bug, but it + has only become apparent since source port randomization has become the + default. + Thanks to Philip-André Fillion, Phil Sutter, Radoslaw Szkodzinski and + others for reporting this bug and sending patches. + +2009-12-25 Paul Rombouts + + * src/status.c,src/status.h,src/pdnsd-ctl/pdnsd-ctl.c + Add a magic number to pdnsd-ctl command codes to guard against + possible incompatibility between the pdnsd-ctl utility and the + pdnsd server. + +2009-10-18 Paul Rombouts + + * src/dns_query.c + Make root-server discovery a little more fault tolerant, i.e. if some + of the root-server names don't resolve don't necessarily reject the + whole result. + +2009-10-17 Paul Rombouts + + * src/servers.c,src/dns_query.c,src/dns_query.h + Implemented automatic root-server discovery, which can now be configured + by setting "root_server=discover". + +2009-06-14 Paul Rombouts + + * src/dns_query.c,src/consts.c,src/consts.h,src/conf-parser.c + Changed the default behaviour of the "neg_rrs_pol" option. The default + used to be to only cache records negatively in case the AA (authoritive + answer) bit in the reply was set. The new default is to also allow + negative caching in case the reply has the RA (recursion available) bit + set and the query had the RD (recursion desired) bit set. + This gives the behaviour that is usually wanted in case "proxy_only=on" + is set without having to set "neg_rrs_pol=on", which can be more + problematic. The new default can be explicitly set using + "neg_rrs_pol=default". The values "on","off" and "auth" are also + still available. + +2009-06-13 Paul Rombouts + + * src/conff.c,src/conff.h,src/dns_answer.c,src/conf-parser.c,src/conf-keywords.h + Included a patch contributed by Andreas Steinmetz that implements a new + global configuration option "ignore_cd". pdnsd used to check that the CD + bit in the DNS header of queries is zero and return the error code + "format error" if it is not. However, considering the meaning of this + bit today it appears to be harmless to ignore it, so the new "ignore_cd" + is on by default. Setting "ignore_cd=off" gives the earlier strict + behavior. + Also renamed the the Z1, AU, Z2 bits to correspond with their modern names + CD, AD, Z. + +2008-12-19 Paul Rombouts + + * pdnsd-1.2.7/src/dns_query.c + If pdnsd receives a SERVFAIL response with a non-empty answer section, + use the information tentatively if no better response is available. + The previous behaviour was to discard the reply completely, which could + cause failure to resolve some names. + Thanks to Rafal Wijata for providing an example involving PowerDNS servers + replying with CNAME records. + +2008-09-01 Paul Rombouts + + * src/dns_query.c + In p_dns_resolve(), try to reduce the burden on root servers further for + names ending in "arpa". + +2008-08-31 Paul Rombouts + + * src/dns_query.c + In p_exec_query(), if the reply from a remote name server is negative + (either because the rcode is NXDOMAIN or because the answer section + contains no records for the queried name), ignore the remaining records + in the answer section (in particular do not add them to the cache). + +2008-07-29 Paul Rombouts + + * src/conff.c,src/dns_query.c + Made the default of the configuration option query_port_start equal to + 1024. Also improved the algorithm used by pdnsd to select random source + ports to ensure that each (free) port gets an equal chance of being + selected. This should guarantee random source ports in the range + 1024-65535, making pdnsd less vulnerable to some of the issues described + in CERT VU#800113. + The old situation, where pdnsd lets the kernel select the source ports, + is still available by specifying query_port_start=none. + +2008-07-25 Paul Rombouts + + * src/dns_query.c + Fixed a dangling pointer bug in p_exec_query(), which could cause pdnsd + to crash when processing a long reply with many entries in the answer + section. + +2008-05-12 Paul Rombouts + + * src/conf-parser.c,src/conff.c + Added a recursive-depth counter to the read_config_file() and + confparse() functions to prevent the possibility of infinite + recursion when processing include files. + In confparse(), warn when in a server section the root_server option is + set in combination with policy=simple_only or policy=fqdn_only. + +2008-05-10 Paul Rombouts + + * src/ipvers.h + Included a patch contributed by Georg Schwarz which selectively undoes + a Debian patch contributed by Juliusz Chroboczek on platforms for which + the IPV6_RECVPKTINFO macro is not defined (e.g. MacOS X). + +2008-05-08 Paul Rombouts + + * src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + The pdnsd-ctl add command can now also be used to define NS records. + A wildcard record defined with this command now behaves the same way as + one defined in the config file. + +2008-05-07 Paul Rombouts + + * src/conf-parser.c,src/conf-keywords.h,src/conff.c + Added the ability to process "include" sections in the configuration + file. This makes it possible to place local definitions in separate + files and include them from the main configuration file. + +2008-05-05 Paul Rombouts + + * src/conff.c,src/conf-parser.c,src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + Implemented two new pdnsd-ctl commands, which make it easier to add + definitions to the pdnsd cache at run time. "pdnsd-ctl include" is + similar to "pdnsd-ctl config" but only processes configuration sections + that effect the cache and disallows global and server sections. + "pdnsd-ctl eval" directly parses its string arguments as if they were + part of a configuration (include) file. + +2007-09-15 Paul Rombouts + + * src/dns.h,src/dns_answer.c,src/dns_query.c + Changed the declarations of various packed structs, by moving the + __attribute__((packed)) specifiers from the field level to the struct level. + This was necessary to get the correct value for sizeof(rr_hdr_t) when + compiling with gcc for the ARM architecture. + Thanks to Dirk Armbrust for reporting the problem and supplying the solution. + +2007-08-10 Paul Rombouts + + * src/dns_answer.c + Applied a Debian patch contributed by Juliusz Chroboczek which + reportedly fixes a problem with pdnsd running in IPv6 mode + (IPV6_RECVPKTINFO instead of IPV6_PKTINFO). + +2007-08-04 Paul Rombouts + + * src/dns_query.c + When resolving a name recursively, pdnsd would stop querying further + name servers as soon as it received a reply with the authority (aa) flag + set. Unfortunately, it appears this flag is sometimes raised erroneously + in replies. I have implemented a work-around that ignores the aa flag + when there appears to be a clear delegation to a sub-domain. + Thanks to Nico Erfurth for reporting this problem. + + It appears that pdnsd would also fail to consult servers in the authority + section when configured with neg_rrs_pol=on. This has been fixed. + +2007-08-01 Paul Rombouts + + * src/pdnsd-ctl/pdnsd-ctl.c + Made the matching of pdnsd-ctl command names and most of the arguments + case-insensitive. + +2007-07-22 Paul Rombouts + + * src/dns_answer.c + Instead of sharing the responsibility for freeing the answer buffer in + case of an error amongst different functions, only free it in + compose_answer(). + + * configure.in, src/Makefile.am, src/test/Makefile.am + Merged patch contributed by Pierre Habouzit to deal with CFLAGS the + automake way (allowing packagers to override CFLAGS properly). + +2007-07-21 Paul Rombouts + + * src/dns_answer.c + For each target name in a SRV record in the answer section, add + addresses to the additional section of the response, as is recommended + by the RFCs. + +2007-07-14 Paul Rombouts + + * src/list.c,src/list.h + Made modifications to the implementation of dynamic arrays, which + should ensure proper alignment on all supported architectures. + +2007-07-10 Paul Rombouts + + * Upgraded pdnsd's license to GPL version 3. + +2007-07-08 Paul Rombouts + + * src/cache.h,src/dns_query.c + The data field of the rr_bucket_t struct is now aligned such that + it possible to use straightforward assignment to copy IP addresses, + making memcpy unnecessary for this purpose. + +2007-07-07 Paul Rombouts + + * src/dns_query.c + If pdnsd fails to connect to a name server using a IPv6 address, it will + now retry the connection using a IPv4 address, if available. This allows + pdnsd to recover from situations where IPv6 connectivity is temporarily + unavailable, but IPv4 connectivity still functions. + Thanks to Andreas Ferber for reporting this problem. + +2007-07-04 Paul Rombouts + + * src/dns_answer.c + I have reordered the arguments of the add_rr() and related + functions to make them more consistent with each other. + +2007-07-03 Paul Rombouts + + * src/cache.c,src/hash.c + pdnsd will no longer immediately abort in add_dns_hash() if it fails + to allocate memory for a new hash entry. + +2007-07-01 Paul Rombouts + + * src/conff.c,src/conff.h,src/consts.c,src/consts.h, + src/conf-parser.c,src/conf-keywords.h,src/dns_query.c + Implemented the new "reject", "reject_policy" and "reject_recursively" + options for the server section of the configuration file. + + * src/ipvers.h,src/conf-parser.c,src/dns.c,src/status.c, + src/pdnsd-ctl/pdnsd-ctl.c + Allow local AAAA records to be defined even if pdnsd is compiled + without --enable-ipv6, provided there is sufficient support in the + C libraries and --disable-new-rrs was not used. + +2007-06-30 Paul Rombouts + + * src/dns_answer.c + Previously, when the answer buffer was realloced in add_rr(), an + extra 2 bytes used to be reserved, which are unnecessary, as far + as I can tell. I have decided to do without these extra 2 bytes, + which originate from Thomas Moestl's code. As compensation, I have + added extra PDNSD_ASSERT() statements to check that the answer + buffer does not overflow. + +2007-06-27 Paul Rombouts + + * src/status.c, src/pdnsd-ctl/pdnsd-ctl.c + Extended the pdnsd-ctl 'add a' and 'add aaaa' commands to allow + multiple IP addresses to be specified. + +2007-06-25 Paul Rombouts + + * src/conff.c,src/conff.h,src/conf-parser.c,src/conf-keywords.h, + src/dns_query.c + Implemented a new option for the server section of the configuration + file: randomize_servers. + + * src/servers.c + Improved the debug messages in uptest(). + +2007-01-30 Paul Rombouts + + * src/icmp.c + Fixed up the code implementing the ping test in icmp.c, + which was broken for 64-bit systems. + Thanks to Michael Uleysky for reporting this bug. + +2007-01-09 Paul Rombouts + + * src/dns_query.c + auth_ok() now returns 1 if the cache entry has the DF_NEGATIVE flag set, + without providing a list of authoritative servers to continue querying. + Otherwise if we receive a non-authoritative NXDOMAIN reply and pdnsd + is configured with neg_domain_pol=on, pdnsd will continue to try to + get an authoritative answer. The intention is that pdnsd + stops querying as soon as it gets an "unknown domain" answer. + +2006-04-29 Paul Rombouts + + * src/main.c + pdnsd would segfault if it tried to call log_message() (via the + log_warn() and log_error() macros) before the FILE pointer to the debug + output stream was properly initialized. + Thanks to Thomas Cort for discovering this problem and suggesting a fix. + +2006-04-09 Paul Rombouts + + * src/conf-parser.c,src/helpers.c,src/conff.h,src/conff.c + I have included a patch contributed by Jan-Marek Glogowski, that + implements the configuration option "use_nss". With use_nss=off pdnsd + will avoid system functions that may use NSS (i.e. initgroups()), which + may need DNS for LDAP lookups, which can lead to long timeouts and + stalls if pdnsd itself is used for the DNS lookup. + +2006-03-26 Paul Rombouts + + * src/dns_query.c + Negative caching of RR sets is now also supported with lean_query=off. + +2006-03-25 Paul Rombouts + + * src/dns_query.c,src/conf-parser.c,src/main.c + I have implemented a new query method: udp_tcp. With this method a UDP + query is tried first and, if the UDP answer is truncated, the query is + repeated using TCP. This is the behaviour that seems to be recommended + by the DNS standards. However, pdnsd wil not discard the truncated + answer if the TCP requery fails. + +2006-03-24 Paul Rombouts + + * src/dns_answer.c + Previously, pdnsd would add at most one additional A (and AAA) record + for each record in the answer and authority sections. At the request of + Angel Marin, pdnsd will now add all A and AAA records it can find in the + cache for each name that produces additional records. + +2006-01-02 Paul Rombouts + + * src/dns_answer.c + compose_answer() would leak memory if the query contained + an unsupported QTYPE or QCLASS. This has now been fixed. + +2005-12-27 Paul Rombouts + + * configure.in + TCP-query support is now compiled in by default. + It can still be disabled using the configure option + --disable-tcp-queries. + +2005-12-23 Paul Rombouts + + * src/dns_answer.c + Queries received from clients with non-empty answer, authority or + additional sections are now treated as malformed and rejected with + rcode 1 (format error). + +2005-11-06 Paul Rombouts + + * src/conf-parser.c + Time intervals in the configuration files can now be expressed in + seconds, minutes, hours, days and weeks, using the suffixes + s,m,h,d,and w. + +2005-10-14 Paul Rombouts + + * src/consts.c + In the pdnsd configuration file, true/false and yes/no are now accepted + as synonyms for the constants on/off. + +2005-08-24 Paul Rombouts + + * src/helpers.c + I have fixed a potential buffer overflow problem that could occur with + the 'pdnsd-ctl dump' command. + In case of the root domain, the function rhn2str() would write 2 bytes + to the output buffer even if size==1. Theoretically (under pathological + circumstances) this could have allowed the dbuf buffer in the function + dump_cent() to overflow by one byte. + +2005-08-21 Paul Rombouts + + * acconfig.h,src/cache.c,src/conff.c,src/conf-parser.c,src/dns.c, + src/dns_answer.c,src/dns_query.c,src/error.h,src/helpers.c,src/main.c, + status.c + + It appears the newer versions of gcc won't convert a pointer to char + into a pointer to unsigned char and vice versa without complaining. + The changes I have made should get rid of these distracting warning + messages. Unfortunately I had to introduce casts in some cases, + which reduces type safety :-(. + +2005-08-16 Paul Rombouts + + * src/dns.h + Some changes were made to the endianess detection code to + address problems on Mac OS X v10.4 Tiger. + +2005-08-15 Paul Rombouts + + * configure.in + Some changes where made to address the reported problems with the + configure script on Mac OS X v10.4 Tiger. + +2005-08-05 Paul Rombouts + + * src/status.c,src/dns_answer.c + The output of the 'pdnsd-ctl status' command now includes some + statistics on the number of query threads. + +2005-07-29 Paul Rombouts + + * src/main.c + It appears that sigwait() can return EINTR under certain conditions. + This explains the problems reported by Sanjoy Mahajan with strace + and ACPI S3 sleep, which both caused pdnsd to exit prematurely. + The return value of sigwait() is now checked and sigwait() is retried + if the return value is EINTR. + +2005-07-04 Paul Rombouts + + * src/dns_query.c + It appears that some servers that do not support recursive queries + answer with "query refused" instead of "not supported". The + p_exec_query() function now takes that possibility into account. + +2005-07-01 Paul Rombouts + + * src/dns_query.c + In the processing of queries, I will make a distinction between + recoverable errors and non-recoverable ones (typically caused by out of + memory conditions). In the case of non-recoverable errors, no attempt to + query alternative name servers is made. + +2005-06-26 Paul Rombouts + + * src/dns_query.c + In p_recursive_query(), as soon as one of the servers in the q list + replied "no error" or "name error", only this reply was examined and + the other servers in the q list were ignored. Joshua Coombs has brought + to my attention that this strategy sometimes fails when this reply is not + authoritative and doesn't contain any usable references to name servers + in the authority section. + I have modified p_recursive_query() to allow pdnsd to continue querying + the remaining servers in the q list as long as we haven't received an + authoritative answer or usable authority information. This will allow + pdnsd to arrive at the correct answer in some cases where it would + formerly fail. + +2005-06-25 Paul Rombouts + + * src/status.c + The "pdnsd dump" command may now also be given an argument + consisting of a name beginning with a dot. This will dump information + about all names in the cache ending in the given name. An argument + consisting of a name without a leading dot will only give information + about the exact name, as it did before. + +2005-06-24 Paul Rombouts + + * src/servers.c,src/status.c + All uptests are now conducted by the server status thread. If a retest + is requested via a "pdnsd-ctl server", an existing server status thread + is signaled or a new server status thread is spawned if the old one has + exited. This has the effect that a "pdnsd-ctl server label retest" + command will now return immediately without waiting for the tests to + finish. + +2005-06-20 Paul Rombouts + + * src/conf-parser.c,src/servers.c,src/servers.h + At the request of Al-Junaid Walker I have added a new configuration + option for the uptest interval. With "interval=ontimeout" the server is + not tested at startup/reconfig, or at regular intervals, but only after + a DNS query to a server times out. However, once a server is declared + dead it is never considered again unless it is revived using a + "pdnsd-ctl config" or "pdnsd-ctl server" command. + +2005-06-19 Paul Rombouts + + * src/servers.c,src/dns_query.c,src/icmp.c + During an uptest the server configuration data is locked. Especially + with ping or query uptests of unresponsive servers this means that the + execution of "pdnsd-ctl config" or "pdnsd-ctl server" commands can be + delayed for a long time (or even time out). I have made modifications + that allow a "pdnsd-ctl config" or "pdnsd-ctl server" commands to + interrupt pending uptests to allow these commands to proceed without + delay in most cases. + + * src/thread.h + Use the POSIX sigaction() instead of signal() to install signal handlers. + +2005-06-08 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c + I have defined a struct dns_msg_t that includes a message length field. + In the case of sending a DNS message over TCP, we no longer need a + separate write() call to send the message length. This prevents possible + packet fragmentation. + +2005-06-07 Paul Rombouts + + * src/dns_query.c + The query_method=tcp_udp option only used to work with cooperative name + servers, i.e. servers that either send back a TCP reply or explicitly + refuse the TCP connection request. This wasn't sufficiently satisfactory + in practice, because some name servers are completely unresponsive to TCP + connection requests. I have made modifications to allow pdnsd to try UDP + queries in case TCP connections time out. When a short server timeout is + combined with a global timeout that is at least twice as long, this may + allow a query to a name server that only responds to UDP queries to + succeed with query_method=tcp_udp. + +2005-04-20 Paul Rombouts + + * src/cache.c,src/hash.c,src/conff.c,src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + The "pdnsd-ctl empty-cache" command now accepts additional arguments; + these are interpreted as include/exclude names. During execution of the + command the name of each cache entry is matched against the names in the + include/exclude list. If the name ends in a name to be included, the + cache entry is deleted, otherwise not. + This feature was added at the request of Joshua Coombs. + +2005-04-19 Paul Rombouts + + * src/cache.c, src/hash.c + pdnsd will now (temporarily) unlock the cache between emptying hash + buckets, this should allow pdnsd to remain responsive while executing + the "pdnsd-ctl empty-cache" command. However, this only applies to DNS + queries; pdnsd will not accept any new pdnsd-ctl commands while a + pdnsd-ctl command is still running. + +2005-03-29 Paul Rombouts + + * configure.in, src/hash.h + I have added a new configure option --with-hash-buckets=... + This makes it possible to specify a different number of + hash buckets without editing the source files. + +2005-03-17 Paul Rombouts + + * src/error.c + When running in both daemon and debug mode, print warning and + error messages to debug file as well as the syslog. + +2005-03-15 Paul Rombouts + + * src/dns_answer.c + Only call pthread_setspecific() in debug mode, because + pthread_getspecific() is also only used in debug mode. + If pthread_setspecific() fails, treat this as a non-fatal error. + +2005-03-10 Paul Rombouts + + * configure.in + On Linux systems the configure script will now try to detect automatically + whether the system implements the Native POSIX Thread Library, but + the method is not necessarily foolproof. + + * src/dns.c + Local PTR records generated for resolving numeric IPv6 addresses back into + names, are now based on ip6.arpa instead of ip6.int, because the latter domain + will be phased out eventually. + +2005-03-06 Paul Rombouts + + * Makefile.am,src/cache.c + Create an empty cache-file at install time and don't complain about empty + cache files at start up. + +2005-02-20 Paul Rombouts + + * acconfig.h,configure.in,src/conf-parser.c,src/conff.h,src/dns.h, + src/dns_answer.c,src/dns_query.c,src/error.h,src/helpers.h,src/icmp.c, + src/ipvers.h + + I have applied some changes to the code proposed by Rodney Brown to improve + portability. In particular, pdnsd should now compile on the Darwin platform + (Apple Mac OS X). + To support some of these changes, the source package is now built with a + slightly more modern version of autoconf (2.57) and automake (1.6.3). + +2005-01-29 Paul Rombouts + + * src/dns.c,src/dns_answer.c,src/dns_query.c + + I have added some extra debug code to make it easier to discover the + reason that pdnsd considers a query or reply malformed (format error). + +2005-01-12 Paul Rombouts + + * src/dns.c,src/dns_answer.c,src/dns_query.c + + I have extended some debug code contributed by Kiyo Kelvin Lee to dump + the data received by pdnsd in debug mode (queries from clients, replies + from name servers). Because this will give very verbose debug output, + I've arranged it so that this data dump only occurs if pdnsd has been + configured and compiled with --with-debug=9 and pdnsd has been called + with -v9. + + Additionally, in the case that pdnsd rejects a reply from a name server + because it is not well formed, I have refined the debug messages to + distinguish between format errors due to unexpected truncation and + others kinds of format errors. + +2004-10-30 Paul Rombouts + + * src/rr_types.c + I have included some changes proposed by Joseph Pecquet to address + the compilation problems reported by FreeBSD users. + +2004-10-18 Paul Rombouts + + * acconfig.h,configure.in,src/helpers.c,src/helpers.h,src/dns.h + I have merged a patch for CYGWIN support by Kiyo Kelvin Lee into + my version of the code. + +2004-10-15 Paul Rombouts + + * src/cache.c + Invalidating local records with the pdnsd-ctl did not work the way the + documentation described. An invalidated local record would be always be + purged at the next lookup, thus invalidation would practically have the + same effect as deletion. An invalidated local record is of no use at all and + would occupy space until it is purged during a lookup (but not by purge_cache). + The function invalidate_record() now behaves as the documentation describes, i.e. + invalidation of local records has no effect. + +2004-09-27 Paul Rombouts + + * doc/pdnsd.conf.5.in + A new man page describing the format of the pdnsd config file has been + added to the pdnsd package. I've used a customized Perl script to generate + one automatically from the html documentation. + +2004-09-14 Paul Rombouts + + * src/hash.c + The cache entries in a hash chain are now stored in order of increasing long hash + value. The advantage is that if an name is looked up that is not present in the + cache, this can be done by comparing with only half (on average) of the number + of entries in the hash chain. Not a huge speed up, but still worth while, I think. + Additionally, the number of hash computations for each add_cache() call has + been halved. + +2004-09-11 Paul Rombouts + + * src/cache.c + insert_rrl() will no longer add local records to the rr_l list, because + purge_cache() ignores them anyway. + +2004-09-08 Paul Rombouts + + * src/dns.h,src/cache.c,src/dns_query.c,src/dns_answer.c,src/conf-parser.c + I've started using GETINT16,GETINT32,PUTINT16,PUTINT32 macros, which are based + on the NS_GET/NS_PUT macros that can be found in the BIND source, instead of memcpy + for fetching and storing non-aligned integer data. + +2004-09-08 Paul Rombouts + + * src/cache.c,src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + New pdnsd-ctl command: "pdnsd-ctl dump" will print information about all the + entries contained in the cache. + "pdnsd-ctl dump " will only print entries belonging to . + The data fields of the more common rr-types will be printed in human readable + form, the remaining ones in a hexadecimal representation. + With thanks to Dan Jacobson for suggesting this feature. + +2004-08-31 Paul Rombouts + + * src/conf-parser.c + At the suggestion of Dan Tihelka, I have expanded to the server_ip= option + to allow the name of an interface to be specified instead of an IP address. + pdnsd will not bind to the interface name, but will lookup the address the + interface has at start up, and listen on that address. If the address + of the interface changes while pdnsd is running, pdnsd will not notice that. + +2004-08-30 Paul Rombouts + + * src/cache.h,src/cache.c + I've reversed the meaning of the CF_NOAUTH and renamed it CF_AUTH. + I've also added a domain level flag DF_AUTH, which is used to + mark cache entries obtained from authoritave replies in response to + a query of type * (all).. + +2004-08-30 Paul Rombouts + + * src/cache.c + I've changed the format of the cache file. A typical cache entry has empty + sets for most RR types (even more if DNS_NEW_RRS is defined). In the old + format, each empty RR set was represented by a zero byte. + In the new format only non-empty sets are respresented, leading + to a (modest) reduction is size. + +2004-08-28 Paul Rombouts + + * src/conf-parser.c + New option for "rr" sections in the config file: reverse=on/off. + If you want a locally defined name to resolve to a numeric address and vice + versa, you can now achieve this by setting reverse=on before defining the + A record, making it unnecessary to define a seperate PTR record for the reverse + resolving. + +2004-08-20 Paul Rombouts + + * src/cache.h,src/cache.c,src/conf-parser.c,src/dns_query.c + At the request of Daniel Black, I have added support for defining local wildcard records + in pdnsd. The only type supported presently is records beginning with '*.'. + +2004-08-10 Paul Rombouts + + * src/hash.c,src/cache.c,src/dns_query.c,src/dns_answer.c + Sampo Lehtinen has remarked that pdnsd sometimes failed to resolve classless + reversed-delegated IP addresses, and that this has something to do with the fact + that pdnsd did not accept '/' characters in domain names. After reading Sampo's + and Thomas' remarks, and also rfc2317 and some of the rfc's referenced in rfc2317, + I decided pdnsd should place no restrictions at all on the types of characters it + allows in domain names, only on the lengths of the byte sequences. + This led me to make some quite extensive internal changes to pdnsd. Among other + things domain names are now stored in transport format (sequences of bytes preceded + by length bytes) instead of C strings. This is also more efficient because there + is no need any more to convert from one representation to the other, except when + reading the config file, interacting with pdnsd-ctl or running in debug mode. + Conversion between the two representations isn't always possible, though. + For example, domain names in transport format might contain non-printable characters. + These are now printed as escape sequences (three octal digits preceded by a back slash). + Presently there are still restrictions on the characters in the domain names that can + be defined in local records. I doubt this will ever be considered a problem. + +2004-08-02 Paul Rombouts + + * src/dns_query.c + The code for handling NXT records was flawed. A response from a remote server + containing NXT records (even well-formed ones) could cause pdnsd to crash. + The code for handling NAPTR records contained incorrect PDNSD_ASSERT statements, + which could cause pdnsd to abort unnecessarily. + +2004-07-25 Paul A. Rombouts + + * src/list.h,src/list.c,src/dns.c,src/dns_query,src/dns_answer.c + I've noticed that some of the (dynamic) arrays that pdnsd uses are quite sparse. + Instead of using an array structure with elements that are large enough to contain + the largest possible domain name, I've implemented a "list" data structure that + is more compact. The elements of a list can only be accessed sequentially from + beginning to end, but it allows more efficient memory use in case the names are + significantly shorter that the maximum. + +2004-07-22 Paul Rombouts + + * src/conf-parser.c + I've expanded pdnsd's configuration options by adding support in pdnsd for reading + /etc/resolv.conf style files. Instead of specifying IP addresses in a server section, + the option "file=" can be used. + The IP addresses in the lines beginning with "nameserver" will be added to + the list of address for that section, the remaining lines will be ignored. + To avoid the possibility that pdnsd will query itself, local addresses are skipped + (unless pdnsd is configured to listen on a different port number). + +2004-07-21 Paul Rombouts + + * src/cache.h,src/cache.c,src/dns_query.c,src/conf-parser.c + New option for "server" sections in the config file: root_server=on/off. + In case a server section contains only addresses of root servers, which + usually only give the nameservers of top level domains in their reply, + setting root_server=on will enable certain optimizations. This involves using + cached information to reduce queries to the root servers, thus speeding up + the resolving of new names. This option is also necessary to make the + delegation_only option work in combination with root servers. + +2004-07-16 Paul Rombouts + + * src/cache.c,src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + New pdnsd-ctl command: "pdnsd-ctl empty-cache" will make pdnsd delete its entire + cache, freeing all entries. This is useful for debugging purposes, or in situations + where you suspect that stale cache entries are causing you problems, but you are not + sure which ones. + +2004-07-11 Paul Rombouts + + * src/cache.c,src/dns_query.c + I've removed the use of the function add_cache_rr_add(), which was used to + add additional RR records to the cache one at a time. I've changed the code + in dns_query.c such that additional (or off-topic) records are first collected + in arrays of dns_cent_t structures, and then added to the cache using add_cache(). + With this approach only one function, viz. add_cache(), is used for adding + new entries to the cache, which I believe leads to a cleaner programming + interface. Added benefit is that query serial numbers are no longer + necessary. + +2004-07-10 Paul Rombouts + + * src/cache.h,src/cache.c,src/dns_query.c,src/dns_answer.c + I've added two new field to the dns_cent_t struct, namely c_ns and c_soa. + These will be used to remember references to NS and SOA records in the authority + sections of replies from remote name servers. + This information can be used by pdnsd to fill in the authority section of its + own reply. + +2004-06-25 Paul Rombouts + + * src/dns_query.c,src/servers.c,src/consts.c + I've added an new server availability test which can be selected with "uptest=query". + This can be useful as an alternative to "uptest=ping" in case the remote server does not + respond to ICMP_ECHO requests at all, which unfortunately is quite common these days. + "uptest=query" causes pdnsd to send an empty query to remote nameservers. Any well-formed + response (apart from SERVFAIL) within the timeout period will be interpreted as a sign that the + server is "up". + In a sense this new availability test can actually be considered more reliable than the + other ones that pdnsd supports. + With thanks to Juliusz Chroboczek for suggesting this feature. + +2004-06-24 Paul Rombouts + + * src/helpers.c + Don't use getpwnam() while we are multi-threaded, because it returns a pointer to + a statically allocated structure. I will use getpwnam_r() instead, which is thread + safe. Unfortunately there seem to be some portability problems with getpwnam_r(). + For those platforms that lack getpwnam_r(), I will keep the old code with getpwnam() + as an alternative. + +2004-06-23 Paul Rombouts + + * src/servers.c + Check that the number of IP addresses in a server section is nonzero before + testing servers for availability. Otherwise pdnsd could crash in debug mode. + +2004-06-21 Paul Rombouts + + * src/conff.c,src/conf-parser.c,src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + New pdnsd-ctl command: "pdnsd-ctl config" will make pdnsd re-load its configuration file. + In most cases (but there are still some exceptions) this is preferable + to restarting pdnsd after making changes to the configuration file. + An important advantage is that there should be no perceptible interruption in the dns service + when using the reload command. + An alternative config file can be specified with "pdnsd-ctl config ". + +2004-05-31 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c,src/dns_query.h + I've made an adjustment to p_recursive_query() and related functions, so that + when pdnsd chases name servers in pursuit of authoritative records, it avoids + all the name servers already queried for the same name in the recursive calling + chain, not just the servers most recently used. + Although the hops counter will already break any possible cycles, this will + allow pdnsd to detect pathological cycles earlier and waste less resources. + + * src/cache.c + In add_cache(), don't add empty entries to the cache. Empty cache entries + waste memory and are more persistent than non-empty ones, because purge_cache() + cannot get rid of them. + +2004-05-30 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c,src/icmp.c,src/netdev.c + I've removed the calls to getprotobyname() and used the constants IPPROTO_TCP + and IPPROTO_UDP instead. First of all, it doesn't seem very efficient to call + a function repeatedly to look up the same well-known protocol numbers. + More importantly, getprotobyname() stores its results in a statically-allocated + structure and thus cannot be considered thread safe. (getprotobyname_r() + is thread safe, but is not portable.) + +2004-05-27 Paul Rombouts + + * src/dns_answer.c + I've noticed that when pdnsd is restarted shortly after it has answered a TCP + query, it is often not able to bind to the TCP socket again, resulting in a + disabled TCP server thread. The solution appears to be to set the SO_REUSEADDR + socket option before binding the socket. This allows you to use the same port even + if it is busy (in the TIME_WAIT state). + I found the code for this in a patch file from an old Debian package. + +2004-05-20 Paul Rombouts + + * src/dns_query.c + Joseph Pecquet has reported that version 1.1.11 does not compile under FreeBSD v4.x + because the macro ENONET is undefined. I've bypassed the problem by surrounding + the case line using this value with conditional preprocessor directives. + +2004-05-08 Paul Rombouts + + * src/rc/Slackware/rc.pdnsd + I've included a Slackware start-up script contributed by Nikola Kotur. + +2004-05-05 Paul Rombouts + + * doc/pdnsd.8 + I'm very grateful to Mahesh T. Pai for contributing a pdnsd man page, + which was still missing up till now. + +2004-04-30 Paul Rombouts + + * src/servers.c,src/dns_query.c + After considering some suggestions made by Juliusz Chroboczek I have made the + following changes: + + - After receiving a reply from a remote server mark the server up and update the + timestamp so that pdnsd doesn't bother testing this server for availability for a + while. + - After detecting an error with an send/recv call that indicates a server is + unavailable, mark a server down so that pdnsd doesn't bother testing this server + for a while. + - After server timeouts, uptests are never performed by a query/answer thread, + because this may delay the sending of an answer to the client. Instead the + timestamp of a server that needs to be tested for availability is set to zero and + a condition signal is sent to alert the server status thread, which will carry out + the test. Unresponsive servers with uptest=ping will not be marked down + immediately any more, but only after the ping test has definitely failed. + + * src/error.c,src/error.h + I've moved most of the code previously contained in the DEBUG_MSG macro to a new + function debug_msg(). + The DEBUG_MSG macro now simply expands to "if(debug_p) debug_msg();". + This should make the executable a little smaller, and be just as fast when + debugging is off. The DEBUG_MSG macro still expands to nothing if pdnsd is built + without debugging support. + +2004-04-28 Paul Rombouts + + * src/dns_query.h,src/dns_query.c + I've tried to simplify the finite state machine used for processing parallel + queries, by merging the "state" and "nstate" variables used by p_exec_query() and + p_query_sm() resp. into one "state" variable. + By introducing an extra field "iolen" to keep track of the number of bytes read + from or written to a socket, I could also reduce the number of states for TCP + queries. The new code has the additional advantage that it can handle situations + that require multiple read() calls to receive a response. + +2004-04-14 Paul Rombouts + + * src/dns_query.c + I've added an extra check comparing the number if poll/select events actually + handled to the return value of poll/select. This should reduce the chance that + pdnsd will get caught in a busy spin due to unknown remaining bugs. An error + message is logged and an error code is returned when this comparison fails. + +2004-04-13 Paul Rombouts + + * src/dns_query.h,src/dns_query.c + I got rid of the event field in the query_stat_t struct. + I think it is redundant, because its value can be quite simply derived from + the nstate field. + +2004-04-12 Paul Rombouts + + * src/dns_query.c + I appears there was flaw in the code for handling a "Not Implemented" response + from a remote server with the RA (recursion available) bit equal to zero. This + could cause pdnsd to get into a busy spin. I traced the flaw back to Thomas + Moestl's code, so it must be in all the versions of pdnsd I know of. In previous + versions of pdnsd the busy spin would eventually time out. Due to some recent + changes the loop would no longer time out, making the bug more noticeable. + With thanks to Nicolas George for reporting the bug. + + I also discovered a closely related flaw that would cause pdnsd to poll() closed + file descriptors. It usually works out OK in practice, but it is definitively not + the correct way to do it. + + Additionally, I discovered some opportunities to save memory, e.g. by replacing + the nsname buffer in the query_stat_t struct by a pointer to an already existing + copy of a name. + +2004-04-10 Paul Rombouts + + * src/cache.c + Nicolas George remarked that he thought it was strange that subdomains of domains + negated with "neg" sections in the config file were not also negated. I thought that + he had a point, and I've implemented a change so that negating example.com will + now also negate www.example.com, xxx.adserver.example.com, etc. + +2004-04-09 Paul Rombouts + + * src/error.c,src/error.h + I noticed that the code for the log_warn() and log_error() functions was almost + identical, even to the point that log_warn() called syslog() with LOG_ERR + priority. I've merged these two functions into one log_message() function. + +2004-04-08 Paul Rombouts + + * src/main.c,src/conf-parser.c + The -4 and -6 command-line options should now work as advertised. + This wasn't entirely trivial. The rule is that options on the command line + override those in the configuration file. The easiest way to implement this is to + process the command-line options after reading the configuration file. But this + doesn't work for the -4 and -6 options, because the run_ipv4 flag determines how + IP addresses in the config file are parsed. I've inserted some extra tests and + warning messages that will hopefully make this setting nearly foolproof. + + I've added two new command-line options, "-a" and "-i ". + With the -a flag pdnsd will try to detect automatically if IPv6 support is + available on a system, and fall back to IPv4 if not. The -a flag can be used + instead of -4 or -6. + + In IPv6 mode, pdnsd will now automatically convert IPv4 addresses to IPv6-mapped + addresses. The -i option can be used to specify a prefix for this mapping. The + default is ::ffff.0.0.0.0 + There is also a corresponding ipv4_6_prefix= option for the config file. + + In IPv4 mode, if IPv6 support is compiled in, pdnsd will now skip IPv6 addresses + in the config file (except for the server_ip and ping_ip options) with a warning + message. This allows you to have mixed sets of IPv4 and IPv6 address in the same + config file, although in IPv4 mode some server sections may become inactive. + + With thanks to Juliusz Chroboczek for suggesting these changes. + +2004-04-07 Paul Rombouts + + * src/cache.c + I've changed some of the cache-flag definitions to make debugging a little simpler. + Unfortunately, this makes the cache files of previous pdnsd versions incompatible + with the new one. I've introduced a cache version identifier to be added at the + beginning of each cache file. This enables pdnsd to recognize and discard + incompatible cache files. + +2004-04-05 Paul Rombouts + + * src/cache.h,src/cache.c + I've changed the way CACHE_LAT (cache latency, normally 120 secs) is used to + determine whether a cache entry has timed out. Instead of simply adding it to the + ttl (time to live), I use CACHE_LAT if the ttl is less then CACHE_LAT, else the + ttl itself, making CACHE_LAT the minimum ammount of time a cache entry stays in + the cache. + +2004-04-02 Paul Rombouts + + * src/dns_query.c + I've introduced a global timeout parameter. This is the minimum period of time + pdnsd will wait after sending the first query to a remote server before giving + up without having received a reply. + The timeout options in the configuration file are now only minimum timeout intervals. + Setting the global timeout option makes it possible to specify quite short timeout + intervals in the server sections. This will have the effect that pdnsd will start + querying additional servers fairly quickly if the first servers are slow to respond + (but will still continue to listen for responses from the first ones). + This may allow pdnsd to get an answer more quickly in certain situations. + + * src/dns_query.c + When receiving a NXDOMAIN (unknown domain) response from a remote name server, + I think it is still useful to process the authority and additional sections, + so that pdnsd can possibly add a SOA record to its own response. + +2004-04-01 Paul Rombouts + + * src/dns_query.c + In p_recursive_query(), I've slightly changed the way pdnsd does parallel + queries. Active queries or not canceled until we have received a useful response + from a remote name server, or all the queries have failed or timed out. + Thus the par_queries parameter is no longer the maximum number of parallel + queries, but rather the increment with which the number of parallel queries is + increased when the previous set has timed out. + In the worst case all the servers in the list of available servers will be queried + simultaneously. We may be wasting more system resources this way, but the advantage + is that we have a greater chance of catching a reply. + After all, if we wait longer anyway, why not for more servers. + +2004-03-31 Paul Rombouts + + * src/dns_answer.c + I've noticed that in compose_answer() that while adding the name in the query + section it was not passed through compress_name(). While it is true that the + first name occurrence cannot be compressed, it is still sensible to process the + query name with compress_name() so that the offset can be stored and provide + additional opportunities for future compressions. + I've tested this with dig and the responses of pdnsd are now usually a little + smaller in size or can hold more information within the 512 byte limit. + +2004-03-30 Paul Rombouts + + * src/cache.c + I've noticed that pdnsd stored rr records (of the same type) in reverse order + in the cache. + Although I don't see anything inherently wrong with that, I think it's neater to + store them in the order they are processed. + +2004-03-29 Paul Rombouts + + * src/cache.c + I've rearranged the order of the arguments of some of the functions in cache.c + to obtain a more consistent calling interface. + + * src/dns_answer.c + I've noticed that pdnsd would only add NS records to an authority section if it could + find such records matching the queried name (or the last CNAME in the answer) exactly. + However, I understand that a server should try to give NS records as close as possible + to the target name in the naming hierarchy. + I also understand that if a domain name is reported as nonexisting, or no record of + the requested type exists, it is customary to provide a SOA record, searching up the + name hierarchy if necessary. + I've tried to implement this in compose_answer(), although with some limitations. + I only look in the cache, I don't search more then three levels up, and stop before + the top level. + +2004-03-28 Paul Rombouts + + * src/cache.c,src/dns_answer.c + There were some issues with add_cache_rr_add(). + + First of all, the way it was used in rr_to_cache() (or rather not used) meant + that if an "off topic" record was added for a name that lacked an entry in the + cache, the rr set would be created with an incorrect serial number (namely zero). + I've rewritten add_cache_rr_add so that it can create new cache entries if necessary. + This simplifies the code in rr_to_cache() and ensures correct serial numbers. + + Secondly, in add_cache_rr_add() the ttl was compared with that of an existing rrset + without adjusting for the min_ttl and max_ttl options. This could lead to all the + previous records being deleted, retaining only the last one. + +2004-03-27 Paul Rombouts + + * src/dns_answer.c + In compose_answer(), if the rd (recursion desired) bit is set in the query + and the response contains a CNAME record (while a different type of record was + requested), always do a recursive query on the CNAME, even if we have already + added a record of the requested type to the response. + Failing to honor the rd bit will cause some resolver libraries to complain, + even if the answer contains a record of the requested type. + + I've slightly changed the calling interfaces of add_to_response() and add_rrset() + to make them more consistent and efficient. + + In add_rrset() I've fixed a memory leak on one of the error paths. + + In add_additional_rr(), the return value of add_rr() was not checked. + If add_rr() fails, it will free *ans, and functions higher up the calling + chain could be referencing freed memory. + + I've fixed a potential referencing of freed memory or double freeing in add_additional_a(). + If a call of add_additional_rr() fails, it will free *ans. + Previously, add_additional_rr() could be called a second time, in which case + the second call would be referencing freed memory or freeing it a second time.. + +2004-03-23 Paul Rombouts + + * configure.in, src/Makefile.in,src/pdnsd-ctl/Makefile.in,src/test/Makefile.in + Frédéric L. W. Meunier has reported that configure --srcdir option (for building + in directory separate from the source directory) was broken. + Should be fixed now. + +2004-03-20 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c,src/helpers.c,src/icmp.c,src/main.c,src/netdev.c,src/ipvers.h,src/test/if_up.c,src/test/is_local_addr.c,src/test/tping.c,src/test/random.c,src/conf-parser.c + I've eliminated the global variable run_ipv6 from the code. + Enabling both the IPv4 and IPv6 protocols at the same time is not supported + in pdnsd, so the value of run_ipv6 (if it is defined) is simply !run_ipv4. + + * src/dns.c,src/test/is_local_addr.c,src/test/tping.c + It appears the option to compile pdnsd without IPv4 support (i.e. only IPv6 + support) was broken. Should be fixed now. + +2004-03-19 Paul Rombouts + + * src/cache.c + I've discovered an incorrect use of cache locks in lookup_cache(). + We only read locks in place, it is possible for purge_cent() to delete a cache + entry while another thread is trying to read it at the same time, which could + lead to trouble. I've rewritten purge_cent() so that it can be used to test + whether something needs to be purged without actually deleting anything. + If something needs to be deleted, purge_cent() will be called again with + the proper read/write locks in place, excluding access to the cache for all + other threads. + +2004-03-18 Paul Rombouts + + * src/cache.c + I've added a new function sort_rrl() for sorting the rr_l list using a merge-sort + algorithm. Usually the insertion sort used by insert_rrl() is good enough, because + new entries belong near the end most of the time. Reading entries from disk forms + an exception, though, because the rrsets in the file are completely out of order + w.r.t. timestamps, leading to quadratic time complexity of the insertion sort method. + In that case it should be faster to simply append items at the end of the rr_l list + and sort using a more efficient algorithm afterwords. + pdnsd now seems to start up noticeably faster when reading large cache files. + I've also considered using a more sophisticated data structure than a doubly linked + list, but this will add considerable complexity to the code and use more memory. + +2004-03-13 Paul Rombouts + + * src/dns_answer.c + Changed a declaration in udp_answer_thread() so that the buffer used for passing + control messages on to sendmsg() is exactly the right size, instead of an arbitrary + 512 bytes. + Also initialized the msg_flags of the struct msghdr passed on to sendmsg() to zero, + to keep Valgrind from complaining about uninitialized bytes. + +2004-03-12 Paul Rombouts + + * src/icmp.c + Fixed an incorrect call to select() in ping4(). A file descriptor set for detecting + exceptions was initialized but not passed on to select(). This would lead subsequent + code always to behave as if an IO exception had occurred. + Valgrind seems to indicate that when a poll() call times out and returns 0, + the revents field of the struct pollfd is not necessarily set. + I've changed the code to check that the return value is > 0 before examining the + revents field. + +2004-02-06 Paul Rombouts + + * src/conf-parser.c,src/conf-parser.h,src/conf-keywords.h + I've rewritten the parser for the configuration file in C from scratch. + (f)lex and yacc/bison are no longer needed to build pdnsd. + +2004-01-16 Paul Rombouts + + * src/main.c + Load the cache from disk without locking cache access because pdnsd + is still single-threaded at that point. + +2004-01-15 Paul Rombouts + + * src/cache.c,src/hash.c + Moved the responsibility for freeing the cache entries referred by + the hash buckets from destroy_cache() to free_dns_hash() (which is called + by destroy_cache()). Previously, the cache and hash tables were already + completely destroyed by the time free_dns_hash() was called, and there was + nothing left for free_dns_hash() to free. + +2004-01-14 Paul Rombouts + + * src/hash.c,src/make_hashconvtable.c + The hash conversion table is now generated at build time instead + of at run time when pdnsd is started up. + +2004-01-13 Paul Rombouts + + * src/dns.c + In add_host() fixed incorrect generation of IPV6 type of name for PTR record + due to use of && instead of & as masking operator. + +2004-01-13 Paul Rombouts + + * src/icmp.c, src/dns_answer.c + Use unsigned long instead of int error counters to reduce the danger + of wraparound. + +2004-01-06 Paul Rombouts + + * src/main.c,src/thread.c,src/thread.h,src/server.c,src/status.c,src/dns_answer.c + Initialize a global thread attribute object in main.c and use it to create all the detached + threads, instead of initializing a separate attribute object for each new thread. + +2004-01-06 Paul Rombouts + + * src/dns_answer.c + Check the return value of pthread_create() in udp_server_thread() + and tcp_server_thread() to ensure that a new answer thread has actually + been created and free resources if not. + +2004-01-04 Paul Rombouts + + * src/helpers.c,src/cache.c,src/conff.c,src/status.c + Stop writing to control socket after an error has been detected. + +2004-01-03 Paul Rombouts + + * src/pdnsd-ctl/pdnsd-ctl.c + Tried to make the error messages of pdnsd-ctl more helpful. + The complete usage description is now only printed if the 'help' command + is used. For problems with other commands a much shorter message is generated + specific for that command. + +2004-01-02 Paul Rombouts + + * src/helpers.h + Changed the definition of rhnlen(). For valid data this will make no difference, + but it may change the behaviour of pdnsd in certain error situations. + +2004-01-02 Paul Rombouts + + * src/dns.c + Optimized compress_name() some more. + +2004-01-02 Paul Rombouts + + * src/dns_answer.c + Additional code cleanup in compose_answer(). + +2004-01-01 Paul Rombouts + + * doc/pdnsd-ctl.8 + Updated the pdnsd-ctl man page. + +2003-12-31 Paul Rombouts + + * src/pdnsd-ctl/pdnsd-ctl.c + Cleaned up some code. + +2003-12-31 Paul Rombouts + + * src/status.c,src/conff.h,src/conff.c + Some further code cleanup in status.c. + Labels for server sections are no longer limited to 32 chars, + but can have arbitrary length. The string that is used to specify + new DNS-addresses with the "pdnsd-ctl server" command can now also + have arbitrary length. + +2003-12-30 Paul Rombouts + + * doc/html/doc.html + Added information about CNAME and MX resource records, that were + previously undocumented. + +2003-12-26 Paul Rombouts + + * src/dns_query.c + Removed the function p_dns_resolve_from(). This function was essentially + a call to p_recursive_query() with a dummy nocache argument. + p_recursive_query() can now be called with nocache=NULL instead. + +2003-12-26 Paul Rombouts + + * src/dns_query.c + Using a variable length array instead of an malloced buffer to hold the struct pollfd array + in p_recursive_query(). This has the potential for causing portability problems, but I + think that's unlikely because almost all the major C compilers I work with support variable + length arrays nowadays. + +2003-10-18 Paul Rombouts + + * src/helpers.h,src/helpers.c + Fixed a mistake that caused a compile error when using the --with-random-device + configuration option. + Thanks to Daniel Black for reporting this bug. + +2003-10-02 Paul Rombouts + + * conf-lex.l.in,src/conf-parse.y,src/conff.h,src/conff.c,src/dns_query.c + Made the "delegation_only" feature configurable. + +2003-09-25 Paul Rombouts + + * src/helpers.c,src/helpers.h + Added alternative implementations of strdup, strndup, stpcpy, getline and asprintf + in an effort to make the code more portable. + +2003-09-22 Paul Rombouts + + * src/helpers.c,src/conf-parse.y + Made some changes to the parser of the configuration file so that domain names + missing a dot at the end will be tolerated. + +2003-09-21 Paul Rombouts + + * src/dns_query.c + Implemented a first version of the "delegation-only" feature. + It has been "hard-coded" to work for "com" and "net" zones, + and is not yet configurable. + +2003-09-21 Paul Rombouts + + * src/dns.c + Rewrote domain_match(). Also changed the way it is used. + I believe it has a cleaner semantics now. + +2003-09-21 Paul Rombouts + + * src/dns_query.c + Changed the order of the arguments of p_exec_query() and p_recursive_query() + to make it more consistent with the other functions. + +2003-09-18 Paul Rombouts + + * src/dns_answer.c + Reordered the code in process_query() so that a buffer for an error response is + allocated only when it is actually needed. + +2003-09-17 Paul Rombouts + + * src/cache.c + Added parentheses to correct mistaken operator precedence assumption in cache.c. + !cent->flags&DF_NEGATIVE is parsed as (!(cent->flags))&DF_NEGATIVE but I think + what Thomas Moestl must have intended was !((cent->flags)&DF_NEGATIVE). + +2003-09-12 Paul Rombouts + + * src/dns_query.c + Fixed a mistake which caused the effect of the proxy_only option to be reversed. + Thanks to Andrew M. Bishop for reporting this bug. + +2003-09-11 Paul Rombouts + + * src/helpers.c + Rewrote str2rhn() and rhn2str(). + +2003-09-10 Paul Rombouts + + * src/dns.c + Rewrote read_hosts(), the function that reads /etc/hosts-style input. + I believe the parsing algorithm is more robust now. + +2003-09-09 Paul Rombouts + + * src/status.c,src/pdnsd-ctl/pdnsd-ctl.c + Fixed a bug (my fault) that caused improper passing on of flags for the + pdnsd-ctl source command. + Also reordered some of the code, so that data is validated after all of it + has been read from the control socket. This should prevent a "broken pipe" + error message if data validation fails. + Also fixed the reporting of success or failure of the pdnsd-ctl "neg" command. + +2003-09-08 Paul Rombouts + + * src/list.c + Rewrote da_grow1() and da_resize() so that they automatically allocate an array + if given a NULL argument. This makes the use of da_create() redundant in most cases. + +2003-09-08 Paul Rombouts + + * src/conf-parse.y,src/servers.c + At the suggestion of Greg Norris, I changed the code to allow server sections in the + configuration file that don't specify any IP addresses. Such a section will remain + inactive until one or more IP addresses are assigned with the control utility pdnsd-ctl. + +2003-09-04 Paul Rombouts + + * src/dns_answer.c,src/dns_query.c + Oops: in my zeal to declare variables in the smallest possible scope, I ended up + using a pointer to a struct that was out of scope. My understanding of compilers tells me + it should work out OK in practice, but it is definitely a no-no. + Used a union declared in a larger scope instead (which is ugly in another way, + but equally efficient). + Also removed a section of redundant code in udp_server_thread(). + +2003-09-01 Paul Rombouts + + * src/dns_query.c + Corrected the iteration range of a for loop in p_dns_cached_resolve(), which would + otherwise cause an array to be indexed out of bounds in the function set_flags_ttl(). + +2003-08-31 Paul Rombouts + + * src/dns_answer.c + Added cleanup handlers for freeing the resources passed on to udp_answer_thread() and + tcp_answer_thread(). This should ensure the resources are freed even if the threads get + canceled. + +2003-08-30 Paul Rombouts + + * src/cache.c + Revised large portions of code in src/cache.c, used for adding and deleting entries in + the cache. In particular, I rewrote purge_cache(), which I believe was incorrect. + I wouldn't be surprised if this was the cause of the crashed (defunct) threads that some + people were reporting. + Also fixed some memory leaks. + +2003-08-28 Paul Rombouts + + * src/cache.c + Eliminated the overhead of allocation debugging in the case that ALLOC_DEBUG is not defined. + +2003-08-24 Paul Rombouts + + * src/conf-parse.y + No longer allow certain settings of the query_method option in the configuration file + if pdnsd is not compiled with the necessary support. + Thanks to Nikolaus Rath for reporting the bug. + +2003-08-23 Paul Rombouts + + * src/netdev.c + Fixed a bug in is_local_addr() where the result of fgetc(f) is restricted to type char + before being compared to EOF, which can result in the comparison always being false. + Thanks to Gerhard Tonn for reporting the bug. + +2003-07-28 Paul Rombouts + + * doc/html/index.html,doc/html/doc.html,doc/html/dl.html,doc/pdnsd-ctl.8,contrib/README + Revised the documentation. + +2003-07-21 Paul Rombouts + + * src/main.c,src/status.c,src/icmp.c + Setting stat_pipe=0 after opening or binding the control socket fails. + This should prevent further use of the control socket if a problem with + it has been detected previously. + Also properly initialized the global variable int ping_isocket in src/icmp.c + +2003-07-13 Paul Rombouts + + * src/main.c + Polished the code in main(). + +2003-07-04 Paul Rombouts + + * src/helpers.c,src/dns_answer.c,src/dns_query.c + Eliminated the use of inet_ntoa() in favor of the more modern inet_ntop(). + inet_ntop() makes more sense in threaded code and is also recommended in + the glibc info pages. + +2003-07-03 Paul Rombouts + + * src/dns_query.c + Fixed an allocation size error (not mine) in p_exec_query(). + The erroneous size is almost always larger than necessary, so in practice this bug + just wastes memory. But there is also a possibility that the allocated buffer is too + small, which would mean trouble. + Also fixed two memory leaks on some of the error paths in p_exec_query(). + +2003-06-28 Paul Rombouts + + * acconfig.h,configure.in,src/thread.h + Extended the configuration option --with-thread-lib. + Configuring with --with-thread-lib=linuxthreads2 will cause the alternative + definition of THREAD_SIGINIT suggested by Thomas Moestl to be used. + +2003-06-27 Paul Rombouts + + * src/consts.h,src/consts.c,src/conff.c,src/conf-parse.y,src/dns_answer.c + Added two new configuration options for policies of inclusion/exclusion lists. + The new policies options are "simple_only" and "fqdn_only". + This allows me to control to which name servers pdnsd will direct queries for + simple host names. + I also polished the code a bit in report_conf_stat(), used for reporting the current configuration. + +2003-06-20 Paul Rombouts + + * acconfig.h,configure.in,src/thread.h,src/thread.c + Added a configuration option --with-thread-lib=nptl. + This causes the macro THREAD_SIGINIT to be defined as empty in src/thread.h, + and thread_sig() in src/thread.c is never used. + +2003-06-11 Paul Rombouts + + * src/thread.h + Undid the change to the definition of THREAD_SIGINIT suggested to me by + Thomas Moestl, after receiving a report of a problem with this change + from someone running SuSE 7.0. + +2003-06-06 Paul Rombouts + + * src/dns_query.c: + Discovered that I failed to preserve the semantics of Thomas Moestl's code + when I rewrote a section of code in use_server(). Fixed. + +2003-05-19 Paul Rombouts + + * src/cache.c,src/conf-lex.l.in,src/conf-parse.y,src/conff.h,src/dns_answer.c,src/dns_query.c,src/servers.c: + Merged fixes contained in patch file sent to me by Thomas Moestl with my own version. + Changing the version to 1.1.8b1 as suggested by the patch file. + +2003-02-26 Paul Rombouts + + * pdnsd-1.1.7a-par.diff: + Made one big patch file from all the changes I made up till now. + Wrote a description of the changes in a file README.par + Posted patch file on the web so others can use it. + +2003-02-24 Paul Rombouts + + * src/cache.c + Changed the code that writes the cache to disk. + Data is now written strictly sequentially, eliminating the need for fseek(). + This seems to have successfully solved the problem I had with corrupt cache files. + +2002-05-27 Paul Rombouts + + * ChangeLog: + Started experimenting with the source code. + Made many changes between 2002-05-27 and 2002-07-13. + Too lazy to maintain the ChangeLog. + +2002-01-06 Thomas Moestl + + * version: Call it 1.1.7. + +2002-01-04 Thomas Moestl + + * src/dns_answer.c, src/dns_query.c: + Comment and debug message fixes, more assertions. + +2002-01-03 Thomas Moestl + + * src/dns.c, src/dns_answer.c, src/dns_query.c: + More harmless fixes, correct some comments and debug messages, add more + assertions. + + * NEWS, version: 1.1.7p2, correct NEWS entry. + + * src/helpers.c: + Make sure the calling thread of pdnsd_exit() terminates immediately. + +2002-01-02 Thomas Moestl + + * src/dns_answer.c, src/helpers.c, src/icmp.c: + Fix a few more harmless bugs, more paranoia. + + * src/status.c: Fix yet more, probably harmless, problems. + +2002-01-01 Thomas Moestl + + * src/dns.h, src/dns_answer.c, src/dns_query.c: + Fix a few more possible buffer size problems, and add a bunch of + assertions as last lines of defence. + +2001-12-30 Thomas Moestl + + * src/dns.c: Build fix (include error.h). + + * NEWS, version: Call it 1.1.7p1, and add a NEWS entry. + + * TODO: Reduce TODO to what actually is still needed. + + * src/dns.c, src/error.h, src/helpers.c: + Add a bunch of robustness PDNSD_ASSERT()'s. + + * src/dns_query.c: + Fix a bug which may possibly be remotely exploitable to gain access as + the user pdnsd runs as. + This was caused by a dumb single-character mistake :( + + * doc/Makefile.am, configure.in: + Avoid confusing automake 1.5 by not putting a comment into a make rule. + Fix CONFDIR passing. + + Submitted by: GoTaR + + * src/pdnsd-ctl/pdnsd-ctl.c: + Avoid crashing when the buffer contents received using the status command + are not terminated. + +2001-10-14 Thomas Moestl + + * src/rc/SuSE/pdnsd.in, THANKS: + Fix the stop case for the SuSE rc script: killproc requires the full + path of the binary as argument (reported by Bernhard Pelz). + +2001-09-23 Thomas Moestl + + * configure.in: + Revamp the OS autodetect test. OpenBSD and (hopefully) NetBSD are no longer + unsupported. + + * src/helpers.c, THANKS: + Do not try to use arc4random when compiling for NetBSD (submitted by + Thomas Stromberg). + +2001-09-10 Thomas Moestl + + * COPYING.BSD: s/REGENTS/AUTHOR/ in one place. + + * src/cache.c: + It is possible no record of the requested type is present after calling + cr_add_cent_rr_int() (when the record was marked as being local), so + check before dereferencing the pointer to the respective rrset. + Leave the record unmodified when cr_check_add() returns 0.x + +2001-07-26 Thomas Moestl + + * src/rc/RedHat/pdnsd.in: + Add a workaround for @sysconfdir@ substitutions containing ${prefix}. + Spotted by Robert Linden. + +2001-07-04 Thomas Moestl + + * src/rc/RedHat/pdnsd.in: + Add a condrestart handler to the Red Hat rc script, and do some general + cleanup. Contributed by Christian Engstler. + +2001-07-02 Thomas Moestl + + * src/error.h: + Attempt to detect a gcc that cannot yet handle ANSI variadic macros, + and work around this by using the old GCC-style variant. + + * src/conff.c: + Remove a + at the start of a line that got in when merging a diff by + hand. + + * src/servers.c: waitpid() returns a pid_t. + + * src/dns.c: + It's sizeof, not sizof. This should unbreak the IPv6 build. Also silence + some warnings with appropriate casts. + + * NEWS, version: Call it 1.1.6, and add a NEWS entry. + +2001-07-01 Thomas Moestl + + * src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns_query.c, THANKS, version, AUTHORS: + Added a modified version of Andreas Steinmetz's code for + query_port_start and query_port_range, and added him to AUTHORS and + THANKS. + +2001-06-23 Thomas Moestl + + * src/cache.c: + Fix a bogon: deleted would not be reset correctly in the first + purge_cache loop, which could cause pdnsd to loop forever when a + negative record was after a deleted rr. + +2001-06-21 Thomas Moestl + + * src/list.h: + Add (currently unused) list macros that are going to be used in future + code. + + * src/cache.c: + Fix a bogon in the rw lock code: we need to wake up a writer if there + are no readers. The old code was a leftover from a time when + SUSP_THRESH was just r_pend * x. + Fix a typo. + +2001-06-13 Thomas Moestl + + * AUTHORS: Add mention of FreeBSD code to AUTHORS. + + * src/netdev.c: + Add SIZEOF_ADDR_IFREQ (taken from FreeBSD: _SIZEOF_ADDR_IFREQ, net/if.h + rev. 1.58.2.1) and add an appropriate copyright notice. + The reason for this is that other BSDs don't have it, and we are not + supposed to use underscored macros in portable software. + +2001-06-12 Thomas Moestl + + * src/icmp.c: Fix double #inclusion of . + Noticed by Sebastian Stark. + +2001-06-08 Thomas Moestl + + * src/dns_query.c, THANKS: + Allow underscores in the query names reported back, as the comment next + to the decompress_name call already indicated (but the call gave NULL + as the uscore parameter, which disables underscores normally). + Add Michael Ströder, who spotted this, to THANKS. + +2001-06-06 Thomas Moestl + + * src/servers.c, THANKS: + Fix a bug discovered by Stefan Erhardt (and add him to THANKS): the + return value of waitpid was misinterpreted. + +2001-06-04 Thomas Moestl + + * Makefile.am, file-list.base.in, version: + Bump version to 1.1.6p1; wire up COPYING.BSD so that it gets included + in RPM's and tarballs. + + * COPYING.BSD: + Add the BSD-Style copyright notice so that it can be included in binary + distributions. + +2001-06-03 Thomas Moestl + + * src/dns.c, src/dns_answer.c, src/dns_query.c, src/helpers.c, src/status.c, NEWS, version: + Bump version to 1.1.5, and add a NEWS entry for this release. + + Miscellaneous cleanups, mainly in the status.c code; fix a bug that + could cause heap corruption (rhncpy always clobbered the whole buffer, + but only the needed space was reserved in add_rr). This should solve + the crashes some people were seeing (this bug is not an exploitable + security hole as far as I know; the respective buffer is on the heap, + as mentioned). + + * src/error.c: + Paranoia: do not use the argument to crash_msg as a format string + (crash_msg is only used with constant strings, though). + +2001-06-02 Thomas Moestl + + * src/dns.c, src/dns.h, src/dns_answer.c, src/dns_query.c, src/error.h, src/hash.c, src/helpers.c: + Correct underscore handling for SRV records, and a few comment fixes. + + * src/cache.c, src/conff.c, src/dns_query.c, src/error.h, src/helpers.h, src/status.c: + Numerous non-critical argument fixes for printf-like functions. + + * src/dns.c: Remove superfluous \n's. + + * src/conf-parse.y, src/dns_answer.c, src/status.c: + Correct some DEBUG_MSG nits, and fix two format string bugs. One of + them could allow users that are allowed to use pdnsd-ctl with the + server (when the status socket is enabled) to gain the privileges of + the user that runs (the run_as user or the user that started pdnsd on + Linux when strict_setuid is set to off) pdnsd. The status socket is + disabled by default, and if it is enabled, it's default permissions + are quite restrictive, so this isn't a problem for most. + +2001-05-30 Thomas Moestl + + * src/status.c: + Make the status permissions actually work (missed last time). + + * src/dns_answer.c, src/main.c, src/status.c, src/status.h: + Move the status socket initialization to a place where it gets executed + before any threads are started; this way, we can use umask to set the + permissions, and avoid a (in this case harmless, but anyway) race + condition. + While being there, remove obsoleted comments and places referring to + the now-socket as fifo. + +2001-05-29 Thomas Moestl + + * src/cache.c: + Replace a misuse of CF_LOCAL with DF_LOCAL. This had no effect, because + the values are the same. + +2001-05-22 Thomas Moestl + + * src/hash.c, src/helpers.c, THANKS, acconfig.h, configure.in: + Add an option for allowing underscores (_) in domain names. This + violates the RFC's if enabled (which it isn't by default). + Thanks to Eelco Vriezekolk for an initial patch. + + While being there, clean up configure.in and acconfig.c a bit. + + * src/helpers.c, src/status.c: + Add a few comments about security implications. + + * src/cache.c, src/dns_answer.c, src/dns_query.c, src/helpers.c: + Change some occurences of strcpy to strncpy. Again, no risk here, the + buffer lentgh was carefully chosen, and while the data was partially of + remote origin, it was carefully validated before entering the cache (and + thus having a chance of being used by us). + 3 occurences remain: 2 in cache.c, where we allocate a sufficient amount + of memory before (mimicking the non-portable strdup) and one where + we copy a constant and which is obviously correct. + + * src/dns.c: + Change two occurences of strcat to strncat. Again, no risk here, the + buffer lentgh was carefully chosen, the data was validated and supplied + by the starting user. + + * src/dns.c: + Change a sprintf to a snprintf and enlarge a buffer a bit. This is pure + paranoia (alrhough makes code review easier for others), because a.) the + lengths were carefully chosen so that no overrun could occur and + b.) this was locally supplied data. + +2001-05-21 Thomas Moestl + + * src/rc/RedHat/Makefile.am: + Add a missing semicolon in the RedHat rc Makefile.am (discovered by + Christian Engstler). + +2001-05-19 Thomas Moestl + + * HACKING: Remove the mostly outdated HACKING file. + + * src/debug.c: + Catch a corner case in the allocation debug helpers: realloc() with a + size of 0 is effectively a free operation. To my knowledge, this is + not done in the pdnsd sources, however. + + * src/test/test.sh: + Use the correct error function, forgotten in last commit. + + * src/test/clnt-test.sh, src/test/srv-test.sh, src/test/test.sh: + Misc small improvements in the regression test scripts, mostly + adding configuration variables and common error handlers. + Comment a little on the tests that are done in clnt-test.sh + + * src/rr_types.c: Fix a typo in a comment. + + * src/cache.c, src/debug.c, src/dns_answer.c, src/dns_query.c, src/error.h, src/hash.c, src/list.c, src/main.c, src/status.c, src/thread.c, src/thread.h: + New ANSI variadic debug macros (finally), which print a timestamp and + a thread ID now for easier debugging with many parallel queries. + It should be considered to make those inline functions instead. However, + we have the advantage that we use printf in place here and benefit + from parameter checking without specifying obscure function attributes. + + * src/rc/SuSE/.cvsignore, src/test/.cvsignore, src/rc/.cvsignore, src/rc/Debian/.cvsignore, src/rc/RedHat/.cvsignore, contrib/.cvsignore, doc/.cvsignore, src/.cvsignore, src/pdnsd-ctl/.cvsignore, .cvsignore: + Brush up the rotten (pre-autoconf!) .cvsignore files and add some where + necessary. + +2001-05-17 Thomas Moestl + + * src/rc/RedHat/Makefile.am, src/rc/RedHat/pdnsd.in, configure.in, pdnsd.spec.in: + Red Hat rc script and RPM improvements by Christian Engstler. + +2001-05-12 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c: + Fix a place missed when converting rr_info. + + * version: It's 1.1.4, finally. + + * src/rr_types.c, version: + Change some class values in the rr type structure to better values. + Bump beta version. + +2001-05-10 Thomas Moestl + + * src/cache.c, src/dns_answer.c, src/dns_query.c: + Fix a signedness bug that could cause erraneous 0 ttls to be returned. + Add some debug messages, and do some minor fixups. + +2001-05-09 Thomas Moestl + + * src/cache.c, src/rr_types.c: + Fix some bugs in the new conflict resolution code and make it more + complete. + + * src/cache.c, version: + Add conflict resolution code. This needs a bit more checking, and + the tables might still need to be tweaked. + Bump version. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/Makefile.am, src/cache.c, src/cache.h, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/consts.c, src/consts.h, src/debug.c, src/dns.c, src/dns_answer.c, src/dns_answer.h, src/dns_query.c, src/dns_query.h, src/error.c, src/error.h, src/hash.c, src/hash.h, src/helpers.c, src/helpers.h, src/icmp.c, src/icmp.h, src/list.c, src/main.c, src/netdev.c, src/netdev.h, src/rr_types.c, src/rr_types.h, src/servers.c, src/servers.h, src/status.c, src/status.h, src/thread.c, src/thread.h, configure.in, version: + Remove the old infrastructure that theoretically could have allowed for + multiple cache subsystems. This ability was never used, and if it should, + the caching should probably be split into two layers, a higher level + common one and the actual caching backends. + src/cacheing/cache.c and src/cacheing/native/*.[ch] were repo-copied to + src/. + Substitute "conf.h" with for includes. + Purge records a little more often (when adding records, and when + retrieving from the cache). Handle cache_size properly when using + purge_cent. + Introduce some infrastructure in rr_types.[ch] for a record conflict + checker which is to be introduced shortly to enforce cache consistency + even in the purge_cache=off case. + +2001-05-04 Thomas Moestl + + * src/rc/RedHat/pdnsd.in, src/rc/SuSE/pdnsd.in, src/rc/Debian/pdnsd.in: + Revert the last commit. It breaks the rc scripts by spamming them with + make style variable expansions. + + * src/rc/SuSE/pdnsd.in, src/rc/RedHat/pdnsd.in, src/rc/Debian/pdnsd.in, AUTHORS, THANKS: + Fix a rc script bug spotted by Frank Elsner, and add him to AUTHORS and + THANKS. + +2001-05-01 Thomas Moestl + + * version: Bump version to 1.1.4p2. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/status.c: + Fix some bogons and remove some unneeded code in the pdnsd-ctl + interface. + Fix spelling and line length bugs. + +2001-04-30 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c, src/conf-parse.y, src/status.c: + Some corrections for the authrec config file and the pdnsd-ctl noauth + support. + + * src/pdnsd-ctl/pdnsd-ctl.c: + Fix wrong argv index (using getopt changed the indices). + + * src/pdnsd-ctl/pdnsd-ctl.c, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns.c, src/dns.h, src/dns_query.c, src/status.c, THANKS, version, AUTHORS: + Accumulated changes that should go in before 1.1.4: + - merge Andrew M. Bishop's patch that adds a server label option + - make local records authoritative for the domain by default, and add + the authrec option to change this + - add the auth keyword to the pdnsd-ctl source option to support that + - fix a bug in the conf-parse.y grammar causing a shift/reduce conflict + - sync up AUTHORS and THANKS: add Andrew M. Bishop, Kevin A. Burton and + Michael Steinl + - bump version to 1.1.4p1 + + * src/conff.c, src/main.c: + Fix two small bugs: the wrong element of argv was used for the pidfile + option, which could cause pdnsd to segfault, and C_INCLUDED was always + used in slist_add, regardless of the tp parameter. + + * src/helpers.c: + Fix a bogon discovered by Michael Steiner: the fread() return value + was tested against bytes, not the number of items. + + * src/hash.c, src/hash.h, src/cache.c: + purge_cache used to walk over the cache quite inefficiently when it was + called from add_cache. Add a lazy mode for purge_cache which uses the + rrset_l to be efficient in this special case. + Add some #ifdef'ed-out-by-default code to debug the hash function. + +2001-04-12 Thomas Moestl + + * NEWS: Add NEWS entry for 1.1.3. + + * src/dns.c, src/helpers.c, src/icmp.c, contrib/Makefile.am, contrib/README, version: + IPv6, ICMP and build fixes. It's 1.1.3 now! + + * src/debug.c, src/debug.h: Add the new debug support files. + + * src/test/clnt-test.sh, src/cache.c, src/cache.h, src/error.h, src/list.c, src/list.h, src/main.c, src/status.c, src/status.h, src/Makefile.am, src/conf-parse.y, src/conff.h, src/dns.c, src/dns_answer.c, src/dns_query.c: + Add allocation debug support. Some small cleanups before the upcoming + 1.1.3 release. + + * src/dns_query.h, src/helpers.c, src/list.c, src/conff.c, src/dns.c, src/dns_answer.c, src/dns_query.c: + Lots of small bugfixes, cleanups, style and spelling fixes. + + * src/test/clnt-test.sh: Fix nc arguments. + + * src/test/clnt-test.sh, src/test/srv-test.sh, src/test/test.sh: + Add regression test scripts. + +2001-04-11 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c, src/cache.c, src/servers.c, src/dns_answer.c, src/helpers.c, src/helpers.h, src/icmp.c, src/main.c: + Further cleanups and bug, style and spelling fixes. + + * configure.in: Use -g again in the CFLAGS for a while. + + * version: Beta version bump. + + * src/rc/SuSE/pdnsd.in: + killproc does not seem to take the full path, but only the process name + (which is what one would expect). + + * src/hash.c, src/netdev.c, src/rr_types.c, src/status.c, src/conf-parse.y, src/conff.c, src/helpers.c: + Misc. smaller fixes, and fixes on the new features. Also clean up style + and spelling in some places. + + * src/dns_answer.c: + Bring the glibc pthread_cleanup_push/pthread_cleanup_pop return bug + workaround into the main tree. + Without this, a return between those two macros would cause pdnsd + to crash on system using a glibc between 2.1.2 and 2.2.2 (and possibly + others). This could e.g. be cause by a TCP connect() port scan. + +2001-04-10 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c: + Minor fixes, direct error messages to stderr. + + * src/list.c, src/list.h: Add the new list implementations. + + * src/cache.c, src/cache.h, src/conf-parse.y, src/dns.c, src/dns_answer.c, src/dns_query.c, src/helpers.c, src/helpers.h, src/conf-lex.l.in: + Introduce rhnlen and rhncpy and make use of it instead of kluged-up + strcpy/strlen in the appropriate places. + Check that incoming names contain only legal characters in + decompress_name, return RC_FORMAT otherwise (this would result in + wrong handling only, but not in a security hole). + Reorganzie compose_answer and make it more correct for multiple + questions. Get rid of the algorithm that tries to add a higher + level name server; this might be readded in another place somewhen. + Use some more da_* instead of hand-built lists. + Some style cleanups. + + * src/rc/RedHat/Makefile.am: + Add K45pdnsd links for rc6.d (reboot) and rc0.d (halt) following a + suggestion by Stas Sergeev. + +2001-04-06 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c, src/cache.h, src/error.h, src/helpers.c, src/helpers.h, src/main.c, src/servers.c, src/status.c, src/conf-parse.y, src/conff.c, src/conff.h, src/dns.c, src/dns.h, src/dns_answer.c, src/dns_query.c, src/Makefile.am, version: + Bump alpha version; introduce a generic dynamic array type and make use + of it to ged rid of some ugly casts and redundant code. + Minor fixes. + + * src/icmp.h, src/ipvers.h, src/conff.h, src/consts.h, src/dns.h, src/dns_answer.h, src/dns_query.h, src/helpers.h: + Use macros without an underscore as first character to protect the + headers. Underscores are reserved and should not be used in the + application name space. + + * src/error.h: Add PDNSD_ASSERT, change style a little. + +2001-04-03 Thomas Moestl + + * src/hash.c, src/netdev.c, src/servers.c, src/helpers.c, src/icmp.c, src/main.c: + Another slew of small bugfixes, minor updates and small fixes. + + * src/rr_types.c, src/consts.c: + Update rr_types.c copyright date, consts.c should have a rcsid string. + + * src/rr_types.c: cvs add rr_types.c. + + * src/dns.h, src/helpers.h, src/ipvers.h, src/rr_types.h, src/status.h, src/conf-parse.y, src/conff.h: + cvs add rr_types.h that got missed before, update copyright dates, + remove some old config cruft, some minor fixups. + + * src/conff.c, src/consts.c, src/dns_answer.c, src/error.c, src/conf-lex.l.in, src/conf-parse.y: + Update copyright dates, fix some minor bugs. Update copyright dates. + cvs add missed consts.c. + +2001-03-28 Thomas Moestl + + * src/cache.c, src/hash.c, src/error.c, src/servers.c, src/dns_answer.c, version: + Bump version to 1.1.3p4 + Fix some non-critical locking issues (none of them could be fatal). + Adjust copyright dates. + + * src/hash.c: Make the hash compare case insensitive. + +2001-03-25 Thomas Moestl + + * contrib/Makefile.am: Add Id tag to Makefile.am + + * src/cache.c, src/dns_answer.c, src/icmp.c: + Some more type fixes overlooked in last commit. + + * src/conf-parse.y, src/conff.h, src/dns.h, src/dns_answer.c, src/dns_query.c, src/icmp.c: + More type cleanups. Use time_t for time specifications throughout, and + make lengths singed longs. Cast cleanup in icmp.c to fix alpha + unalinged access faults. + + * contrib/dhcp2pdnsd, contrib/pdnsd_dhcp.pl, contrib/save_ram.pl, contrib/Makefile.am, contrib/README, configure.in, version, Makefile.am: + It's 1.1.3p3 now. + Change the contrib infrastructure: there is a Makfile.am in contrib/ + now. Rename Marko Stolle's pdnsd_update.pl to pdnsd_dhcp.pl and bring + it up to date (adding the rc script and save_ram.pl). + + * src/helpers.c, src/dns.c, src/dns_query.c, AUTHORS, THANKS: + Bring in Bjoern Fischer's changes to make pdnsd conserve the case of + cached names, and add him to AUTHORS and THANKS. + + * configure.in: The gdbm backend is discontinued. + + * src/cache.c, src/hash.c: + Cleanup and small bugfixes of the cache code (esp. locking). + + * AUTHORS, THANKS, file-list.base.in, pdnsd.spec.in: + SuSE fixes by Christian Engstler. + Add him to AUTHORS, THANKS. + +2001-03-14 Thomas Moestl + + * src/dns_query.c: + Fix a bug that could cause servers that were not used in the first + parallel query not to be used at all (failure would be returned + instead). + +2001-03-13 Thomas Moestl + + * src/icmp.c: Add define for ip_p equivalent on Linux. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/cache.c, src/dns_query.c, src/icmp.c, src/status.c, src/conf-parse.y, src/dns_answer.c, version: + Bump alpha version, more alignment fixes. All casts should be correct + now. + +2001-03-12 Thomas Moestl + + * src/dns_answer.c, src/dns_query.c, AUTHORS, THANKS: + Add the alpha fixes by P.J. Bostley, and add him to THANKS and AUTHORS. + +2001-03-10 Thomas Moestl + + * src/dns.h, src/helpers.h: + Remove prototype for removed function strtolower. + Use unit16_t and uint32_t instead of unsinged short/long for dns + protocol structures. + +2001-02-25 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c, src/status.c, src/conf-lex.l.in, src/conf-parse.y, AUTHORS, Makefile.am, version: + Add MX and CNAME for rr sections in the config file and MX setting + for pdnsd-ctl. + Typo fixes. + + * src/netdev.c: Two more fixes. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/cache.c, src/dns.c, src/main.c: + More small robustness fixes. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/netdev.c, src/status.c, src/status.h, src/conf-parse.y, src/helpers.c, src/main.c, configure.in, version, Makefile.am, NEWS: + A batch of robustness fixes. Move the status socket to the cache + directory. Various cleanups. + It's 1.3 now (hopefully to be released soon). + +2001-02-21 Thomas Moestl + + * src/main.c, src/conf-lex.l.in: + Fix breakage of the -mtu option and the query_method option (the parser + would not recognize constants that contained underscores). + +2001-02-20 Thomas Moestl + + * contrib/README, contrib/pdnsd_dhcp.pl, AUTHORS, Makefile.am, THANKS, file-list.base.in: + Add Marko Stolle's pdnsd_update.pl DHCP update script, add him to THANKS, + and bring a contrib/ directory in place. + +2001-02-15 Thomas Moestl + + * src/dns_answer.c, configure.in, version: + Some minor build & misc fixes. Bump version to 1.1.2a and release a + version with the spec file fixes to get proper Red Hat RPM's. + +2001-02-09 Thomas Moestl + + * NEWS: Bring NEWS up to date. + + * src/icmp.c: Do not close the socket on error. + + * pdnsd.spec.in: Add spec file fixes for man pages by Sourav K. Mandal + +2001-02-07 Thomas Moestl + + * version: It is now 1.1.2. + + * src/dns_query.c, src/main.c, Makefile.am, THANKS: + Fix a too strict length checking that could cause SERVFAIL to be returned + when the server returned NXDOMAIN. Add Markus Storm to THANKS (he has + reported this bug and supplied helpful information). + Minor tweaking in main.c. + Remove emptying of GZIP_ENV in Makefile.am (this normally contains --best). + +2001-01-27 Thomas Moestl + + * AUTHORS, THANKS: + Add Michael Wiedmann to AUTHORS and THANKS for his pdnsd-ctl.8 man page. + + * doc/Makefile.am, doc/pdnsd-ctl.8, configure.in, Makefile.am: + Add the pdnsd-ctl man page contributed by Michael Wiedmann. For this to + build in a correct way, add doc/Makefile.am and move all doc and + pdnsd.conf.sample related stuff in there. + +2001-01-25 Thomas Moestl + + * src/main.c: Removed unneeded for the non-O_NOFOLLOW case. + +2001-01-24 Thomas Moestl + + * src/main.c: + Add a fchown and a fchmod to the new non-O_NOFOLLOW case (not yet used). + + * src/conf-parse.y, src/main.c, src/status.c: Misc small fixups. + + * version: It's called 1.1.1 now. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/status.c, src/main.c: + Fix command line parsing. Add code to securely create pid files under + OSs that do not support the O_NOFOLLOW flag (those OSs are not supported + yet, though). + Fix a possible race condition in socket creation/chmod. We now create + a directory in /tmp (or whatever TEMPDIR was set) to hold the socket. + + * src/dns.c, src/dns_answer.c, src/icmp.c, src/main.c, src/status.c: + Another slew of copyright notice upgrades. + + * version, configure.in: + Bump beta revision, fix typo (missing $) in configure.in + + * src/dns.c, src/dns_answer.c, src/status.c: + Silence BSD compile time warnings. + + * configure.in: + Cleanup, add autoconf code for building pdnsd on FreeBSD-CURRENT with the + new additionally-linked libc_r. + +2001-01-16 Thomas Moestl + + * src/dns_answer.c, src/icmp.c, version: + Bump beta revision, fix a comment. Also, generate ping id's using pdnsd's + random wrappers instead of using rand() for paranoia. + +2001-01-15 Thomas Moestl + + * src/helpers.c, configure.in: Improve wording. + + * src/helpers.c: Update copyright year (forgotten in last commit). + + * src/dns_answer.c, src/helpers.c, src/main.c, acconfig.h, configure.in, version: + Bump versions. Small fixes (move socket intitializations from + udp_server_thread to init_udp_sockets to prevent warning when startup + takes long. + Make arc4random an option for a query id RNG and make it the default + on FreeBSD. + +2000-12-07 Thomas Moestl + + * src/conf-parse.y, src/main.c, version: + We are at 1.1.1p1. Removed the exec-uptest security warning printef if no + explicit user is given in the strict_setuid case (it is not needed there, + and confuses users). + +2000-11-28 Thomas Moestl + + * src/cache.c, src/helpers.c: + Converted cache locks to use condition vars and have lock contention + prevention. Added comments where not converted. + +2000-11-25 Thomas Moestl + + * AUTHORS, THANKS, pdnsd.spec.in: + Added spec file patches by Bernd Leibing and added him to AUTHORS and + THANKS. + +2000-11-21 Thomas Moestl + + * src/rc/SuSE/Makefile.am: Fixed a hopefully last SuSE rpm build bug. + + * src/rc/SuSE/Makefile.am: + Another one: allow rc.conf manipulation to fail for a clean + rpm build (SuSE only). + + * file-list.base.in: + Last-minute fix: correct filelist for rpm build to reflect the new name + for the sample configuration. + + * version: It's 1.1.0 now. + +2000-11-18 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl.c, src/cache.c, src/dns_query.c, version: + Fixed a condition where the cache code did not give up a lock. + Made the udp code use connect(). + Some small changes. + +2000-11-16 Thomas Moestl + + * version: Calling it 1.1.0b3. + +2000-11-15 Thomas Moestl + + * src/test/Makefile.am, src/pdnsd-ctl/Makefile.am, src/cache.c, src/Makefile.am, src/dns_answer.c, src/error.h, src/icmp.c, src/icmp.h, src/main.c, src/netdev.c, src/servers.c, src/thread.c, Makefile.am, configure.in, version: + Enabled new rr support by default (some resolvers don't seem to like not + supported answers - not our bug, but well). + Made some globals volatile to avoid being bitten by optimisations. + +2000-11-12 Thomas Moestl + + * TODO, version: Called it the first beta. + +2000-11-11 Thomas Moestl + + * src/cache.c, src/conf-lex.l.in, src/conf-parse.y, doc/pdnsd.conf.in: + renanmed rrneg to neg in the config file. + Misc small fixes. + pdnsd-ctl record xxx inval will now also invalidate local records. + + * src/conf-lex.l.in, src/conf-parse.y, src/dns_answer.c, src/status.c, pdnsd.spec.in: + Added --sysconfdir=/etc as argument to configure in the spec file. + Implemented the new rrneg config file section. + + * src/test/Makefile.am, src/pdnsd-ctl/Makefile.am, src/pdnsd-ctl/pdnsd-ctl.c, src/cache.c, src/cache.h, src/status.c, src/status.h, TODO: + Added the neg option to pdnsd-ctl. + + * src/cache.c, src/Makefile.am, src/conf-lex.l.in, src/consts.h, src/dns.c, src/dns.h, src/dns_answer.c, src/dns_query.c, src/helpers.c, src/main.c, configure.in: + Assorted fixes. The new features should be stabilized by now, will + integrate the missing few features now. + Also actived the tcp server by default. + +2000-11-07 Thomas Moestl + + * src/dns_answer.c, src/dns_query.c, src/icmp.c, src/ipvers.h, THANKS, TODO: + Fixed a possible memory and socket leak reported by Erich Reitz. + Implemented udp source address discovery for FreeBSD. + + * src/dns_query.c: Part 2 of yesterdays fix. + +2000-11-06 Thomas Moestl + + * src/dns_query.c, version: + Fixed a bug reported by Erich Reitz: pdnsd could leak fd's and memory if + queries timed out. + + * src/cache.c, src/cache.h, src/Makefile.am, src/dns_answer.c, src/dns_query.c, TODO, configure.in: + Sorted out some bugs for the new neg cacheing. + +2000-11-05 Thomas Moestl + + * src/cache.c, src/dns_query.c, TODO: + Negative cacheing support is now present, but largely untested. + + * src/conff.c, TODO: + The output of pdnsd-ctl status is now complete with all currently + supported options. + + * src/conf-parse.y, src/conff.c, src/conff.h, src/consts.h, src/conf-lex.l.in: + Added the config file options for the nefative cacheing support. + +2000-11-04 Thomas Moestl + + * src/cache.c, src/cache.h, src/conf-parse.y, src/dns.c, src/dns_query.c, src/status.c, version: + The new cache infrastructure for negative cacheing is in place. + Using and testing it remains. + + * src/cache.c, src/cache.h: + First changes to support negative cacheing. This should not break + anything, but the cache file format will be incompatible. + + * src/main.c, src/dns_answer.c: + init_udp_socket() and init_tcp_socket() are now called after + daemonizing on FreeBSD, as bind wants to lock the fd which + can cause later calls to fail after an exit. + +2000-11-03 Thomas Moestl + + * src/dns_query.c, src/icmp.c, src/servers.c: + Minor bugfixes and repository cleanup. + +2000-11-02 Thomas Moestl + + * src/icmp.c, TODO, version: + Called it 1.0.16p4. Fixed some compatability problems with the new code; + the ipv4 implementation seems to be fairly stable, the ipv6 one needs + some testing with dest unreach messages. + + * src/icmp.c, src/main.c: + Rewrote large parts of the ping implementation to be more portable. + +2000-11-01 Thomas Moestl + + * acconfig.h, configure.in, version: + Some config fixes, version to 1.0.16p3. SOCKET_LOCKING should be + off by default, as sendmsg can block. + + * src/pdnsd-ctl/pdnsd-ctl.c, src/error.h, configure.in: + Removed -W* arguments from CFLAGS that were implied by -Wall. + + * src/thread.c, configure.in: + Added some more safety tests to configure.in, and made it give + an error on some conditions. Also made configure do poll and usleep + detectione. + + * src/cache.h, src/test/Makefile.am, src/dns_answer.c, src/error.c, src/error.h, src/helpers.c, src/main.c, src/servers.c, src/status.c, src/thread.c, src/thread.h, src/Makefile.am: + Code cleanup. Beautified some macros, and moved the thread + specific things from error.[ch] over to the new thread.[ch]. + Also introduced usleep_r which tries to be thread safe for + different Unices. + +2000-10-31 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl, src/pdnsd-ctl/pdnsd-ctl.c: + The pdnsd-ctl binary got into cvs. Fixed that. + + * src/pdnsd-ctl/pdnsd-ctl, src/cache.c, src/cache.h, src/error.c, src/helpers.c, src/main.c, version: + Another set of FreeBSD compatability patches. This seems to catch + most of the problems, and pdnsd should be useable with libc_r now. + +2000-10-30 Thomas Moestl + + * src/pdnsd-ctl/pdnsd-ctl, src/conff.c, src/dns_answer.c, src/dns_query.c, src/helpers.c, src/icmp.c, src/main.c, AUTHORS, Makefile.am, THANKS, configure.in, version: + FreeBSD fixes, mostly contributed by Roman Shterenzon. + +2000-10-25 Thomas Moestl + + * src/pdnsd-ctl/Makefile.am, src/pdnsd-ctl/pdnsd-ctl: + pdnsd-ctl was not in cvs. + + * src/dns_query.c, src/error.h, configure.in: Some fixups for 1.0.15. + +2000-10-23 Thomas Moestl + + * src/dns_answer.c, src/dns_query.c, configure.in: + Several fixes for pdnsd to work better when it receives error replys. + + * src/dns.c, src/dns_answer.c: + Fixed another memory leak on an error path in dns_answer.c and did + a pointer signedness fixup in dns.c + +2000-10-21 Thomas Moestl + + * src/dns_answer.c, AUTHORS: + Applied a patch by Paul Wagland that fixes some spelling mistakes + and some memory leaks on error paths. + + * src/dns_query.c, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns_answer.c, NEWS, version: + Bug fixes. Added the randomize_recs option and turned it on + by default. + +2000-10-20 Thomas Moestl + + * src/helpers.c, src/dns.c, src/dns_query.c: + Fixes for the paranoid option to work with root servers + properly. + + * src/dns_query.c, src/dns.h, src/dns_answer.c, AUTHORS, THANKS: + Applied a patch by Paul Wagland for bind9-compatability and added + him to AUTHORS and THANKS. + +2000-10-19 Thomas Moestl + + * src/dns_answer.c, NEWS, version: + Another POLL_* fix. It is now called 1.0.14. + + * src/dns_answer.c, src/dns_query.c, src/icmp.c: BSD build fixes. + + * src/dns_query.c: + Made p_recurdive_query return immediately if a query returns + NXDOMAIN. + + * src/dns_query.c, Makefile.am: + Some bugifixes. It is now called 1.0.13. Releasing. + + * src/cache.c, src/dns_query.c, AUTHORS, NEWS: + Updated AUTHORS and NEWS. Made destroy_cache() lock the cache so + that no thread can access the cache afterwards (could lead to + crashes). + + * src/helpers.c, NEWS, THANKS: + Integrated a security fix contributed by Olaf Kirch: when + changing user IDs, pdnsd did not reinitialize the supplementary + group list, meaning that the process still had the privileges + of the supplementary groups the original user was member of. + + * src/conf-lex.l.in, src/conf-parse.y, Makefile.am, TODO, version: + Introduced the par_queries option. + + * src/dns_answer.c, src/dns_query.c, TODO: + Updated TODO, did some fixups for string handling. + + * HACKING: Added HACKING with some comments about coding style. + +2000-10-18 Thomas Moestl + + * src/dns_answer.c, src/dns_query.c, src/error.h, src/main.c, TODO: + Revieved and fixed the new dns_query.c-poll/select loops. + + * src/test/tping.c, src/dns_query.c, src/icmp.c: + Fixed the new poll/select ping support. + +2000-10-17 Thomas Moestl + + * src/dns_query.c, src/icmp.c, TODO: + Got rid of the O_NONBLOCK loop in the icmp.c ping implementation. + Beta tesing pending. + + * src/rc/Debian/Makefile.am, src/conff.c, src/conff.h, src/dns_query.c, src/dns_query.h, THANKS, TODO, acconfig.h, configure.in: + Corrected the Debian rc script (bug reported by Michael Müller). + Got rid of the nonblocking socket things in dns_query.c, and + using poll/select now. + Testing (esp. --no-poll) remains. + + * src/dns_answer.c: + Got rid of O_NONBLOCK read loops in dns_answer.c, using poll/select + now instead (after one issue about boundaries was cleared up). + +2000-10-16 Thomas Moestl + + * src/rc/SuSE/Makefile.am, src/rc/RedHat/Makefile.am, src/rc/Debian/Makefile.am: + The generated rc scripts do not need to be in the distribution. + + * src/conff.c, src/main.c: + Fixed a server structure members in conff.c. Only delete the socket + if we are in status pipe mode now. + + * src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns_answer.c, src/dns_query.c, acconfig.h, configure.in: + Added the --enable-tcp-subseq and --with-tcp-qtimeout configure + options, added the tcp_qtimeout conf file option, tested things. + 1.0.12 is ready for release. + +2000-10-15 Thomas Moestl + + * src/dns_answer.c, TODO, acconfig.h: + Added TCP timeouts to the answer code. Still need an option in the + conf file and documentation for that (besides beta testing). + + * src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/consts.h, src/dns_query.c, src/helpers.c, src/helpers.h, NEWS, TODO: + Introduced domain inclusion/exclusion lists in the server section + (new options include=, exclude=, policy=). + +2000-10-14 Thomas Moestl + + * src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns_answer.c, src/main.c, NEWS, TODO, version: + Upped version, updated NEWS and TODO and implemented a process + count limit. + +2000-10-13 Thomas Moestl + + * src/rc/Debian/pdnsd.in, src/main.c: + Added the --pdnsd-user option, and made the Debian rc script + use it rather than trying to parse the config file itself. + +2000-10-11 Thomas Moestl + + * src/rc/SuSE/pdnsd, src/rc/SuSE/pdnsd.in, src/rc/RedHat/pdnsd, src/rc/RedHat/pdnsd.in, src/rc/Debian/pdnsd, src/rc/Debian/pdnsd.in, AUTHORS, THANKS, configure.in: + Added the 'configure'-able rc scripts contributed by Carsten Block + and added him to THANKS and AUTHORS. + + * src/main.c: + Added O_NOFOLLOW to the pidfile open() call (if it is defined) + to prevent users creating files as the pdnsd user (using links) + if the admin put the pidfile in a world-writeable directory + against all good advice. + This is not a bug fix! Admins were not, and are still not supposed + to put the pidfile in a directory that is writeable for untrusted + users! + +2000-10-10 Thomas Moestl + + * THANKS: Added Milan P. Stanic to THANKS. + + * src/main.c: + Fixed a missing O_WRONLY in the open() call for pidfile operation. + +2000-10-08 Thomas Moestl + + * src/Makefile.am, src/dns.c, src/dns_answer.c, configure.in, version, acconfig.h: + Released 1.0.11. + Two security fixes in dns.c and dns_answer.c, and misc. smaller issues. + + * src/Makefile.am, src/conf-parse.y, src/dns_answer.c, src/dns_query.c, src/icmp.c, src/servers.c, AUTHORS, THANKS, TODO, acconfig.h, configure.in, version: + 1.0.10 was released some time ago ;-) + This had some IPv6 fixes. + Also fixed minor bug when using SOCKET_LOCKING. + +2000-08-28 Thomas Moestl + + * src/dns_answer.c: Fixed a parameter mismatch in getsockopt() + + * Makefile.am: + Applied Sourav K. Mandal's rpm build patch to the toplevel + Makefile.am + +2000-08-27 Thomas Moestl + + * src/conf-lex.l.in, src/conf-parse.y, src/consts.h, src/servers.c, version: + Added diald support. It's now called 1.0.9. + + * src/conf-parse.y, src/conff.c, src/netdev.c, pdnsd.spec.in: + Fixed some ugly typos in conf-parse.y and netdev.c. + Since I have no further bug reports and these bugs make some + things inconvenient, I will release 1.0.9 immediately. + +2000-08-26 Thomas Moestl + + * pdnsd.spec.in: small spec fix. + + * NEWS, configure.in: Last fixups for 1.0.8. Released it. + + * Makefile.am: Set mode and owner for cache file. + + * src/conf-parse.y, src/dns_answer.c, src/netdev.c, acconfig.h, configure.in, version: + Misc fixes. Hopefully fixed the UDP socket problems under Linux SMP. + +2000-08-20 Thomas Moestl + + * src/cache.c, src/dns_answer.c, AUTHORS, THANKS, configure.in, pdnsd.spec.in, version: + Build fixes by Alexandre Nunes, spec fixes (does now set distro for + configure), first attempt at an "error in udp send"-fix, and fix + for a problem with having records for the root domain in the disk + cache file. + +2000-08-13 Thomas Moestl + + * src/netdev.h, src/servers.c, src/status.c, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/consts.h, src/dns.c, src/dns.h, src/main.c, src/netdev.c, AUTHORS, THANKS: + Some minor fixes. Integrated the ppp device patch by Ron Yorston. + +2000-08-12 Thomas Moestl + + * configure.in: + configure.in was missing in repository. Also removed debugging + flag for build. + + * src/main.c: Made the pid file handling safe for directories. + + * src/dns.c: Part II of the last fix. + + * src/dns.c: + Fixed a nasty bug in decompress_name which would produce errors very + rarely. That was a off-by-one bug, but on the safe side (no overflow, + stopping one by too early). + + * src/main.c: + Fixed several possible problems with strncat(). None of these was + critical or involved remote data. + +2000-08-08 Thomas Moestl + + * src/main.c: Changed FreeBSD signal latency to 250 ms. + + * src/main.c, acconfig.h: + A set of last-minute FreeBSD fixes. pdnsd does now NEED linuxthreads on + BSD. + +2000-08-07 Thomas Moestl + + * version: It's now called 1.0.7. + + * src/main.c, doc/pdnsd.conf.in, Makefile.am: Misc build&BSD fixes. + + * src/conff.c, src/conf-parse.y, version: + Version set to the hopefully last beta. Fixed the proxy_only option. + +2000-08-05 Thomas Moestl + + * src/rc/SuSE/Makefile.am, src/rc/RedHat/Makefile.am, src/rc/Debian/Makefile.am, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns_query.c, src/status.c, doc/pdnsd.conf.in, Makefile.am, TODO: + Added the proxy_only options. Some build fixups. + +2000-07-30 Thomas Moestl + + * src/rc/SuSE/Makefile.am, src/rc/RedHat/Makefile.am, src/rc/Debian/Makefile.am, src/rc/Makefile.am, src/main.c, src/status.h, AUTHORS, INSTALL, Makefile.am, TODO, version: + Many small fixups for 1.0.7. + +2000-07-29 Thomas Moestl + + * src/rc/SuSE/Makefile.am, src/rc/RedHat/Makefile.am, src/rc/Debian/Makefile.am, src/rc/README, src/status.c, src/servers.c, Makefile.am, TODO, acconfig.h: + Assorted fixes. + + * src/cache.c, src/hash.c, src/dns.h, src/dns_answer.c, src/dns_query.c, src/icmp.c, src/ipvers.h, src/servers.c, src/servers.h, src/status.c, src/status.h, src/Makefile.am, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns.c, AUTHORS, Makefile.am, THANKS: + Big heap of updates and fixes. Incorporated build changes from Sourav + K. Mandal and pcmcia SCHEME support by Stephan Boettcher. + +2000-07-22 Thomas Moestl + + * src/rc/Debian/pdnsd: + Applied a patch by Markus Mohr to his debian rc script, which I had + broken in some way. + +2000-07-21 Thomas Moestl + + * src/cache.c, src/main.c, src/status.c, src/status.h: + Worked on the new status socket (pdnsd-ctl) option. + + * src/Makefile.am, version: Upped version, fixed Makefile.am + + * src/cache.c, src/hash.c, src/hash.h, src/cache.h, src/Makefile.am, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/dns.c, src/dns.h, src/dns_answer.c, src/dns_query.c, src/dns_query.h, src/helpers.c, src/helpers.h, src/ipvers.h, src/main.c, src/status.c, src/status.h, AUTHORS, Makefile.am, THANKS, acconfig.h: + Updated AUTHORS and THANKS. Merged in patches by Sourav K. Mandal + and Lyonel Vincent. + +2000-07-20 Thomas Moestl + + * doc/pdnsd.conf: Added pdnsd.conf. Well... + + * src/dns_query.c, src/dns_query.h, doc/pdnsd.conf: + Added some ommited files. + + * src/test/Makefile.am, src/test/if_up.c, src/test/is_local_addr.c, src/test/random.c, src/test/tping.c, src/rc/SuSE/Makefile.am, src/rc/SuSE/pdnsd, src/rc/RedHat/Makefile.am, src/rc/RedHat/pdnsd, src/rc/Debian/pdnsd, src/rc/Makefile.am, src/rc/README, src/Makefile.am, src/conf-lex.l.in, src/conf-parse.y, src/conff.c, src/conff.h, src/consts.h, src/dns.c, src/dns.h, src/dns_answer.c, src/dns_answer.h, src/error.c, src/error.h, src/helpers.c, src/helpers.h, src/icmp.c, src/icmp.h, src/ipvers.h, src/main.c, src/netdev.c, src/netdev.h, src/servers.c, src/servers.h, src/status.c, src/status.h, doc/pdnsd.conf.in, Makefile.am, acconfig.h, file-list.base.in, pdnsd.spec.in: + Checked in the pdnsd files at their new locations. + + * doc/pdnsd.conf, Makefile, a-conf.sh, cache.c, cache.h, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, consts.h, dns.c, dns.h, dns_answer.c, dns_answer.h, dns_query.c, dns_query.h, error.c, error.h, exec-flex.sh, hash.c, hash.h, helpers.c, helpers.h, icmp.c, icmp.h, ipvers.h, main.c, netdev.c, netdev.h, pdnsd-redhat.spec.templ, pdnsd-suse.spec.templ, servers.c, servers.h, status.c, status.h, version: + Removed the moved files. Will add the new ones soon. + +2000-07-16 Thomas Moestl + + * TODO: New tasks in TODO. + +2000-07-15 Thomas Moestl + + * TODO: + Updated TODO: Autoconf support was contributed by Sourav K. Mandal + + * conff.h, dns_query.c, ipvers.h, cache.c: + Fixed some minor bugs and a showstopper in cache.c that caused + crashes in some situations. + +2000-07-12 Thomas Moestl + + * dns_query.c, error.c, error.h, main.c: + Made pdnsd ignore SIGPIPE, which seemed to be responsible for some + crashes. + Accept (grudgingly) SOA rr's where NS ones would be The Right Thing. + +2000-07-10 Thomas Moestl + + * AUTHORS, THANKS, conff.c: + Updated AUTHORS, THANKS, and the fprintfs for the status pipe in + conff.c + + * TODO, config.h.templ, dns.h, dns_answer.c, dns_query.c, dns_query.h, main.c, version: + Added UDP queries and gave the user the choice between TCP and UDP + queries (UDP is the default now). Made the TCP server optional. + Fixed a authoritative record handling bug. Added pidfile support. + +2000-07-07 Thomas Moestl + + * doc/pdnsd.conf: + Inserted run_as="nobody"; again, it is The Right Thing and people + should use it. + + * Makefile: + The pdnsd cache directory is now created as nobody, since the + default run_as in the example pdnsd.conf is also nobody. + + * doc/pdnsd.conf: + Commented the run_as option out (people may run into permission + problems). + + * version: Upped version to 1.0.5 + + * AUTHORS, THANKS, conf.l.templ, conf.y, conff.c, conff.h, dns_answer.c, icmp.c, icmp.h, main.c, version: + Folded in the server_ip option code as contributed by Wolfgang Ocker + and extended it to IPv6. Fixed a bug in IPv4 ping in IPv6 mode. + +2000-07-06 Thomas Moestl + + * cache.c, dns_query.c: + Killed a bug which could cause crashes with more than 2 servers. + + * cache.c: Fixed a bug reported by Bert Frederiks that would break the + serve_aliases option when only one character was between official + name and alias in the /etc/hosts-style file. + +2000-07-04 Thomas Moestl + + * pdnsd-suse.spec.templ: The SuSE spec now uses the new makefile rule. + + * Makefile, THANKS, dns_query.c, helpers.c, version: + Added people to THANKS, fixed a bug that caused uppercase hosts/ + rr-section entries to be ignored in the cache, fixed the SuSE + makefile for pdnsd to run_as nobody, and other small fixups. + +2000-07-03 Thomas Moestl + + * dns_answer.c: + First change after release of 1.0.4: The questions received + are now properly written into the debug file when starting + with -g -d. + + * config.h.templ, dns_query.c: + Fixed a possible way to get around paranoid restrictions. + + * version: Set version to 1.0.4 + + * doc/pdnsd.conf: Added an entry for the paranoid option. + + * cache.c, config.h.templ, dns_answer.c, dns_query.c, ipvers.h: + Revisions and fixups. The complete code revision is now complete. + +2000-06-29 Thomas Moestl + + * dns_query.c: Overhaul. + + * dns_answer.c, dns_query.c, config.h.templ: + Code overhault continued. dns_answer.c is finished. + +2000-06-27 Thomas Moestl + + * conff.c, dns_answer.c, icmp.c, netdev.c, servers.c, status.c: + Continued code overhaul. Fixed several bugs, and simplified some + code. + + * conf.l.templ, conf.y, conff.c, ipvers.h, version: Fixups. + +2000-06-26 Thomas Moestl + + * hash.c: Revised; fixed a minor bug. + + * cache.c: Overhauled. + + * dns_query.c, error.c, helpers.c, helpers.h, ipvers.h, main.c, version, dns.c: + Manual code overhaul. Numerous small patches, greatly simplified + decompress_name(). + +2000-06-25 Thomas Moestl + + * config.h.templ: + Made the C random() RNG the default (using /dev/urandom, we suck up + too much randomness on high load). + + * error.c, error.h, icmp.c, icmp.h, main.c: + Small cleanups. Makes the testsuite compilation easier. + + * Makefile, config.h.templ: Preparing for release of 1.0.4. + +2000-06-24 Thomas Moestl + + * Makefile, THANKS, a-conf.sh, dns_answer.c, dns_query.c, error.c, version: + Fixed bugs with the paranoid option, connect() timeout handling, and + a incompatability in response handling that caused the glibc + resolver to misunderstand error messages pdnsd generated on unknown + query types. This bug, that was reported by James MacLean, could + for example cause ssh to hang some time. + + * Makefile, NEWS, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, dns.c, dns_query.c, dns_query.h, helpers.c, helpers.h, icmp.c, icmp.h, main.c: + Added the paranoid option, and modified the ping uptest so that it + works with strict_setuid. Also made strict_setuid=on the default. + 1.0.4 should be out soon. + +2000-06-23 Thomas Moestl + + * doc/pdnsd.conf: Added a run_as= line, which is sensible normally. + + * Makefile, conf.l.templ, conf.y, conff.c, conff.h, dns_answer.c, dns_answer.h, helpers.c, helpers.h, main.c, servers.c, status.c, version: + Some fixups, added the run_as and strict_setuid security options. + + * THANKS: Updated. + + * AUTHORS, ipvers.h, main.c, netdev.c, version: + Fixed some definitions for glibc2.0-users. Repaced the return at the + end of main() with _exit(). Should not build and run OK on glibc 2.0 + boxen. + Fixed a typo in netdev.c + + * ipvers.h: + Fixed a typo in ipvers.h to fix compile problems on systems without + an IPv6-supporting C library, and possible IPv6 problems using the + status pipe. + + * error.c, version: + Fixed a bug that could cause signals to be delivered to the wrong + process. + +2000-06-22 Thomas Moestl + + * version: Set version to 1.0.1. + + * cache.c, dns_answer.c, error.c, error.h, main.c, pdnsd-suse.spec.templ: + Fixed misc issues reported by Jonathan Hudson and Joachim Dorner, one + of them a real showstopper in cache.c. + + * Makefile, NEWS, README, cache.h, config.h.templ, version: + Updated things for 1.0.0 and released it finally. + + * AUTHORS, THANKS: Updated THANKS and AUTHORS + + * NEWS, a-conf.sh, cache.c, conf.l.templ, conf.y, conff.c, conff.h, dns_answer.c, dns_query.c, error.c, error.h, main.c, servers.c, status.c: + Fixed a-conf.sh and cleaned up signal handling as far as it can be + done ;-). Added the max_ttl option. + +2000-06-21 Thomas Moestl + + * dns_answer.c, error.c, error.h, main.c, servers.c, status.c: + More signal fixes. This is a real pain with LinuxThreads. + + * NEWS, cache.c, dns_answer.c, error.c, error.h, helpers.c, helpers.h, main.c, servers.c, status.c, version: + Fixups for signal handling. This is more than only a little tricky + using the linuxthreads library. This hopefully fixes the deadlocks + we had on signals. + +2000-06-13 Thomas Moestl + + * AUTHORS, THANKS: Updated credits. + + * a-conf.sh: + A primitive configure-like script intended as drop-in replacement + until autoconf support finally comes. + + * .cvsignore, Makefile, cache.c, dns_query.c, ipvers.h, servers.c, version: + Added a primitive configuration script as drop-in. Killed some bugs + and changed the recently added linkdown_kluge option following + suggestions from Daniel Smolik. + +2000-06-12 Thomas Moestl + + * dns_query.h, exec-flex.sh, Makefile, cache.c, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, dns_query.c: + Numerous cleanups and fixes. Implemented the linkdown_kluge option + as proposed by Daniel Smolik. Hope to get ready for 1.0.0 know. + +2000-06-10 Thomas Moestl + + * Makefile, NEWS, TODO, dns_answer.c: + Modified some stuff in dns_answer.c (if no nameserver for a knot in + the dns namespace is found now, its predecessors are tried now in + order to return accurate authority results). This will be paid with a + little more beta time, so the Makefile has developer switches again. + Corrected NEWS and TODO. + + * Makefile, config.h.templ, dns_answer.c, dns_query.c, dns_query.h, hash.h, helpers.c, version: + Removed some dead code, fixed some really minor bugs. Version is up + to 1.0.0p7, which is hopefully the last beta. + + * Makefile, config.h.templ: + Fixed things up for the 1.0.0 distribution version + +2000-06-06 Thomas Moestl + + * Makefile, config.h.templ, icmp.c, netdev.c: + Some minor comment fixes. + + * Makefile, TODO, main.c, version: + BSD fix in Makefile and help update. It is now called 1.0.0p6. TODO + was updated to reflect the project status. + + * dns_answer.c: + BSD & misc fixes. pdnsd runs now nicely on my FreeBSD 4.0 box. + + * dns_answer.c, ipvers.h: + Fixed IPv6 UDP dest address recovery. Also fixed a real stupid bug in + ipvers.h. + + * cache.h, dns_query.c, error.h: + Added DEBUG_MSG6 macros. Cleaned up requery handling. + + * dns.c, dns_answer.c, dns_query.c, dns_query.h: + Fixed another heap of bugs, introduced some sanity checks, no requery + on answers that have ra not set now. + +2000-06-05 Thomas Moestl + + * cache.c: + Fixed write_disk_cache. + + * cache.c, cache.h: + Fixes for rr handling. + +2000-06-04 Thomas Moestl + + * cache.c, dns_answer.c, dns_query.c: + Fixes again: some missing checks for rrset existence added. + + * cache.c, dns_answer.c, helpers.c, icmp.c: + Fixes for the new/modified code and its side effects on old code ;-) + + * ChangeLog.old, NEWS, cache.c, conf.l.templ, conf.y, conff.c, config.h.templ, dns.c, dns_answer.c, dns_query.c, error.c, hash.c, helpers.c, icmp.c, main.c, netdev.c, servers.c, status.c: + Folded the ChangeLog and NEWS of the 0.9.x tree back in and added NEWS for the + upcoming 1.0.0 release. Some compile fixes. Reorganized config.h.templ. Made + the inclusion of the rcsid strings into the executable optional. + + * cache.c, dns_answer.c: + Pile of fixes on recently added/modified code. + +2000-06-03 Thomas Moestl + + * .cvsignore, Makefile, lex.inc.h: + lex.inc.h should not be in CVS (it is automatically generated by + exec-flex.sh). It should also be deleted by 'make mclean'. + + * TODO, cache.c, dns_answer.c, dns_query.c, lex.inc.h: + rfc2181 conformance should be reached by now. Updated TODO. Bugfixing + remains. + + * doc/html/.cvsignore, doc/html/dl.html, doc/html/doc.html, doc/html/faq.html, doc/html/index.html: + Removed the html documentation from CVS. It is maintained separately. + + * doc/pdnsd.conf: + Added CVS/RCS $Id$ tag. + + * cache.h, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, consts.h, dns.c, dns.h, dns_answer.c, dns_answer.h, dns_query.c, dns_query.h, error.c, error.h, exec-flex.sh, hash.c, hash.h, helpers.c, helpers.h, icmp.c, icmp.h, ipvers.h, main.c, netdev.c, netdev.h, pdnsd-redhat.spec.templ, pdnsd-suse.spec.templ, servers.c, servers.h, status.c, status.h, version, AUTHORS, INSTALL, Makefile, NEWS, README, THANKS, TODO, cache.c: + Added CVS/RCS $Id$ tags to most files, did some cleanups, introduced + the new rrset granularity caching. The new code is still much of beta, + use with care. + +2000-06-01 Thomas Moestl + + * Makefile, cache.c, hash.c, helpers.c, icmp.c, netdev.c: + Yet another set of BSD fixes (test programs do now work for me + under FreeBSD). Some other minor fixes. + + * Makefile, error.c, error.h, helpers.c, helpers.h: + Transplanted kill_pdnsd from error.c to helpers.c in order to get the + tests compiled without the thread library. + +2000-05-31 Thomas Moestl + + * pdnsd: + Ooops, executable got in. + + * Makefile, pdnsd: + Added test suite programs. + + * icmp.c, netdev.c: + All basic BSD patches have been folded in. pdnsd will now compile on + FreeBSD with (hopefully) all features. + + * dns_answer.c, Makefile: + Disabled udp targed address discovery for BSD builds (this sadly ist + OS specific at least for IPv4. Must be rewritten under BSD as it is + an RFC compatability issue under some circumstances) + + * cache.c, cache.h, conf.y, conff.c, conff.h, config.h.templ, dns_answer.c, helpers.c, icmp.c, ipvers.h, netdev.c, Makefile: + BSD include & misc build fixes. More to follow... + + * Makefile, cache.h: + BSD Fixes: Makefile should work with BSD make, sed command line, + sorted out naming clash in cache.h + + * .cvsignore: + Added ChangeLog to .cvsignore + + * THANKS, conff.c: + Fixed a bug reported by Jonathan Hudson and added him to THANKS + + * ChangeLog.old: + Added the pre-CVS ChangeLog. + + * .cvsignore, AUTHORS, COPYING, INSTALL, Makefile, NEWS, README, THANKS, TODO, cache.c, cache.h, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, consts.h, dns.c, dns.h, dns_answer.c, dns_answer.h, dns_query.c, dns_query.h, doc/.cvsignore, doc/html/dl.html, doc/html/doc.html, doc/html/faq.html, doc/html/index.html, doc/pdnsd.conf, doc/txt/.cvsignore, error.c, error.h, exec-flex.sh, hash.c, hash.h, helpers.c, helpers.h, icmp.c, icmp.h, ipvers.h, lex.inc.h, main.c, netdev.c, netdev.h, pdnsd-redhat.spec.templ, pdnsd-suse.spec.templ, servers.c, servers.h, status.c, status.h, version: + Initial import of pdnsd-1.0.0p3 source tree into CVS. + + + * .cvsignore, AUTHORS, COPYING, INSTALL, Makefile, NEWS, README, THANKS, TODO, cache.c, cache.h, conf.l.templ, conf.y, conff.c, conff.h, config.h.templ, consts.h, dns.c, dns.h, dns_answer.c, dns_answer.h, dns_query.c, dns_query.h, doc/.cvsignore, doc/html/dl.html, doc/html/doc.html, doc/html/faq.html, doc/html/index.html, doc/pdnsd.conf, doc/txt/.cvsignore, error.c, error.h, exec-flex.sh, hash.c, hash.h, helpers.c, helpers.h, icmp.c, icmp.h, ipvers.h, lex.inc.h, main.c, netdev.c, netdev.h, pdnsd-redhat.spec.templ, pdnsd-suse.spec.templ, servers.c, servers.h, status.c, status.h, version: + New file. + diff --git a/jni/pdnsd/ChangeLog.old b/jni/pdnsd/ChangeLog.old new file mode 100644 index 00000000..0b3553e2 --- /dev/null +++ b/jni/pdnsd/ChangeLog.old @@ -0,0 +1,161 @@ +2000-02-15 + Version 0.2. First working alpha with the extended feature set. + +2000-02-16 + Version 0.3 with many bugfixes, better standard conformity and + some new features. + +2000-02-17 + Did a lint on the code, implemented soft timeouts, again bugfixes, + drastically reduced cache memory requirements, implemented local + records. + Version 0.4 released. + +2000-02-19 + Recursive query finally implemented. Version 0.5 out. + +2000-02-20 + Various bugfixes. The server now always tries to get an AA answer + if possible; this implies recursion. This is to deal better with + caching servers that may return incomplete results on * queries. + This may be a little sub-optimal since it may not take the full + effect of caching, but it is the only real possibility of getting + complete records. + Redid the deps in the makefile for now. + Version is now 0.6. + +2000-02-21 + Another set of bugfixes. Version is 0.6.1. + +2000-02-22 + Another set of bugfixes. It should stabilize by now. Answer compression + is there finally. Version is therefore up again, 0.7 by now. + +2000-02-23 + Minor bugfixes, isdn interface uptest added. The new record types as of + rfc1700 are implemented, but as a compile-time option, since normally + there is no need to waste space for them. + Version is 0.7.1. + +2000-02-24 + Version 0.7.2 with all rrs up to KX (36). #define DNS_NEW_RRS in + config.h and (re)compile if you want to use them. Delete the cache + file before using a version with this option changed! + NSAP-PTR does NOT WORK (any incoming answer containing it may cause + a format error) because it is ill-designed (see TODO). Never mind, it + is officially deprecated anyway. + The secure DNS extension record types defined in RFC 2065 (KEY, SIG, + NXT) are cached only and therefore useless. + +2000-02-26 + Version 0.8 with parallel query (and probably new bugs) introduced. + +2000-02-27 + Version 0.8.1 with minor bugfixes on the new features. + +2000-02-27 + Version 0.8.5 with authority support and the usual bugifxes. Some issues + with standard conformity were also fixed (wow, two versions a day). + +2000-02-28 + Implemented caching of non-authoritative records. This allows better + usage of other caching name servers. This may return non-authoritative + records to any non-wildcard query. If a wildcard query arrives, we + always look for authoritative records, so we do if the non-authoritative + answer does not contain at least one answering record to the query. + This fixes the sub-optimal behaviour since 0.6. + Version is therefore up to 0.8.7 (0.8.6 was also released today + containing bugfixes) + +2000-02-29 + Better thread support, avoiding deadlocks in signal handling. The cost + is unfortunately one more thread. + New option server_port in config file. + Version is 0.8.8. + +2000-03-01 + Nailed a renitent memory leak bug to the wall (shame, what a trivial + mistake). Also improved handling of error conditions slightly. + Version is 0.8.9. + +2000-03-01 + Cache code cleanup. The development of the non-parallel query code + is discontinued, although it still works. If you want serial query, + just set PAR_QUERIES to 1. + Additional information finally implemented. + We are up to 0.9. + +2000-03-02 + Fixed a DoS possibility. + More rfc compatability fixups and a smarter resolver logic. + Version 0.9.1 + +2000-03-02 + Added the source section to the config file handling. This allows to + source your /etc/hosts file. Version 0.9.2. + +2000-03-02 + Avoiding double additional records now. Version 0.9.3. + +2000-03-09 + Fixed some REALLY STUPID bugs. Uuummph, thought it was finished. + However, the number of bugs remaining is always n+1... + Anyway, we are up to 0.9.4. Hope that there are no mean bugs left. + +2000-03-14 + Added another uptest, exec. See README for details. Also grained the + cache size finer (it's now specified in kB). Version 0.9.5 + +2000-04-07 + Fixed some really stupid bugs, what else? Version is 0.9.6 + To be more exact: fixed misc bugs, cleaned up hash.c and cache.c + +2000-04-20 + Again fixed some bugs, version is now 0.9.7. + +2000-04-29 + Fixed a build problem caused by some missing #defines in glibc2.0 and a + minor bug. + Version is up to 0.9.8 + +2000-04-30 + Fixed some unclean C code and did a general C lint. Thanks to Byrial + Jensen for pointing out some issues. Now using stricter compiler flags. + Also replaced the daemon() call in main.c for improved portability. + Pre-Released 0.9.9p1 + +2000-05-03 + Released 0.9.9p2 with the changes of 0.9.9p1, Documentation updates, + bugfixes, and the Red Hat rc scripts contributed by Torben Janssen. + Also, the meaning of the command line option -v has changed. + There is a new config file option "lean_query" that is on by + default. It is an optimization, so please look in the docs when + updating whether you want it switched on or not. + Removed the long-dead serial query code from the distribution tree. + Some resolvers seem to be broken somehow in a respect that it cares + about order in which the records appear. In particular, it wants + cname to appear before other records. Ok, so it be... + + +2000-05-04 + Save all names in lower case in the rrs. + Tidying up the source tree. + The long-awaited cache structure changes have been started. Please + delete you cache files before using this new release. + +2000-05-05 + Fixed several bugs in the old and in the new source tree. + Use time_t instead of long for internal time storage for compatibility. + + +2000-05-06 + Version 0.9.10. + This fixes a bug in uptest=if. Red Hat and configuration fixes + suggested by Soeren J. Peters were included. + +2000-05-08 + Version 0.9.11 + This fixes a locally exploitable security problem (pdnsd.cache was + world-writeable). This is actually a one-line fix; for a description of + possible dangers, please refer to the html documentation. + Thanks to Alan Swanson for reporting. diff --git a/jni/pdnsd/INSTALL b/jni/pdnsd/INSTALL new file mode 100644 index 00000000..03991892 --- /dev/null +++ b/jni/pdnsd/INSTALL @@ -0,0 +1,190 @@ +The installation instructions are in doc/html/doc.html and doc/txt/manual.txt. +The system requirements are listed in doc/html/index.html and doc/txt/intro.txt. +I recommend using the html version. +Following are generic installation instructions for autoconf programs. +I strongly recommend to read the Installation section in the docs! + + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/jni/pdnsd/Makefile.am b/jni/pdnsd/Makefile.am new file mode 100644 index 00000000..146c32a5 --- /dev/null +++ b/jni/pdnsd/Makefile.am @@ -0,0 +1,40 @@ + +SUBDIRS = src doc contrib + +EXTRA_DIST = version ChangeLog.old COPYING.BSD README.par README.par.old PKGBUILD + +# The sample configuration is handled in doc/Makefile.am +install-data-hook: + $(mkinstalldirs) "$(DESTDIR)$(cachedir)" + test -f "$(DESTDIR)$(cachedir)/pdnsd.cache" || \ + touch "$(DESTDIR)$(cachedir)/pdnsd.cache" + if test `whoami` = "root"; then \ + chown $(def_id) "$(DESTDIR)$(cachedir)/pdnsd.cache"; \ + chown $(def_id) "$(DESTDIR)$(cachedir)"; \ + fi + chmod 0640 "$(DESTDIR)$(cachedir)/pdnsd.cache" + chmod 0750 "$(DESTDIR)$(cachedir)" + +dist-hook: $(PACKAGE).spec.in + sed -e '/^%{!?distro: %define distro /c\ + %if 0%{!?distro:1}\ + %if "%{_vendor}" == "redhat"\ + %define distro RedHat\ + %else\ + %if "%{_vendor}" == "suse"\ + %define distro SuSE\ + %else\ + %if "%{_vendor}" == "SuSE"\ + %define distro SuSE\ + %endif\ + %endif\ + %endif\ + %endif' \ + -e 's:[@]PACKAGE[@]:$(PACKAGE):g' \ + -e 's:[@]VERSION[@]:$(VERSION):g' \ + -e 's:[@]fullversion[@]:$(fullversion):g' \ + -e 's:[@]packagerelease[@]:$(packagerelease):g' \ + -e 's:[@]cachedir[@]:/var/cache/$(PACKAGE):g' \ + -e 's:[@]def_id[@]:$(PACKAGE):g' \ + $(PACKAGE).spec.in > $(distdir)/$(PACKAGE).spec + diff --git a/jni/pdnsd/Makefile.in b/jni/pdnsd/Makefile.in new file mode 100644 index 00000000..a865d546 --- /dev/null +++ b/jni/pdnsd/Makefile.in @@ -0,0 +1,734 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/PKGBUILD.in \ + $(srcdir)/config.h.in $(srcdir)/file-list.base.in \ + $(srcdir)/pdnsd.spec.in $(top_srcdir)/configure AUTHORS \ + COPYING ChangeLog INSTALL NEWS THANKS TODO acconfig.h compile \ + depcomp install-sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +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 = pdnsd.spec file-list.base PKGBUILD +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(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" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = src doc contrib +EXTRA_DIST = version ChangeLog.old COPYING.BSD README.par README.par.old PKGBUILD +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: 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 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +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) $(top_srcdir)/acconfig.h + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +pdnsd.spec: $(top_builddir)/config.status $(srcdir)/pdnsd.spec.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +file-list.base: $(top_builddir)/config.status $(srcdir)/file-list.base.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +PKGBUILD: $(top_builddir)/config.status $(srcdir)/PKGBUILD.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +# 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. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; 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" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +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 \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + 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 + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -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) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__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*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(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 \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(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__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: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { 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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +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 + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-data-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-hook dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-data-hook 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 pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am + + +# The sample configuration is handled in doc/Makefile.am +install-data-hook: + $(mkinstalldirs) "$(DESTDIR)$(cachedir)" + test -f "$(DESTDIR)$(cachedir)/pdnsd.cache" || \ + touch "$(DESTDIR)$(cachedir)/pdnsd.cache" + if test `whoami` = "root"; then \ + chown $(def_id) "$(DESTDIR)$(cachedir)/pdnsd.cache"; \ + chown $(def_id) "$(DESTDIR)$(cachedir)"; \ + fi + chmod 0640 "$(DESTDIR)$(cachedir)/pdnsd.cache" + chmod 0750 "$(DESTDIR)$(cachedir)" + +dist-hook: $(PACKAGE).spec.in + sed -e '/^%{!?distro: %define distro /c\ + %if 0%{!?distro:1}\ + %if "%{_vendor}" == "redhat"\ + %define distro RedHat\ + %else\ + %if "%{_vendor}" == "suse"\ + %define distro SuSE\ + %else\ + %if "%{_vendor}" == "SuSE"\ + %define distro SuSE\ + %endif\ + %endif\ + %endif\ + %endif' \ + -e 's:[@]PACKAGE[@]:$(PACKAGE):g' \ + -e 's:[@]VERSION[@]:$(VERSION):g' \ + -e 's:[@]fullversion[@]:$(fullversion):g' \ + -e 's:[@]packagerelease[@]:$(packagerelease):g' \ + -e 's:[@]cachedir[@]:/var/cache/$(PACKAGE):g' \ + -e 's:[@]def_id[@]:$(PACKAGE):g' \ + $(PACKAGE).spec.in > $(distdir)/$(PACKAGE).spec + +# 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/jni/pdnsd/NEWS b/jni/pdnsd/NEWS new file mode 100644 index 00000000..9a83bba1 --- /dev/null +++ b/jni/pdnsd/NEWS @@ -0,0 +1,324 @@ +Version 1.2.9a fixes a bug in the 1.2.9 release that causes a build failure when +pdnsd is configured with --enable-strict-rfc2181. Unless you use this option to +compile pdnsd, there is no need to upgrade from 1.2.9 to 1.2.9a. + +Version 1.2.9 has support for many additional RR types, in particular those +needed for DNSSEC (though no support for the DNSSEC protocol itself yet in +pdnsd). Caching data structures are now more efficient when they only store the +most commonly used RR types. Fine-grained configurability over which RR-types +are cache-able. Pdnsd now has support for EDNS (Extension mechanisms for DNS), +although its usefulness is currently limited to enabling UDP messages larger +than 512 bytes. Defining local TXT records in the configuration file is now +supported. A new configuration option provides a fix in case the query uptest +fails due to remote servers ignoring empty queries. Several bugs have been fixed +including a UDP socket descriptor leak that affected the FreeBSD platform, and +an IPv6 port binding bug. + +Version 1.2.8 implements support for automatic discovery of root servers. +There are also some improvements in the resolver and a new default setting for +the neg_rrs_pol configuration option. + +Version 1.2.7-par fixes some security problems. It contains a fix for a +"dangling pointer" bug that could cause pdnsd to crash when it received a long +reply. It also addresses some of the issues raised in the CERT vulnerability +note VU#800113 by making the default of query_port_start equal to 1024, thereby +ensuring that source ports are randomly selected by the pdnsd resolver in the +range 1024-65535. This release also fixes problems with compiling pdnsd for the +ARM architecture and for the Darwin platform (Max OS X). There are a number of +(minor) new features. pdnsd now supports "include" files, essentially +configuration files that only contain definitions for local records. It is now +possible to define interactively, using pdnsd-ctl, any local record that can be +defined in a configuration file. + +Version 1.2.6-par has an upgraded license: GPL version 3. +A bug has been fixed which which caused pdnsd to handle NXDOMAIN replies +inefficiently when configured with neg_domain_pol=on. Also the code for the +ping test has been fixed, which was broken for 64-bit systems. A new option +randomize_servers can be used to give each server in a section of the +configuration file an equal chance of being queried. The new options reject, +reject_policy and reject_recursively make it possible to check for the presence +of certain IP addresses in the replies of name servers and to correct some types +of unwanted replies or to censor these IP addresses. +The pdnsd-ctl 'add a' and 'add aaaa' commands now allow multiple IP addresses to +be specified for the same name. There are some further improvements to pdnsd's +recursive resolver. + +Version 1.2.5-par introduces a new query method: udp_tcp. With this method a UDP +query is tried first and, if the UDP answer is truncated, the query is repeated +using TCP, which is the behaviour that seems to be recommended by the DNS +standards. There is a new configuration option use_nss, which can be turned off +to prevent lengthy timeouts and stalls in certain situations. A bug has been +fixed which could cause pdnsd to crash if debug output was generated before the +debug output stream was properly initialized. + +In version 1.2.4-par a memory leak and a minor buffer-overflow problem have been +fixed. There is now a fix for some situations that would previously cause pdnsd +to exit prematurely (such as ACPI S3 sleep or trying to attach strace to pdnsd). +Time intervals specified in the configuration file can now be expressed in +minutes, hours, days and weeks as well as seconds. Support for Apple Mac OS X +v10.4 Tiger has been improved. The "pdnsd-ctl status" command now also provides +some information about the status of the running threads. There are some further +improvements in the debugging information provided by pdnsd. +TCP-query support is now compiled in by default (but can still be disabled using +the configure option --disable-tcp-queries). + +In version 1.2.3-par the "pdnsd-ctl empty-cache" command can be provided with an +include/exclude list, allowing the user to specify a selection of names to be +removed, instead of emptying the cache completely. +Additional improvements: pdnsd should now remain responsive while executing the +"pdnsd-ctl empty-cache" command. With the query_method=tcp_udp option pdnsd will +now also try a UDP query after a TCP connection times out, which should allow +pdnsd to resolve the same names with query_method=tcp_udp as with +query_method=udp_only, although perhaps with an occasional delay. +"pdnsd-ctl config" or "pdnsd-ctl server" commands should now run without delays, +even if pdnsd is performing ping or query uptests at the time. A problem with +resolving certain names using root servers has been fixed. + +Version 1.2.2-par has a number of important portability improvements. A bug has +been fixed that prevented pdnsd from compiling successfully on some 64 bit +architectures. The code for determining endianness (most significant or least +significant byte first) should now be more portable. This release has +(experimental) support for the Darwin (Apple Mac OS X) platform. On Linux +systems, the configure script will now try to detect automatically whether the +system implements the Native POSIX Thread Library, but the method used may not +necessarily be foolproof. In addition, the debug features have been improved and +should make it easier to find out why pdnsd considers some queries or replies +malformed. + +Version 1.2.1-par has improved support for non-Linux platforms. This release has +(experimental) support for the Cygwin platform, and should also fix some +compilation glitches that have been reported by FreeBSD users. + +Version 1.2-par is a new and improved version of pdnsd! Most of the changes +effect the internal workings of pdnsd, but there are also a number of +interesting new features (well, I think they are interesting). Among the bugs +fixed are two rather nasty ones which involve the handling of NXT and NAPTR +records and which can cause pdnsd to crash or abort. The new features include a +new server availability test which can be specified with uptest=query, support +for reading the DNS configuration from resolv.conf files, a new option for +optimizing the use of root servers, a new option that makes defining local +records for reverse resolving easier, support for defining wildcard records, a +new pdnsd-ctl command for reloading the config file without restarting pdnsd, +and a new pdnsd-ctl command for dumping information about the names stored in +the cache. +The documentation has also been updated: there is now a pdnsd.conf man page. For +a more complete list of the changes I'll have to refer you to README.par and the +ChangeLog. + +Version 1.1.11a-par contains a fix for FreeBSD users that bypasses a problem +with the macro ENONET, which can cause a compilation failure when it is +undefined. Linux users will notice no difference between 1.1.11a-par and +1.1.11-par. + +Version 1.1.11-par has a rather large number of small changes, which are rather +difficult to summarize. Among the bugs fixed are a race condition in the cache +lookup code, a flaw in the code that caused a busy spin when a remote server +answered with "Not Implemented", and problems with the -4 and -6 command-line +options. Among the improvements are an alternative sorting algorithm which +should allow pdnsd to start up faster when reading a large cache file from disk, +automatic mapping of IPv4 to IPv6 addresses when running in IPv6 mode, somewhat +more efficient memory use, better compression of the replies and changes in the +parallel querying algorithm that should improve the chances of catching a reply +from a remote server. For a more complete list of the changes I'll have to +refer you to README.par and the ChangeLog. + +Version 1.1.10-par has a new parser for configuration files, completely +rewritten from scratch in C. The main advantages are: (f)lex and yacc/bison are +no longer needed to build pdnsd, more informative error messages instead of +merely "parse error", and string literals no longer need to be enclosed in +quotes in most cases. Furthermore, a bug has been fixed that caused incorrect +IPV6-type PTR records to be generated when sourcing /etc/hosts like files. +There have been other small changes, more details can be found in the ChangeLog. + +Version 1.1.9-par adds some missing pieces to the documentation (the pdnsd +manual and the man page for pdnsd-ctl). The changes to the code consist mostly +of optimizations, removal of some size limits due to fixed-size buffers, and +some cleaning up. I've also tried to make the error responses of pdnsd-ctl more +helpful. More details can be found in the ChangeLog. + +Version 1.1.8b1-par8 introduces a "delegation-only" feature that may be useful +for blocking Verisign's Sitefinder. The parser for the configuration file now +tolerates domain names missing a dot at the end. I have provided alternative +implementations for some GNU extensions that I used in an effort to make the +code more portable. In particular, the code should build on FreeBSD again. More +details can be found in the README.par file. + +Version 1.1.8b1-par7 fixing a number of bugs. I have also reworked some of the +code for adding and removing entries in the cache in an effort to improve +efficiency and stability. More details can be found in the ChangeLog. + +Version 1.1.8b1-par6 introduces some further code cleanup. In addition the +documentation has been revised. + +Version 1.1.8b1-par5 fixes a troublesome allocation size error that has been +discovered in Thomas Moestl's code. In practice this bug only wastes memory but +it could also potentially lead to memory corruption. Upgrading is +recommended. More details can be found in the ChangeLog. + +Version 1.1.8b1-par4 has been released. Due to incompatibilities between +various implementations of the pthread library on Linux systems, problems can +occur with signal handling in pdnsd. The usual symptom is failure by pdnsd to +save the cache to disk, and /var/cache/pdnsd/pdnsd.cache remaining empty. If you +experience this kind of trouble, try reconfiguring with different values for the +new --with-thread-lib option. The allowable values are described in the +documentation. + +pdnsd is no longer maintained by Thomas Moestl: I have not had time to maintain +pdnsd for quite a while now, and have been very slow to respond to issues, or +did not respond at all. It is time that I officially announce that pdnsd is no +longer actively maintained; I apologize to all those who reported bugs or asked +questions without receiving any reply. However, Paul A. Rombouts has published a +patch set against the last released version at +http://www.phys.uu.nl/~rombouts/pdnsd.html, which cleans up a lot of code fixes +many bugs. + +Version 1.1.7a fixes a reversed assertion that would cause pdnsd to terminate +if used with the ping uptest. No other changes were made. + +Version 1.1.7 fixes some problems that might be remotely exploitable to +gain access as the user pdnsd runs as (an unprivileged user by default). To do +this, an attacker needs to control a name server that is queried by pdnsd, and +send a malicious reply to such a query. Upgrading is strongly recommended! +There are also minor bug fixes and stability improvements. + +Version 1.1.6 adds the query_port_start and query_port_end options (contributed +by Andreas Steinmetz), that allow confining the ports pdnsd uses for outgoing +queries to a certain range. It also fixes numerous bugs, one of which could +cause pdnsd to hang; update is therefore recommended. + +Version 1.1.5 contains a fix for a security bug that would allow local users +that are allowed to use pdnsd-ctl on a running pdnsd server to execute +arbitrary code as the user that pdnsd runs as (or on Linux, when strict_setuid +is not enabled, as the user that started pdnsd). The danger of this is usually +quite limited; the status socket is not enabled by default, it's default +permissions do only allow the user pdnsd runs as to use the socket, +strict_setuid is enabled by default and pdnsd runs as an unprivileged user. +There is also a new configure option, --enable-underscores, that will make +pdnsd allow underscores in domain names. Furthermore, the SRV record handling +has been fixed to allow underscores in any case (this was not allowed +previously, but is required by the RFC). SOA records are not put in the +answer section any more if no answers are found (this violates the RFC's). +It may be put in the authority section in a later version. +There are also various bugfixes in this release. +Upgrade is recommended. + +Version 1.1.4 fixes various smaller bugs, and should also improve the cache +write performance especially for larger caches. There are also two new +features: servers can now be given a label (using the label server option) +which can be used to identify them for the pdnsd-ctl server command +(contributed by Andrew M. Bishop), and local records can be marked to make +the domain record authoritative in pdnsd's cache (which means that pdnsd will +assume that records that are not present in the cache for that domain are +non-existent); this is on by default now, and can be controlled using the new +authrec server option). + +Version 1.1.3 added contrib/ and had a lot of robustness fixes. +This release addresses a security hole that affects only Linux systems. Due to +a bug in glibc, pdnsd could crash during a port scan. This release contains +a workaround for this, as well as a fix for a deadlock under heavy load +conditions. It also fixes a possible problem that could be triggered by +malicious servers, and contains numerous bug fixes. +A script, contributed by Marko Stolle, makes pdnsd useful in a DHCP setup. +pdnsd also preservers the case of names in the cache, and should work much +better on alpha machines (thanks for the contributions by Bjoern Fischer +and P.J. Bostley that made this possible). New types were dded for rr +sections and pdnsd-ctl. +Upgrade is recommended. + +Version 1.1.2 has a fix for a bug that could cause SERVFAIL to be +returned when NXDOMAIN would be appropriate. The bug surfaced only when +pdnsd queried name servers with a behaviour different from BIND's in the +NXDOMAIN case, e.g. pdnsd querying another pdnsd or e.g. djbdns. + +Version 1.1.1 fixes a possible race condition in status socket creation. +This race might be used by a local attacker to change the access +permissions of a certain file in /tmp. The risk of this is probably +negligible. The default setup uses a non-privileged user, default mode +0600, and the status socket is disabled normally, so this should be +relatively safe. I don't see any possibility to exploit this, it is +more of a paranoia fix. +There are also some other minor fixes and documentation improvements. +Upgrade is recommended. + +Version 1.1.0 introduces negative cacheing, pdnsd-ctl enhancements and +a much improved FreeBSD support. The cache file format has changed from +prior releases. Some configuration defaults have changed, too. + +Version 1.0.15 is mostly a bugfix release. It also has a new option: +randomize_recs in the global section. + +Version 1.0.14 has a fix in icmp.c that will make it build properly +on FreeBSD and older Linux systems. + +Version 1.0.13 has some code cleanup, a fix for the Debian rc install, +and a security fix (contributed by Olaf Kirch): when changing +user and group id, pdnsd did not drop supplementary group IDs that +the original user was member of. + +Version 1.0.12 is a bugfix release and contains some security +enhancements. There are also inclusion/exclusion lists for servers +(new options include=, exclude=, policy= in the server +section). + +Version 1.0.11 fixes two bugs that might be used for denial-of-service +attacks, upgrading is recommended. + +Versions 1.0.9 and 1.0.10 are bugfix releases. + +Version 1.0.8 introduces special linux ppp device support contributed +by Ron Yorston, and has some bugfixes. + +Version 1.0.7 introduces autoconf support, many new config file options and +the new pdnsd-ctl run-time configuration program. + +Version 1.0.6 has another set of bugfixes, in addition to higher compile- +time configurability and UDP query support. It also contains Debian rc +scripts contributed by Markus Mohr. + +Version 1.0.5 has some bugfixes and the new "server_ip" option +contributed by Wolfgang Ocker. + +Version 1.0.4 introduces the new options run_as, strict_setuid and +paranoid. These new options are optional security enhancements. + +Versions 1.0.1, 1.0.2 and 1.0.3 are bugfix releases. + +Version 1.0.0 has a lot of changes compared to the 0.9.x tree, but much of +them "under the hood": +- IPv6 support (experimental; compile- and run-time configurable) +- FreeBSD (and such hopefully *BSD) support +- better rfc2181 compatability +- new options: + - serve_aliases in source section + - linkdown_kluge in global section + - max_ttl in global section +- cache-code reorganization, only one unified hash (of variable depth) +- Optimizations & cleanups +- Automatic deps (only interesting for developers ;-) + +Version 0.9.11 fixes a locally exploitable security hole (the cache file was +world writeable by default). Please see ChangeLog.old for details. + +Version 0.9.10 fixes some bugs and improves build on Red Hat. + +Version 0.9.9 contains the rc scripts for Red Hat Linux contributed by Torben +Janssen, in addition to code cleanups and bugfixes. +The meaning of the option -v has changed in this release. +There is also a new config file option "lean_query" that is on by default. It +is an optimization, so please look in the docs when updating whether you want +it switched on or not. + +When compiling versions after 0.9.8, you will probably get more +compiler warningsthan before. This is because the C compiler settings +have been made stricter. + +Version 0.9.8 fixes a minor bug some build problems with glibc2.0 systems. + +The versions 0.9.6 and 0.9.7 are bugfix releases. + +Version 0.9.5 introduces uptest=exec, and a modified config file syntax (cache +sizes are now specified in kB). + +Version 0.9.4 was the first to be released to the public. For information on +changes, see ChangeLog. + diff --git a/jni/pdnsd/PKGBUILD.in b/jni/pdnsd/PKGBUILD.in new file mode 100644 index 00000000..3d617651 --- /dev/null +++ b/jni/pdnsd/PKGBUILD.in @@ -0,0 +1,24 @@ +# Package build script for Arch Linux, +# contributed by Alexander Drozdov. + +pkgname=@PACKAGE@ +pkgver=@VERSION@ +pkgrel=@packagerelease@ +pkgdesc="pdnsd is a proxy DNS server with permanent caching (the cache contents are written to hard disk on exit) that is designed to cope with unreachable or down DNS servers." +url="http://members.home.nl/p.a.rombouts/pdnsd.html" +license="GPLv3" +depends=() +makedepends=(glibc) +conflicts=() +replaces=() +backup=() +install= +source=(http://members.home.nl/p.a.rombouts/pdnsd/releases/$pkgname-$pkgver-$pkgrel.tar.gz) +md5sums=() + +build() { + cd $startdir/src/$pkgname-$pkgver + ./configure --prefix=/usr --enable-ipv6 --sysconfdir=/etc --with-distribution=ArchLinux + make || return 1 + make DESTDIR=$startdir/pkg install +} diff --git a/jni/pdnsd/README b/jni/pdnsd/README new file mode 100644 index 00000000..7042e934 --- /dev/null +++ b/jni/pdnsd/README @@ -0,0 +1,22 @@ +You can find the documentation for pdnsd in the doc/ directory. The html +documentation (which I recommend) is in the doc/html/ subdirectory. +The pure text documentation (which is generated automatically from the +html documentation) is in doc/txt/. +The following documents are available: + +index.html / intro.txt Overview, system requirements +doc.html / manual.txt Building, installation and usage instructions +faq.html / faq.txt The FAQ + +Share and enjoy! + Thomas + + +For news about recent changes in pdnsd the following files may be of +interest to you: + + README.par + ChangeLog + NEWS + +Last revised: 08 July 2007 by Paul Rombouts diff --git a/jni/pdnsd/README.par b/jni/pdnsd/README.par new file mode 100644 index 00000000..ea181bc6 --- /dev/null +++ b/jni/pdnsd/README.par @@ -0,0 +1,216 @@ + pdnsd version 1.2.9a by Paul Rombouts + ===================================== + +This file describes the version of pdnsd that I maintain personally and am +making available so other people can enjoy the latest features and fixes. Thomas +Moestl no longer maintains pdnsd himself, so I am effectively the new +maintainer. This README describes the new features in version 1.2. This version +has a rather large number of internal changes and also some new features, which +I am rather pleased with, even if I say so myself. I think the changes are +significant enough to warrant increasing the minor version number from 1.1 to +1.2. The differences between my previous "official" release 1.1.11 and Thomas' +last release 1.1.7a are described in my previous README, which I have renamed +REAME.par.old. In this README I restrict myself to describing changes between +1.1.11 and 1.2. +The main difference between versions 1.2 and 1.2.1, aside from some minor +changes, is that 1.2.1 has (experimental) support for the Cygwin platform. +Version 1.2.2 has further improvements in portability and should in +particular now also compile on the Darwin (Apple Mac OS X) platform. +Version 1.2.4 has some important fixes for a memory leak, a minor buffer- +overflow problem and some situations which could cause pdnsd to exit +prematurely. Note that TCP-query support is now compiled in by default, but can +still be disabled using a configure option. +The main new feature of version 1.2.5 is the new query method "udp_tcp". +Version 1.2.6 has an updated license: GPL version 3. The main new feature of +version 1.2.6 is the "reject" option, which makes it possible to censor or +correct for unwanted IP addresses in replies. +Version 1.2.7 contains an important fix for a "dangling pointer" bug and +attempts to make pdnsd less vulnerable to the issues raised in CERT +vulnerability note VU#800113. It also contains some improvements for defining +local records interactively using the pdnsd-ctl utility. +The main new feature of version 1.2.8 is automatic discovery of root servers, +as well as some minor improvements in the resolver. +Version 1.2.9 among other things supports many addtional RR types, uses data +structures that should be more slightly more memory efficient and has support +for EDNS, which allows DNS UDP messages to be larger than 512 bytes. +Version 1.2.9a is a simple bugfix release that fixes a problem with compiling +1.2.9 after configuring with --enable-strict-rfc2181. Unless you use this option +to compile pdnsd, there is no need to upgrade from 1.2.9 to 1.2.9a. + +For instructions how to compile and install pdnsd see doc/html/doc.html or +doc/txt/manual.txt. Note that I am no longer distributing a patch w.r.t. Thomas' +version because the (compressed) patch file is barely smaller than the +(compressed) tar archive. + +Here follows a list of some of changes in version 1.2 from a user's perspective. +For a more technical description of some of the changes in the code see the ChangeLog. +For a short history about recent releases have a look at NEWS or doc/html/index.html. + +- First of all, two potentially rather nasty bugs have been fixed in the code + for the handling of NXT and NAPTR records. A response from a remote server + containing NXT records (even well-formed ones) will very likely cause pdnsd to + crash. The code for handling NAPTR records contained incorrect ASSERT + statements, which could cause pdnsd to abort in a controlled fashion, but + completely unnecessarily. + +- Sampo Lehtinen has remarked that pdnsd sometimes failed to resolve classless + reversed-delegated IP addresses, and that this has something to do with the + fact that pdnsd didn't accept '/' characters in domain names. After reading + some of the relevant RFCs I decided to remove all restrictions on the types + of characters that pdnsd accepts in domain names. Of course for most + applications, there are many characters which don't make sense in domain + names, but I feel that it is the responsibility of the client application to + reject these, not the proxy server. + +- At the suggestion of Dan Tihelka, I have expanded to the server_ip= option to + allow the name of an interface to be specified instead of an IP address. + Presently this has been tested on Linux only. Can someone running pdnsd on + *BSD tell me if the code for getting the address of an interface is different + for Linux and BSD-type systems? + +- At the suggestion of Juliusz Chroboczek I've added an new server availability + test which can be specified with uptest=query. This can be useful as an + alternative to "uptest=ping" in case the remote server does not respond to + ICMP_ECHO requests at all, which unfortunately is quite common these days. + "uptest=query" causes pdnsd to send an empty query to remote name servers. Any + well-formed response (apart from SERVFAIL) within the timeout period will be + interpreted as a sign that the server is "up". + +- Instead of specifying the IP addresses of the name servers that pdnsd should + query in a server section of the config file, you may also specify a + resolv.conf-style file. Preferably this should not be /etc/resolv.conf. If the + contents of the resolv.conf type file changes while pdnsd is running, you can + make pdnsd aware of the changes with the "pdnsd-ctl config" command, see + below. Example: + + server { + label=myisp; + file=/etc/ppp/resolv.conf; + timeout=10; + } + +- There is a new option for "server" sections in the config file: + root_server=on/off. + In case a server section contains only addresses of root servers, which + usually only give the name servers of top level domains in their reply, + setting root_server=on will enable certain optimizations. This involves using + cached information to reduce queries to the root servers, thus speeding up the + resolving of new names. + +- New option for "rr" sections in the config file: reverse=on/off. + If you want a locally defined name to resolve to a numeric address and vice + versa, you can now achieve this by setting reverse=on before defining the A + record, making it unnecessary to define a separate PTR record for the reverse + resolving. + Example: + + rr { + name = localhost; + reverse = on; + a = 127.0.0.1; + } + + has the same effect as: + + rr { + name = localhost; + a = 127.0.0.1; + } + rr { + name = 1.0.0.127.in-addr.arpa; + ptr = localhost; + } + +- In rr sections it is now possible to specify a wildcard name, i.e. a name + starting with the label *. The * in a wildcard can match one or more labels in + a queried name, but only whole labels. For example, *.mydomain will match + a.mydomain or www.a.mydomain, but not mydomain. Before you can specify an rr + section with name=*.mydomain you must define some records for mydomain, + typically NS and/or SOA records. + Example: + + rr { + name = mydomain; + ns = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + rr { + name = *.mydomain; + a = 192.168.1.10; + } + +- There is a slight backwards compatibility problem which involves the name= and + owner= options in rr sections. The new version does not allow you to place + owner= before name=. On the other hand, you may now freely mix the owner + option with the a,ptr,cname,mx and soa options and define as many records of + this type as you like (including zero). + +- pdnsd-ctl has three new commands: + + config: Reloads pdnsd's configuration file. This is more efficient than + restarting pdnsd, and should not cause only noticeable interruption in DNS + service. However, some types of configuration changes cannot be put into + effect this way, and you will be prompted to restart pdnsd instead. + + empty-cache: Empties the cache completely, freeing all existing entries. + In version 1.2.3 you can specify a selection of entries to delete by providing + a list of include/exclude patterns. + + dump: Prints information about all the names stored in the cached. This is + mainly useful for diagnostic purposes. + +- There is now a pdnsd.conf(5) man page, describing pdnsd's configuration file. + The man page has been generated from the html documentation using a customized + Perl script. + +- New in version 1.2.4: Time intervals in the configuration files can now be + expressed in seconds, minutes, hours, days and weeks, using the suffixes + s,m,h,d,and w. + Example: 2h30m is interpreted as 2*60*60 + 30*60 = 9000 seconds. + +- Version 1.2.5 introduces a new configuration option, contributed by Jan-Marek + Glogowski, called "use_nss" which can be turned off to prevent nasty delays in + certain situations. + Besides the query methods "udp_only", "tcp_only" and "tcp_udp" you can now + also specify "udp_tcp", which more closely adheres to the behaviour + recommended by DNS standards. + +- Version 1.2.6 introduces the "randomize_servers" and "reject" options. By + setting "randomize_servers" on you can give each server in a server section an + equal chance of being queried, which is useful when resolving from root + servers, for instance. The "reject" option can be used to censor certain IP + addresses or correct for unwanted replies from servers you don't completely + trust. + +- Version 1.2.7 contains support for "include" files which can be referenced + from configuration files or read interactively using pdnsd-ctl. These files + can be used to add local definitions to the cache without reconfiguring pdnsd. + The new "pdnsd-ctl eval" command can be used to interactively define local + records that could previously only be defined in configuration files but not + with the "pdnsd-ctl add" command. + +- Version 1.2.8 contains support for automatic discovery of root servers. + Instead of supplying a complete list of IP addresses of root servers in a + server section of the configuration file, you need only enter one or two + addresses of name servers which know the names and addresses of the root + servers and set "root_server=discover". + The "neg_rrs_pol" option has a new default setting, which should allow + sensible negative caching of RRs in most situations, even if "proxy_only=on". + +- Version 1.2.9 contains support for EDNS (Extension mechanisms for DNS), which + allows UDP messages to be larger than 512 bytes. Whether pdnsd uses EDNS in + outgoing queries is determined by the configuration option "edns_query". If + pdnsd receives a query using EDNS, it will reply using EDNS regardless of the + configuration settings. + Local TXT records can now be defined in the configuration file. + If the query uptest fails due to remote servers ignoring empty queries, this + can now be remedied using the new "query_test_name" config option. + +The new features are described in greater detail in the manual doc/html/doc.html +or doc/txt/manual.txt. + +Enjoy! + +If you have any questions about my version of pdnsd, you can send these +to . Questions about the original (unmaintained) pdnsd +version should be sent to or . diff --git a/jni/pdnsd/README.par.old b/jni/pdnsd/README.par.old new file mode 100644 index 00000000..4bf0edaf --- /dev/null +++ b/jni/pdnsd/README.par.old @@ -0,0 +1,249 @@ + pdnsd maintenance version 1.1.11-par by Paul Rombouts + ======================================================= + +This file describes the version of pdnsd that I maintain personally and am +making available so other people can enjoy the latest features and fixes. +Thomas Moestl no longer maintains pdnsd himself, so I am effectively the new +maintainer. The current version is 1.1.11-par, which has a rather large number +of small changes. Among the bugs fixed are a race condition in the cache lookup +code, a flaw in the code that caused a busy spin when a remote server answered +with "Not Implemented", and problems with the -4 and -6 command-line options. +Among the improvements are an alternative sorting algorithm which should allow +pdnsd to start up faster when reading a large cache file from disk, automatic +mapping of IPv4 to IPv6 addresses when running in IPv6 mode, somewhat more +efficient memory use, and better compression of the replies. Some of the new +features are described in the second half of this file (look for "new in version +1.1.11"). For the rest of the changes I will have to refer you to the ChangeLog. +For a short history about recent releases have a look at doc/html/index.html. + +Since version 1.1.9 I've added some missing pieces to the documentation (the +manual doc/html/doc.html,doc/txt/manual.txt and the man page doc/pdnsd-ctl.8). +Version 1.1.11 finally has a man page doc/pdnsd.8, thanks to a contribution by +Mahesh T. Pai. + +The first part of this file describes how to patch, compile, install and run +pdnsd. The second part describes some of the changes I've made to Thomas +Moestl's code. + +Unless you're using the pre-patched source archive pdnsd-1.1.11-par.tar.gz you +must first apply my patch file pdnsd-1.1.11-par.diff.gz before compiling and +installing pdnsd according to Thomas Moestl's instructions described in the the +documentation. Use a freshly untarred copy of Thomas Moestl's original version +1.1.7a source, cd into the source directory pdnsd-1.1.7a and apply the command: + +gzip -cd /pdnsd-1.1.11-par.diff.gz | patch -p2 -N -Z + +Note: I have used GNU extensions so there may be some portability issues. I have +supplied alternatives for some of the less portable functions. There should be no +problem with most Linux distributions. + +That's it! You should now be able to compile, install and run pdnsd. See the +documentation in doc/html/doc.html or doc/txt/manual.txt for more detailed +instructions. + +Some people may want change the compiler optimization flag. I use the -O2 flag, +but it might be safer to use a lower level of optimization or no optimization at +all. In that case prefix the configure command with the desired compiler flags +like this (assuming you're using a bash shell): + + CFLAGS="-O1 -g -Wall" ./configure ... + +I have added a new configuration option "--with-thread-lib=", which you +should use if you experience problems with signal handling under Linux. The +usual symptom is failure by pdnsd to save the cache to disk, and +/var/cache/pdnsd/pdnsd.cache remaining empty. If you experience this kind of +trouble, try reconfiguring with different values for the --with-thread-lib +option. The allowable values are "linuxthreads" (the default), "linuxthreads2" +(or "lt2" for short), and "nptl". I recommend that you first configure and +compile without the --with-thread-lib option, then if you experience trouble try +again with --with-thread-lib=lt2 and recompile. +If your Linux system has an implementation of the Native POSIX Thread Library, +which is the case with Red Hat 9 for instance, you should use +--with-thread-lib=nptl . +Ideally, I would like to write a configure script which automatically detects +which kind of thread library is being used on a Linux system, but I don't have a +clue yet how to do this. If you can help me with this please write to me at the +email address listed at the end of this file. + +The rest of this file describes some of the modifications I've made, but you +don't have to read it if you simply want to run pdnsd as you're used to. + + +- The main new feature I've added enables you to change the server addresses + that pdnsd uses at run-time using pdnsd-ctl. I've done this because the ISPs I + use do not specify fixed DNS server addresses, but expect their clients to use + dynamic DNS configuration (DHCP in the case of the cable connection, RFC1877 + in case of isdn). I've extended the options that can be given with the + "server" command to pdnsd-ctl, to allow IP addresses to be specified as an + additional argument after "up|down|retest". This allows me to put something + like this in my ifup-local script: + + pdnsd-ctl server isp-label up "$DNS1 $DNS2" + + For more details how to use pdnsd-ctl read the updated documentation in + the doc/html directory. There is also a manpage for pdnsd-ctl. + This was quite tricky to implement because there might be pending queries + while the addresses are being changed. It certainly was an interesting + exercise in writing multi-threaded code for me. + + +- I've implemented a feature which allowed me to specify multiple IP addresses + per server section in the configuration file. This allowed for a much more + compact configuration file (3 server sections instead of 7 in my case), + because most configuration options are identical for servers belonging to the + same ISP. It also made the output of "pdnsd-ctl status" more compact. And it + was necessary to enable a satisfactory implementation of the previous feature. + Example of the new syntax: + + ip = 123.456.789.001, 123.456.789.002, 123.456.789.003; + + At the suggestion of Greg Norris server sections no longer have to specify IP + addresses. A server section without IP addresses will remain inactive until it + is assigned one more addresses at run-time with pdnsd-ctl. + +- I've changed the implementation of dynamic arrays to make it slightly more + efficient, and improve type safety. I also got rid of several arrays of fixed + size in favor of dynamically allocated arrays. In particular, I got rid of + all occurrences of MAXPATH. I also made several static variables "automatic". + +- The output of the "status" command of pdnsd-ctl now gives more meaningful + constant names "ping|none|if|exec" instead of numbers for the "uptest" option. + I've also added some information that was previously missing. + +- I've fixed I a problem that caused pdnsd to use up a lot of CPU time and slow + down my system considerably when it received a query that took a long time to + resolve. It turned out that pdnsd can get into a "busy spin" when one of the + DNS servers pdnsd is querying refuses the connection. Apart from fixing this + bug, to speed things up additionally, I thought it would be a good idea to + mark a server down (without retesting it) after detecting errno==ECONNREFUSED. + This gives me very satisfactory performance, with the problematic server being + tried only once during every testing interval. + + New in version 1.1.11: An additional busy spin condition, triggered when a + remote server answers with "Not Implemented", has been discovered and fixed. + In case there are remaining bugs in the multiplexing code, I've added a test + that checks if the number of events reported by poll/select matches the number + of events handled by pdnsd. If not, pdnsd will log an error message and give + up. Although the bugs still need to be reported and fixed, at least this + should prevent pdnsd from wasting CPU cycles. + +- Due to a bug in Thomas' code, pdnsd tries, but fails, to remove the control + socket "pdnsd.status" before exiting. This has also been fixed. In version + 1.1.8b1-par6 I have cleaned this up some more so that pdnsd will handle + situations where it can't open or bind the control socket more gracefully. + +- I've rewritten some of the code that saves the contents of the cache to the + file "pdnsd.cache" just before pdnsd exits. This is because I noticed in my + logfiles that pdnsd occasionally had problems reading this file back at + startup. I eliminated the use of fseek() in Thomas' code. I could not find + anything that was demonstrably incorrect about his use of fseek(), but it + seemed better to me to do without it and write the file in a strictly + sequential order. Anyway, it turned out my hunch paid off: no more error + messages about "pdnsd.cache" in my logfile. + + New in version 1.1.11: I've added some new code for sorting the queue used for + purging stale cache entries. This should allow pdnsd to start up faster when + reading large cache files from disk. + +- I've extended the configuration options for policies of inclusion/exclusion + lists in server sections. The new policies options are "simple_only" and + "fqdn_only". Setting policy=simple_only will cause the server to used only for + simple hostnames if no other rule matches. On the other hand, setting + policy=fqdn_only will cause the server to be used only for fully qualified + domain names (i.e. the name has at least one dot in-between). I find these + options useful for controlling which name servers (if any) will be used by + pdnsd for simple host names. + +- I've added a new "delegation_only" option that can be used to undo the + unwanted effects of DNS "wildcards". It works roughly as the feature by the + same name in BIND. It is turned off by default. To block Verisign's + Sitefinder, add the following line to the global section of the configuration + file: + + delegation_only= com, net; + + If you find that this feature blocks some legitimate domain names, you will + probably need to add the address of a nameserver that provides good authority + information. More information can be found at + http://www.phys.uu.nl/~rombouts/pdnsd/delegationonly.html + +- It is no longer mandatory that domain names in the configuration file end in a + dot. + +- The parser for configuration files has been rewritten purely in C, so (f)lex + and yacc/bison are no longer needed to build pdnsd. + It is no longer necessary to place strings between quotes in the configuration + file, unless a string contains a special character such as whitespace, a token + that normally starts a comment, or one of the characters ",;{}". Note that + these special characters are illegal in domain names anyway. + +- New in version 1.1.11: Negating whole domains with a neg section in the + config file will result in all the subdomains being negated as well. + For example, adding the lines + + neg {name=doubleclick.com; types=domain;} + neg {name=doubleclick.net; types=domain;} + + will also negate ad.doubleclick.com, ad.fr.doubleclick.net, etc. + +- New in version 1.1.11: When running in IPv6 mode, pdnsd will now automatically + map any IPv4 addresses it reads in the config file to IPv6 addresses. + When pdnsd has been compiled with IPv6 support and runs in IPv4 mode, it will + skip IPv6 addresses with a warning message. This may result in certain server + sections becoming inactive, though. + + The -4 and -6 options should now work as advertised. + I've added two new command-line options, "-a" and "-i ". + With the -a flag pdnsd will try to detect automatically if IPv6 support is + available on a system, and fall back to IPv4 if not. The -a flag can be used + instead of -4 or -6. + The -i option can be used to specify a prefix for mapping IPv4 to IPv6 + address. The default is ::ffff.0.0.0.0. There is also a corresponding + ipv4_6_prefix= option for the config file. + +- New in version 1.1.11: I've slightly changed the way pdnsd does parallel + queries. Active queries or not canceled until we have received a useful + response from a remote name server, or all the queries have failed or timed + out. Thus the par_queries parameter is no longer the maximum number of + parallel queries, but rather the increment with which the number of parallel + queries is increased when the previous set has timed out. In the worst case + there will be pending queries to all the servers in the list of available + servers simultaneously. We may be wasting more system resources this way, but + the advantage is that we have a greater chance of catching a reply. After all, + if we wait longer anyway, why not for more servers. + I've also introduced a global timeout parameter. This is the minimum period of + time pdnsd will wait after sending the first query to a remote server before + giving up without having received a reply. The timeout options in the + configuration file are now only minimum timeout intervals. Setting the global + timeout option makes it possible to specify quite short timeout intervals in + the server sections. This will have the effect that pdnsd will start querying + additional servers fairly quickly if the first servers are slow to respond + (but will still continue to listen for responses from the first ones). This + may allow pdnsd to get an answer more quickly in certain situations. + + After receiving a reply from a remote server the server is marked up and its + time stamp is updated. This will have the effect that pdnsd doesn't bother + testing this server for availability for a period of time, and thus the + overhead caused by testing is reduced. After server timeouts, uptests are + performed by the separate server status thread, not by threads that have to + answer queries. Unresponsive servers with uptest=ping will not be marked down + immediately any more, but only after the ping test has definitely failed. + +I've also included a number of bug-fixes contained in a patch file supplied to +me by Thomas Moestl. In addition to the things I had already fixed, the +following issues are addressed: some memory leaks, dropping of root privileges +before calling uptest scripts in case pdnsd was started setuid root (which is a +bad idea anyway), passing on open fd's to uptests, integer overruns in the +status reporting code, fixing string passing from the lexer, more consistent +treatment of underscores in domain names. + +In addition to the things I've listed above, I've made various little changes to +fix minor bugs, improve efficiency or elegance, or simply to suit my my own +coding style. These changes are too numerous to list here, but some of them are +listed in the ChangeLog. Of course if you are really interested in the +nitty-gritty you can always compare the source of my version with Thomas' +original code. + +If you have any questions about the modifications I've made, you can send these +to . Questions about the original pdnsd version should +be sent to or . diff --git a/jni/pdnsd/THANKS b/jni/pdnsd/THANKS new file mode 100644 index 00000000..9c7e3bbc --- /dev/null +++ b/jni/pdnsd/THANKS @@ -0,0 +1,66 @@ +This is a (hopefully complete) list of people I have to thank for helping me +develop and improve pdnsd: + +David G. Andersen +Andrew M. Bishop +Daniel Black +Carsten Block +Stephan Boettcher +P.J. Bostley +Rodney Brown +Kevin A. Burton +Juliusz Chroboczek +Joachim Dorner +Frank Elsner +Christian Engstler +Stefan Erhardt +Bjoern Fischer +Stefan Förster +Bert Frederiks +Mike Hammer +Jonathan Hudson +Torben Janssen +Byrial Jensen +Olaf Kirch +Nikola Kotur +Kiyo Kelvin Lee +Bernd Leibing +Patrick Loschmidt +James MacLean +Sourav K. Mandal +Fraser McCrossan +Markus Mohr +Michael Müller +Gustavo Niemeyer +Alexandre Nunes +Wolfgang Ocker +Mahesh T. Pai +Bernhard Pelz +Soenke J. Peters +Erich Reitz +Paul A. Rombouts +Brian Schroeder +Roman Shterenzon +Daniel Smolik +Milan P. Stanic +Michael Steiner +Norbert Steinl +Andreas Steinmetz +Marko Stolle +Markus Storm +Michael Ströder +Thomas Stromberg +Alan Swanson +Lyonel Vincent +Eelco Vriezekolk +Paul Wagland +Sverker Wiberg +Michael Wiedmann +Ron Yorston +Nikita V. Youshchenko +Jan-Marek Glogowski +Thomas Cort +Pierre Habouzit +Dirk Armbrust +Georg Schwarz +Ashish Shukla diff --git a/jni/pdnsd/TODO b/jni/pdnsd/TODO new file mode 100644 index 00000000..f6a1650a --- /dev/null +++ b/jni/pdnsd/TODO @@ -0,0 +1,20 @@ +- Implement a reference counter to ensure that newly entered records are not + purged immediately (really needed?) +- Perhaps do a two-step form of recursive query: first query those servers we + have got cached, then (if unsuccessful) look the others up and query again. + The impact of this optimisation may not be very big, because all sane servers + give A records for NS records if possible. +- Test for compatibility on other Unix-like Systems other than the BSDs and + Linux; rewrite the functions in netdev.c and icmp.c for those OSs if + necessary. Also try to get compatibility for other compilers than gcc. +- Write an install rule for the Slackware start-up script. +- Update the FAQ. +- Implement DNSSEC support. Since version 1.2.9, pdnsd is able to cache the RR + types necessary for DNSSEC, but the resolver is not yet security aware. +- Implement a lookup table (hash table) for queries in progress. This would + enable a thread that is resolving a query that is already being handled by + another thread to wait for that other thread to finish and copy its result + rather than independently query remote servers. It is very common for + resolvers to resend UDP queries if they don't get a reply within a timeout + period and if the answer is not yet cached, this will result in multiple + threads duplicating each others work in the current implementation. diff --git a/jni/pdnsd/acconfig.h b/jni/pdnsd/acconfig.h new file mode 100644 index 00000000..c8640712 --- /dev/null +++ b/jni/pdnsd/acconfig.h @@ -0,0 +1,191 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* ONLY EDIT acconfig.h, NEVER config.h or config.h.in! + * config.h MAY BE OVERWRITTEN BY make, config.h.in by autoheader! */ + +/* Define your Target here. Currently defined are TARGET_LINUX (any + * architecture), TARGET_BSD (experimental; tested on FreeBSD, hopefully + * works for other BSD variants) and TARGET_CYGWIN. */ +#define TARGET TARGET_LINUX + +/* change the #undef to #define if you do not want to compile with special + * ISDN support for Linux. Note that the ISDN support will not compile ok on + * unpatched kernerls earlier than 2.2.12 (if you did apply newer isdn patches, + * it may work fine). This is not on by default because it will cause compile + * problems on some systems */ +#undef ISDN_SUPPORT + +/* The following regulates the IP Protocol support. Supported types are IPv4 + * and IPv6 (aka IPng). You may enable either or both of these protocols. + * Enabling in this context means that support for the respective protocol + * will be in the binary. When running the binary, one of the protocols may + * be activated via command line switches. Note that activating both IPv4 and + * IPv6 is pointless (and will not work because two UDP and two TCP threads + * will be started that concur for ports). Because of that, it is not allowed. + * When pdnsd runs with IPv6 activated it should be able to service queries + * from IPv6 as well as from IPv4 hosts, provided that you host is configured + * properly. + * For each of the protocols there are two options: ENABLE_IPV4 and ENABLE_IPV6 + * control whether support for the respective protocol is available in the + * binary. DEFAULT_IPV4 selects which protocol is enabled on pdnsd + * startup by default. 1 means IPv4, while 0 means IPv6. If support for + * a protocol was included in the executable, you can specify command line + * parameters to activate or deactivate that protocol (the options are -4 and + * -6), but it makes more sense to use the run_ipv4=on/off option in the + * configuration file. + * Make your choice. Note that IPv6 support is experimental in pdnsd. + * In normal operation, you will currently only need IPv4. */ +#undef ENABLE_IPV4 +#define DEFAULT_IPV4 1 +#undef ENABLE_IPV6 + +/* In all pdnsd versions before 1.0.6, DNS queries were always done over + * TCP. Now, you have the choice. You can control that behaviour using + * the -m command line switch, and you can give a preset here. There + * are 3 different modes: + * UDP_ONLY: This is undoubtedly the fastest query method, because + * no TCP negotiation needs to be done. + * TCP_ONLY: This is slower than uo, but generally more secure + * against DNS spoofing. Note that some name servers on the + * internet do not support TCP queries, notably dnscache. + * TCP_UDP: TCP, then UDP. If the TCP query fails with a "connection refused"- + * error or times out, the query is retried using UDP. + * UDP_TCP: UDP, then TCP. If the UDP reply is truncated (i.e. the tc flag is set), + * the query is retried using TCP. */ +#define M_PRESET UDP_ONLY + +/* In addition to choosing the presets, you may also completely disable + * one of the protocols (TCP for preset UDP_ONLY and UDP for preset TCP_ONLY). + * This saves some executable space. */ +#undef NO_UDP_QUERIES +#undef NO_TCP_QUERIES + +/* With the following option, you can disable the TCP server functionality + * of pdnsd. Nearly no program does TCP queries, so you probably can do + * this safely and save some executable space and one thread. + * You also can turn off the TCP server at runtime with the --notcp option. */ +#undef NO_TCP_SERVER + +/* By undefining the following, you can disable the UDP source address + * discovery code. This is not recommended, but you may need it when + * running into compilation problems. */ +#undef SRC_ADDR_DISC + +/* NO_POLL specifies not to use poll(2), but select(2) instead. If you are + * unsure about what this means, just leave this as it is.*/ +#undef NO_POLL + +/* Define this for "hard" RFC 2181 compliance: this RFC states that + * implementations should discard answers whose RR sets have multiple + * different time stamps. While correct answers are generated, incorrect + * ones are normally tolerated and corrected. Full RFC compliance is + * however only achieved by deactivating this behaviour and thus being + * intolerant. */ +#undef RFC2181_ME_HARDER + +/* Define this to the device you want to use for getting random numbers. + * Leave this undefined if you wand to use the standard C library random + * function, which basically should be sufficient. + * Linux and FreeBSD have two random number devices: /dev/random and + * /dev/urandom. /dev/urandom might be less secure in some cases, but + * should still be more than sufficient. The use of /dev/random is + * discouraged, as reading from this device blocks when new random bits + * need to be gathered. */ +#undef RANDOM_DEVICE +#undef R_DEFAULT +#undef R_RANDOM +#undef R_ARC4RANDOM +/*#define RANDOM_DEVICE "/dev/urandom"*/ + +/* Designate which database manager to use for cacheing. + * default: native; others: gdbm */ +#define CACHE_DBM DBM_NATIVE + +#define CACHEDIR "/var/cache/pdnsd" + +#define TEMPDIR "/tmp"; + +/* This is for various debugging facilities that produce debug output and + * double-check some values. You can enable debug messages with the -g option. + * Normally, you can switch this off safely by setting the number after DEBUG + * to 0. This will increase speed (although only marginally), save space + * in the executable (only about 12kB) and some stack space per thread + * (which may be significant if you have many threads running simultaneously). + * However, it may be an aid when debugging config files. + * The only defined debug levels by now are in the range 0 - 9. + * Define this to 9 if you want hex dumps of all the queries and replies pdnsd + * receives (you must also call pdnsd with -v9 to actually see the hex dumps). + * When in doubt, leave it defined to 1. */ +#define DEBUG 1 + +/* This defines the default verbosity of informational messages you will get. + This has nothing to to with the debug option (-g), but may be set with -v + option. 0 is for normal operation, up to 3 for debugging. + Unlike the debug messages, these messages will also be written to the syslog.*/ +#define VERBOSITY 0 + +/* Redefine this if you want another hash size. + * The number of hash buckets is computed as power of two (1< 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 8's {/usr,}/bin/sh. + touch 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 + ;; + 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, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# 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. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 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"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //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' -e 's/\$U/'"$U"'/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"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# 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. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 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. + +# serial 16 + +# 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. + +# 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.62])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], +[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], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [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([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. 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)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl 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 +]) + +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, 2003, 2005, 2008 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}" != 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, 2005 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. + +# serial 2 + +# 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, 2002, 2003, 2005, 2009 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. + +# serial 4 + +# 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 +]) + +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# 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. + +# serial 6 + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != 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 +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# 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. + +# serial 6 + +# 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 supports --run. +# If it does, 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 --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 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_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 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. + +# serial 4 + +# _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])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# 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. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# 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 ( + 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 + rm -f conftest.file + 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 + + 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)]) + +# Copyright (C) 2001, 2003, 2005 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, 2008 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. + +# serial 2 + +# _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, 2005 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. + +# serial 2 + +# _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. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +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 + diff --git a/jni/pdnsd/compile b/jni/pdnsd/compile new file mode 100644 index 00000000..1b1d2321 --- /dev/null +++ b/jni/pdnsd/compile @@ -0,0 +1,142 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# 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 +# . + +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 $? + ;; +esac + +ofile= +cfile= +eat= + +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 -e 's|^.*/||' -e '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 + mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + 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-end: "$" +# End: diff --git a/jni/pdnsd/config.h b/jni/pdnsd/config.h new file mode 100644 index 00000000..2bfa2686 --- /dev/null +++ b/jni/pdnsd/config.h @@ -0,0 +1,437 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* ONLY EDIT acconfig.h, NEVER config.h or config.h.in! + * config.h MAY BE OVERWRITTEN BY make, config.h.in by autoheader! */ + +/* Define your Target here. Currently defined are TARGET_LINUX (any + * architecture), TARGET_BSD (experimental; tested on FreeBSD, hopefully + * works for other BSD variants) and TARGET_CYGWIN. */ +#define TARGET TARGET_LINUX + +/* change the #undef to #define if you do not want to compile with special + * ISDN support for Linux. Note that the ISDN support will not compile ok on + * unpatched kernerls earlier than 2.2.12 (if you did apply newer isdn patches, + * it may work fine). This is not on by default because it will cause compile + * problems on some systems */ +/* #undef ISDN_SUPPORT */ + +/* The following regulates the IP Protocol support. Supported types are IPv4 + * and IPv6 (aka IPng). You may enable either or both of these protocols. + * Enabling in this context means that support for the respective protocol + * will be in the binary. When running the binary, one of the protocols may + * be activated via command line switches. Note that activating both IPv4 and + * IPv6 is pointless (and will not work because two UDP and two TCP threads + * will be started that concur for ports). Because of that, it is not allowed. + * When pdnsd runs with IPv6 activated it should be able to service queries + * from IPv6 as well as from IPv4 hosts, provided that you host is configured + * properly. + * For each of the protocols there are two options: ENABLE_IPV4 and ENABLE_IPV6 + * control whether support for the respective protocol is available in the + * binary. DEFAULT_IPV4 selects which protocol is enabled on pdnsd + * startup by default. 1 means IPv4, while 0 means IPv6. If support for + * a protocol was included in the executable, you can specify command line + * parameters to activate or deactivate that protocol (the options are -4 and + * -6), but it makes more sense to use the run_ipv4=on/off option in the + * configuration file. + * Make your choice. Note that IPv6 support is experimental in pdnsd. + * In normal operation, you will currently only need IPv4. */ +#define ENABLE_IPV4 1 +#define DEFAULT_IPV4 1 +#undef ENABLE_IPV6 + +/* In all pdnsd versions before 1.0.6, DNS queries were always done over + * TCP. Now, you have the choice. You can control that behaviour using + * the -m command line switch, and you can give a preset here. There + * are 3 different modes: + * UDP_ONLY: This is undoubtedly the fastest query method, because + * no TCP negotiation needs to be done. + * TCP_ONLY: This is slower than uo, but generally more secure + * against DNS spoofing. Note that some name servers on the + * internet do not support TCP queries, notably dnscache. + * TCP_UDP: TCP, then UDP. If the TCP query fails with a "connection refused"- + * error or times out, the query is retried using UDP. + * UDP_TCP: UDP, then TCP. If the UDP reply is truncated (i.e. the tc flag is set), + * the query is retried using TCP. */ +#define M_PRESET TCP_ONLY + +/* In addition to choosing the presets, you may also completely disable + * one of the protocols (TCP for preset UDP_ONLY and UDP for preset TCP_ONLY). + * This saves some executable space. */ +/* #undef NO_UDP_QUERIES */ +/* #undef NO_TCP_QUERIES */ + +/* With the following option, you can disable the TCP server functionality + * of pdnsd. Nearly no program does TCP queries, so you probably can do + * this safely and save some executable space and one thread. + * You also can turn off the TCP server at runtime with the --notcp option. */ +/* #undef NO_TCP_SERVER */ + +/* By undefining the following, you can disable the UDP source address + * discovery code. This is not recommended, but you may need it when + * running into compilation problems. */ +#define SRC_ADDR_DISC 1 + +/* NO_POLL specifies not to use poll(2), but select(2) instead. If you are + * unsure about what this means, just leave this as it is.*/ +/* #undef NO_POLL */ + +/* Define this for "hard" RFC 2181 compliance: this RFC states that + * implementations should discard answers whose RR sets have multiple + * different time stamps. While correct answers are generated, incorrect + * ones are normally tolerated and corrected. Full RFC compliance is + * however only achieved by deactivating this behaviour and thus being + * intolerant. */ +/* #undef RFC2181_ME_HARDER */ + +/* Define this to the device you want to use for getting random numbers. + * Leave this undefined if you wand to use the standard C library random + * function, which basically should be sufficient. + * Linux and FreeBSD have two random number devices: /dev/random and + * /dev/urandom. /dev/urandom might be less secure in some cases, but + * should still be more than sufficient. The use of /dev/random is + * discouraged, as reading from this device blocks when new random bits + * need to be gathered. */ +/* #undef RANDOM_DEVICE */ +#define R_DEFAULT 1 +/* #undef R_RANDOM */ +/* #undef R_ARC4RANDOM */ +/*#define RANDOM_DEVICE "/dev/urandom"*/ + +/* Designate which database manager to use for cacheing. + * default: native; others: gdbm */ +#define CACHE_DBM DBM_NATIVE + +#define CONFDIR "/data/data/net.typeblog.socks" + +#define CACHEDIR "/data/data/net.typeblog.socks" + +#define TEMPDIR "/data/data/net.typeblog.socks/cache"; + +/* This is for various debugging facilities that produce debug output and + * double-check some values. You can enable debug messages with the -g option. + * Normally, you can switch this off safely by setting the number after DEBUG + * to 0. This will increase speed (although only marginally), save space + * in the executable (only about 12kB) and some stack space per thread + * (which may be significant if you have many threads running simultaneously). + * However, it may be an aid when debugging config files. + * The only defined debug levels by now are in the range 0 - 9. + * Define this to 9 if you want hex dumps of all the queries and replies pdnsd + * receives (you must also call pdnsd with -v9 to actually see the hex dumps). + * When in doubt, leave it defined to 1. */ +#define DEBUG 1 + +/* This defines the default verbosity of informational messages you will get. + This has nothing to to with the debug option (-g), but may be set with -v + option. 0 is for normal operation, up to 3 for debugging. + Unlike the debug messages, these messages will also be written to the syslog.*/ +#define VERBOSITY 0 + +/* Redefine this if you want another hash size. + * The number of hash buckets is computed as power of two (1< and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the `asprintf' function. */ +#define HAVE_ASPRINTF 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getline' function. */ +#if defined(__aarch64__) || defined(__x86_64__) +#define HAVE_GETLINE 1 +#endif + +/* Define to 1 if you have the `getpwnam_r' function. */ +//#define HAVE_GETPWNAM_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +//#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#define HAVE_MKFIFO 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if the system has the type `socklen_t'. */ +#define HAVE_SOCKLEN_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#if defined(__aarch64__) || defined(__x86_64__) +#define HAVE_STPCPY 1 +#endif + +/* Define to 1 if you have the `stpncpy' function. */ +//#define HAVE_STPNCPY 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if the system has the type `struct ifreq'. */ +#define HAVE_STRUCT_IFREQ 1 + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#define HAVE_STRUCT_IN6_ADDR 1 + +/* Define to 1 if the system has the type `struct in_pktinfo'. */ +#define HAVE_STRUCT_IN_PKTINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSLOG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vasprintf' function. */ +#define HAVE_VASPRINTF 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/jni/pdnsd/config.h.in b/jni/pdnsd/config.h.in new file mode 100644 index 00000000..c4ac9948 --- /dev/null +++ b/jni/pdnsd/config.h.in @@ -0,0 +1,430 @@ +/* config.h.in. Generated from configure.in by autoheader. */ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* ONLY EDIT acconfig.h, NEVER config.h or config.h.in! + * config.h MAY BE OVERWRITTEN BY make, config.h.in by autoheader! */ + +/* Define your Target here. Currently defined are TARGET_LINUX (any + * architecture), TARGET_BSD (experimental; tested on FreeBSD, hopefully + * works for other BSD variants) and TARGET_CYGWIN. */ +#define TARGET TARGET_LINUX + +/* change the #undef to #define if you do not want to compile with special + * ISDN support for Linux. Note that the ISDN support will not compile ok on + * unpatched kernerls earlier than 2.2.12 (if you did apply newer isdn patches, + * it may work fine). This is not on by default because it will cause compile + * problems on some systems */ +#undef ISDN_SUPPORT + +/* The following regulates the IP Protocol support. Supported types are IPv4 + * and IPv6 (aka IPng). You may enable either or both of these protocols. + * Enabling in this context means that support for the respective protocol + * will be in the binary. When running the binary, one of the protocols may + * be activated via command line switches. Note that activating both IPv4 and + * IPv6 is pointless (and will not work because two UDP and two TCP threads + * will be started that concur for ports). Because of that, it is not allowed. + * When pdnsd runs with IPv6 activated it should be able to service queries + * from IPv6 as well as from IPv4 hosts, provided that you host is configured + * properly. + * For each of the protocols there are two options: ENABLE_IPV4 and ENABLE_IPV6 + * control whether support for the respective protocol is available in the + * binary. DEFAULT_IPV4 selects which protocol is enabled on pdnsd + * startup by default. 1 means IPv4, while 0 means IPv6. If support for + * a protocol was included in the executable, you can specify command line + * parameters to activate or deactivate that protocol (the options are -4 and + * -6), but it makes more sense to use the run_ipv4=on/off option in the + * configuration file. + * Make your choice. Note that IPv6 support is experimental in pdnsd. + * In normal operation, you will currently only need IPv4. */ +#undef ENABLE_IPV4 +#define DEFAULT_IPV4 1 +#undef ENABLE_IPV6 + +/* In all pdnsd versions before 1.0.6, DNS queries were always done over + * TCP. Now, you have the choice. You can control that behaviour using + * the -m command line switch, and you can give a preset here. There + * are 3 different modes: + * UDP_ONLY: This is undoubtedly the fastest query method, because + * no TCP negotiation needs to be done. + * TCP_ONLY: This is slower than uo, but generally more secure + * against DNS spoofing. Note that some name servers on the + * internet do not support TCP queries, notably dnscache. + * TCP_UDP: TCP, then UDP. If the TCP query fails with a "connection refused"- + * error or times out, the query is retried using UDP. + * UDP_TCP: UDP, then TCP. If the UDP reply is truncated (i.e. the tc flag is set), + * the query is retried using TCP. */ +#define M_PRESET UDP_ONLY + +/* In addition to choosing the presets, you may also completely disable + * one of the protocols (TCP for preset UDP_ONLY and UDP for preset TCP_ONLY). + * This saves some executable space. */ +#undef NO_UDP_QUERIES +#undef NO_TCP_QUERIES + +/* With the following option, you can disable the TCP server functionality + * of pdnsd. Nearly no program does TCP queries, so you probably can do + * this safely and save some executable space and one thread. + * You also can turn off the TCP server at runtime with the --notcp option. */ +#undef NO_TCP_SERVER + +/* By undefining the following, you can disable the UDP source address + * discovery code. This is not recommended, but you may need it when + * running into compilation problems. */ +#undef SRC_ADDR_DISC + +/* NO_POLL specifies not to use poll(2), but select(2) instead. If you are + * unsure about what this means, just leave this as it is.*/ +#undef NO_POLL + +/* Define this for "hard" RFC 2181 compliance: this RFC states that + * implementations should discard answers whose RR sets have multiple + * different time stamps. While correct answers are generated, incorrect + * ones are normally tolerated and corrected. Full RFC compliance is + * however only achieved by deactivating this behaviour and thus being + * intolerant. */ +#undef RFC2181_ME_HARDER + +/* Define this to the device you want to use for getting random numbers. + * Leave this undefined if you wand to use the standard C library random + * function, which basically should be sufficient. + * Linux and FreeBSD have two random number devices: /dev/random and + * /dev/urandom. /dev/urandom might be less secure in some cases, but + * should still be more than sufficient. The use of /dev/random is + * discouraged, as reading from this device blocks when new random bits + * need to be gathered. */ +#undef RANDOM_DEVICE +#undef R_DEFAULT +#undef R_RANDOM +#undef R_ARC4RANDOM +/*#define RANDOM_DEVICE "/dev/urandom"*/ + +/* Designate which database manager to use for cacheing. + * default: native; others: gdbm */ +#define CACHE_DBM DBM_NATIVE + +#define CACHEDIR "/var/cache/pdnsd" + +#define TEMPDIR "/tmp"; + +/* This is for various debugging facilities that produce debug output and + * double-check some values. You can enable debug messages with the -g option. + * Normally, you can switch this off safely by setting the number after DEBUG + * to 0. This will increase speed (although only marginally), save space + * in the executable (only about 12kB) and some stack space per thread + * (which may be significant if you have many threads running simultaneously). + * However, it may be an aid when debugging config files. + * The only defined debug levels by now are in the range 0 - 9. + * Define this to 9 if you want hex dumps of all the queries and replies pdnsd + * receives (you must also call pdnsd with -v9 to actually see the hex dumps). + * When in doubt, leave it defined to 1. */ +#define DEBUG 1 + +/* This defines the default verbosity of informational messages you will get. + This has nothing to to with the debug option (-g), but may be set with -v + option. 0 is for normal operation, up to 3 for debugging. + Unlike the debug messages, these messages will also be written to the syslog.*/ +#define VERBOSITY 0 + +/* Redefine this if you want another hash size. + * The number of hash buckets is computed as power of two (1< and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the `asprintf' function. */ +#undef HAVE_ASPRINTF + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getline' function. */ +#undef HAVE_GETLINE + +/* Define to 1 if you have the `getpwnam_r' function. */ +#undef HAVE_GETPWNAM_R + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mempcpy' function. */ +#undef HAVE_MEMPCPY + +/* Define to 1 if you have the `mkfifo' function. */ +#undef HAVE_MKFIFO + +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if the system has the type `socklen_t'. */ +#undef HAVE_SOCKLEN_T + +/* 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 `stpcpy' function. */ +#undef HAVE_STPCPY + +/* Define to 1 if you have the `stpncpy' function. */ +#undef HAVE_STPNCPY + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* 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 + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strndup' function. */ +#undef HAVE_STRNDUP + +/* Define to 1 if the system has the type `struct ifreq'. */ +#undef HAVE_STRUCT_IFREQ + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#undef HAVE_STRUCT_IN6_ADDR + +/* Define to 1 if the system has the type `struct in_pktinfo'. */ +#undef HAVE_STRUCT_IN_PKTINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_POLL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_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_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* 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 version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/jni/pdnsd/configure b/jni/pdnsd/configure new file mode 100644 index 00000000..a3b78220 --- /dev/null +++ b/jni/pdnsd/configure @@ -0,0 +1,11389 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.63. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 + + + + +# PATH needs CR +# 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_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 +if (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 + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +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. +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); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# Required to use basename. +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 + + +# Name of the executable. +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'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +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 + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +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_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell bug-autoconf@gnu.org about your system, + echo including any error possibly output before this message. + echo This can help us improve future autoconf versions. + echo Configuration will now proceed without shell functions. +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. 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 + { (exit 1); exit 1; }; } + + # 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 +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +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 -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +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=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# 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 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, 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= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src" +# 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_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +ALLOCA +thread_CFLAGS +RANLIB +threadlib +specbuild +def_id +cachedir +distribution +packagerelease +fullversion +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +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 +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_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +with_distribution +with_target +with_cachedir +enable_isdn +enable_ipv4 +enable_ipv6 +enable_ipv4_startup +enable_ipv6_startup +enable_udp_queries +enable_tcp_queries +with_query_method +enable_tcp_server +enable_src_addr_disc +enable_socket_locking +enable_poll +enable_new_rrs +enable_strict_rfc2181 +with_random_device +enable_underscores +with_default_id +with_debug +with_verbosity +with_hash_buckets +enable_hash_debug +enable_rcsids +with_tcp_qtimeout +enable_tcp_subseq +with_par_queries +with_max_nameserver_ips +enable_specbuild +with_thread_lib +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# 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}' +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=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_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + 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_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + 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_echo "$as_me: error: invalid package name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + 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_echo "$as_me: error: invalid package name: $ac_useropt" >&2 + { (exit 1); exit 1; }; } + 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_echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + 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_echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 + { (exit 1); exit 1; }; } ;; + *) $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_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +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 + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + 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_echo "$as_me: error: working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# 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_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + 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 this package 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/PACKAGE] + --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 +_ACEOF +fi + +if test -n "$ac_init_help"; then + + 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] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-isdn Enable ISDN support (may cause problems on + some systems; only for Linux) + --disable-ipv4 Disable IPv4 networking support + (default=enabled) + --enable-ipv6 Enable IPv6 networking support + --disable-ipv4-startup Disable IPv4 on pdnsd startup by default + (default=enabled) + --enable-ipv6-startup Enable IPV6 on pdnsd startup by default + (default=IPv4) + --disable-udp-queries Disable udp as query method. + --disable-tcp-queries Disable tcp as query method. + --disable-tcp-server Disable the TCP serving ability of pdnsd + --disable-src-addr-disc Disable the UDP source address discovery + --enable-socket-locking Enable the UDP socket locking + --disable-poll Disable poll(2) and use select(2) + (default=enabled) + --disable-new-rrs Disable new DNS RR types (obsolete, currently ignored) + --enable-strict-rfc2181 Enforce strict RFC 2181 compliance + --enable-underscores Allow _ in domain names (obsolete, currently ignored) + --enable-hash-debug Debug hash tables (warning: massive output) + --enable-rcsids Enable RCS IDs in executables (obsolete, currently ignored) + --enable-tcp-subseq Enable multiple dns querys using one + tcp connection + --enable-specbuild Only used when building pdnsd from spec files + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-distribution=distro Specify target distribution (default=Generic; + others: RedHat, SuSE, Debian, ArchLinux) + --with-target=platform Change compilation target platform (default: + autodetect; others: Linux, BSD, Cygwin) + --with-cachedir=dir Default directory for pdnsd cache + (default=/var/cache/pdnsd) + --with-query-method=qm Specify the query method (default=udponly; + others: tcponly, tcpudp, udptcp) + --with-random-device=device Specify random device other than + /dev/random; default: C Library random() PRNG; + special value arc4random for BSD C Library + arc4random function (default on FreeBSD) + --with-default-id=id Specify default uid/gid for pdnsd + (default=nobody) + --with-debug=level Specify debugging level (0 means no debug support) + --with-verbosity=level Specify default message verbosity + --with-hash-buckets=num Number of hash buckets to use (default=1024). + The number actually used is the smallest power of two + greater or equal to the number specified here. + --with-tcp-qtimeout=secs Specify default tcp query timeout (default=30) + --with-par-queries=num Specify default parallel query number (default=2) + --with-max-nameserver-ips=num Specify maximum number of IP addresses used per nameserver obtained from NS records (default=3) + --with-thread-lib=lib Specify thread library, overriding automatic detection (for Linux only). + Possible values: LinuxThreads, + LinuxThreads2 (implements a fix for newer glibcs) + or NPTL (Native POSIX Thread Library) + +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 C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_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 +configure +generated by GNU Autoconf 2.63 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 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 +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 $as_me, which was +generated by GNU Autoconf 2.63. 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) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$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 + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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 + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + 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:$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= ;; #( + *) $as_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 + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + 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 + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + 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 + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + 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'; { (exit 1); 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 + +# 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 + + +# 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 + ac_site_file1=$CONFIG_SITE +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 -r "$ac_site_file"; then + { $as_echo "$as_me:$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" + 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. + if test -f "$cache_file"; then + { $as_echo "$as_me:$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:$LINENO: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# 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:$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:$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:$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:$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:$LINENO: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:$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. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:$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_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +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 + + + +package="pdnsd" +version=`cut -d - -f 1 "$srcdir"/version` +fullversion=`cat "$srcdir"/version` +packagerelease=`cut -d - -f 2- "$srcdir"/version` + +distribution="Generic" +target="autodetect" +cachedir="/var/cache/$package" +ipv4_default=1 +have_ipv4="yes" +#newrrs="yes" +query_m="udponly" +have_tcp_server="yes" +adisc="default" +slock="no"; +def_id="nobody" +#have_rcsids="no" +udp_queries="yes" +tcp_queries="yes" +tempdir="/tmp" +randomdev=default +freebsd_pthread="4" +specbuild=no +threadlib=default + +am__api_version='1.11' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; 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_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +$as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +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. + + +# 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:$LINENO: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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:$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:$LINENO: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# 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_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5 +$as_echo "$as_me: error: unsafe absolute working directory name" >&2;} + { (exit 1); exit 1; }; };; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5 +$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;} + { (exit 1); exit 1; }; };; +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 ( + 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 + rm -f conftest.file + 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_echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +$as_echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { $as_echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +$as_echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +{ $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } +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 --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:$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}" != 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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:$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:$LINENO: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:$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:$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:$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 test "${ac_cv_path_mkdir+set}" = set; 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 + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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 + + 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. + test -d ./--version && rmdir ./--version + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:$LINENO: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:$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 { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; 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:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:$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 + +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_echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +$as_echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } + 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=$package + VERSION=$version + + +# 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"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + +ac_config_headers="$ac_config_headers config.h" + +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:$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:$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='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +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 +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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + +# Provide some information about the compiler. +$as_echo "$as_me:$LINENO: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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:$LINENO: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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 + +{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +if test -z "$ac_file"; then + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + fi + fi +fi +{ $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +{ $as_echo "$as_me:$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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +fi + +rm -f conftest$ac_cv_exeext +{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:$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 test "${ac_cv_c_compiler_gnu+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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:$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:$LINENO: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$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:$LINENO: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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" + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$LINENO: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:$LINENO: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +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="$CC" am_compiler_list= + +{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; 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'. + 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 8's {/usr,}/bin/sh. + touch 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 + ;; + 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:$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 + + + +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:$LINENO: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:$LINENO: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } +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 + + +{ $as_echo "$as_me:$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 test "${ac_cv_path_GREP+set}" = set; 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" + { test -f "$ac_path_GREP" && $as_test_x "$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 + ac_count=`expr $ac_count + 1` + 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_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:$LINENO: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; 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" + { test -f "$ac_path_EGREP" && $as_test_x "$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 + ac_count=`expr $ac_count + 1` + 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_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +rm -f 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +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 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +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` +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + if test "${ac_cv_header_minix_config_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for minix/config.h" >&5 +$as_echo_n "checking for minix/config.h... " >&6; } +if test "${ac_cv_header_minix_config_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5 +$as_echo "$ac_cv_header_minix_config_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking minix/config.h usability" >&5 +$as_echo_n "checking minix/config.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking minix/config.h presence" >&5 +$as_echo_n "checking minix/config.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$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_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: minix/config.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: minix/config.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for minix/config.h" >&5 +$as_echo_n "checking for minix/config.h... " >&6; } +if test "${ac_cv_header_minix_config_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_minix_config_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5 +$as_echo "$ac_cv_header_minix_config_h" >&6; } + +fi +if test "x$ac_cv_header_minix_config_h" = x""yes; then + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_SOURCE 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _POSIX_1_SOURCE 2 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define _MINIX 1 +_ACEOF + + fi + + + + { $as_echo "$as_me:$LINENO: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if test "${ac_cv_safe_to_define___extensions__+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_safe_to_define___extensions__=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_safe_to_define___extensions__=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + cat >>confdefs.h <<\_ACEOF +#define __EXTENSIONS__ 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define _ALL_SOURCE 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define _GNU_SOURCE 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define _POSIX_PTHREAD_SEMANTICS 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define _TANDEM_SOURCE 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$fullversion" +_ACEOF + + + + + +# Check whether --with-distribution was given. +if test "${with_distribution+set}" = set; then + withval=$with_distribution; distribution=$withval +fi + + + + +# Check whether --with-target was given. +if test "${with_target+set}" = set; then + withval=$with_target; target=$withval +fi + +case $target in + Linux|linux) + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_LINUX +_ACEOF + + target="Linux" + ;; + BSD| bsd) + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_BSD +_ACEOF + + target="BSD" + ;; + Cygwin|CYGWIN|cygwin) + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_CYGWIN +_ACEOF + + target="cygwin" + ;; + autodetect) + ;; + *) + { { $as_echo "$as_me:$LINENO: error: --with-target must have Linux, BSD or Cygwin as parameter." >&5 +$as_echo "$as_me: error: --with-target must have Linux, BSD or Cygwin as parameter." >&2;} + { (exit 1); exit 1; }; } + ;; +esac + + +# Check whether --with-cachedir was given. +if test "${with_cachedir+set}" = set; then + withval=$with_cachedir; cachedir=$withval +fi + +cat >>confdefs.h <<_ACEOF +#define CACHEDIR "$cachedir" +_ACEOF + + + +# Check whether --enable-isdn was given. +if test "${enable_isdn+set}" = set; then + enableval=$enable_isdn; test $enableval = "yes" && cat >>confdefs.h <<\_ACEOF +#define ISDN_SUPPORT 1 +_ACEOF + +fi + + +# Check whether --enable-ipv4 was given. +if test "${enable_ipv4+set}" = set; then + enableval=$enable_ipv4; have_ipv4=$enableval +fi + + +test $have_ipv4 = "yes" && cat >>confdefs.h <<\_ACEOF +#define ENABLE_IPV4 1 +_ACEOF + + +# Check whether --enable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval=$enable_ipv6; if test $enableval = "yes" ; then + cat >>confdefs.h <<\_ACEOF +#define ENABLE_IPV6 1 +_ACEOF + + if test $have_ipv4 != "yes" ; then + ipv4_default=0 + fi + fi +fi + + +# Check whether --enable-ipv4-startup was given. +if test "${enable_ipv4_startup+set}" = set; then + enableval=$enable_ipv4_startup; if test $enableval = "yes" ; then + ipv4_default=1 + else + ipv4_default=0 + fi +fi + + +# Check whether --enable-ipv6-startup was given. +if test "${enable_ipv6_startup+set}" = set; then + enableval=$enable_ipv6_startup; if test $enableval = "yes" ; then + ipv4_default=0 + else + ipv4_default=1 + fi +fi + + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_IPV4 $ipv4_default +_ACEOF + + +# Check whether --enable-udp-queries was given. +if test "${enable_udp_queries+set}" = set; then + enableval=$enable_udp_queries; udp_queries=$enableval +fi + + +# Check whether --enable-tcp-queries was given. +if test "${enable_tcp_queries+set}" = set; then + enableval=$enable_tcp_queries; tcp_queries=$enableval +fi + + + +# Check whether --with-query-method was given. +if test "${with_query_method+set}" = set; then + withval=$with_query_method; query_m=$withval +fi + +case $query_m in + udponly|UDPonly) + cat >>confdefs.h <<\_ACEOF +#define M_PRESET UDP_ONLY +_ACEOF + + udp_queries=yes; + ;; + tcponly|TCPonly) + cat >>confdefs.h <<\_ACEOF +#define M_PRESET TCP_ONLY +_ACEOF + + tcp_queries=yes; + ;; + tcpudp|TCPUDP) + cat >>confdefs.h <<\_ACEOF +#define M_PRESET TCP_UDP +_ACEOF + + udp_queries=yes; + tcp_queries=yes; + ;; + udptcp|UDPTCP) + cat >>confdefs.h <<\_ACEOF +#define M_PRESET UDP_TCP +_ACEOF + + udp_queries=yes; + tcp_queries=yes; + ;; + *) + { { $as_echo "$as_me:$LINENO: error: --with-query-method must have udponly, tcponly, tcpudp or udptcp as parameter." >&5 +$as_echo "$as_me: error: --with-query-method must have udponly, tcponly, tcpudp or udptcp as parameter." >&2;} + { (exit 1); exit 1; }; } + ;; +esac + +test $udp_queries != "yes" && cat >>confdefs.h <<\_ACEOF +#define NO_UDP_QUERIES 1 +_ACEOF + +test $tcp_queries != "yes" && cat >>confdefs.h <<\_ACEOF +#define NO_TCP_QUERIES 1 +_ACEOF + + +# Check whether --enable-tcp-server was given. +if test "${enable_tcp_server+set}" = set; then + enableval=$enable_tcp_server; have_tcp_server=$enableval +fi + + +test $have_tcp_server != "yes" && cat >>confdefs.h <<\_ACEOF +#define NO_TCP_SERVER 1 +_ACEOF + + +# Check whether --enable-src-addr-disc was given. +if test "${enable_src_addr_disc+set}" = set; then + enableval=$enable_src_addr_disc; adisc=$enableval +fi + + +# Check whether --enable-socket-locking was given. +if test "${enable_socket_locking+set}" = set; then + enableval=$enable_socket_locking; slock=$enableval +fi + + +test $slock = "yes" && cat >>confdefs.h <<\_ACEOF +#define SOCKET_LOCKING 1 +_ACEOF + + +# Check whether --enable-poll was given. +if test "${enable_poll+set}" = set; then + enableval=$enable_poll; test $enableval != "yes" && cat >>confdefs.h <<\_ACEOF +#define NO_POLL 1 +_ACEOF + +fi + + +# Check whether --enable-new-rrs was given. +if test "${enable_new_rrs+set}" = set; then + enableval=$enable_new_rrs; newrrs=$enableval +fi + + +# Check whether --enable-strict-rfc2181 was given. +if test "${enable_strict_rfc2181+set}" = set; then + enableval=$enable_strict_rfc2181; test $enableval = "yes" && cat >>confdefs.h <<\_ACEOF +#define RFC2181_ME_HARDER 1 +_ACEOF + +fi + + + +# Check whether --with-random-device was given. +if test "${with_random_device+set}" = set; then + withval=$with_random_device; randomdev=$withval +fi + + +if test "$randomdev" = arc4random ; then + cat >>confdefs.h <<\_ACEOF +#define R_ARC4RANDOM 1 +_ACEOF + +elif test "$randomdev" = random ; then + cat >>confdefs.h <<\_ACEOF +#define R_RANDOM 1 +_ACEOF + +elif test "$randomdev" = default ; then + cat >>confdefs.h <<\_ACEOF +#define R_DEFAULT 1 +_ACEOF + +else + cat >>confdefs.h <<_ACEOF +#define RANDOM_DEVICE "$randomdev" +_ACEOF + +fi + +# Check whether --enable-underscores was given. +if test "${enable_underscores+set}" = set; then + enableval=$enable_underscores; underscores=$enableval +fi + + + +# Check whether --with-default-id was given. +if test "${with_default_id+set}" = set; then + withval=$with_default_id; def_id=$withval +fi + + + + +# Check whether --with-debug was given. +if test "${with_debug+set}" = set; then + withval=$with_debug; cat >>confdefs.h <<_ACEOF +#define DEBUG $withval +_ACEOF + +fi + + + +# Check whether --with-verbosity was given. +if test "${with_verbosity+set}" = set; then + withval=$with_verbosity; cat >>confdefs.h <<_ACEOF +#define VERBOSITY $withval +_ACEOF + +fi + + + +# Check whether --with-hash-buckets was given. +if test "${with_hash_buckets+set}" = set; then + withval=$with_hash_buckets; powof2=1 + hashsz=0 + + while test $powof2 -lt "$withval" + do + powof2=`expr 2 '*' $powof2` + hashsz=`expr $hashsz '+' 1` + done + cat >>confdefs.h <<_ACEOF +#define HASH_SZ $hashsz +_ACEOF + + +fi + + +# Check whether --enable-hash-debug was given. +if test "${enable_hash_debug+set}" = set; then + enableval=$enable_hash_debug; test $enableval = "yes" && cat >>confdefs.h <<\_ACEOF +#define DEBUG_HASH 1 +_ACEOF + +fi + + +# Check whether --enable-rcsids was given. +if test "${enable_rcsids+set}" = set; then + enableval=$enable_rcsids; have_rcsids=$enableval +fi + + + +# Check whether --with-tcp-qtimeout was given. +if test "${with_tcp_qtimeout+set}" = set; then + withval=$with_tcp_qtimeout; cat >>confdefs.h <<_ACEOF +#define TCP_TIMEOUT $withval +_ACEOF + +fi + + +# Check whether --enable-tcp-subseq was given. +if test "${enable_tcp_subseq+set}" = set; then + enableval=$enable_tcp_subseq; test $enableval = "yes" && cat >>confdefs.h <<\_ACEOF +#define TCP_SUBSEQ 1 +_ACEOF + +fi + + + +# Check whether --with-par-queries was given. +if test "${with_par_queries+set}" = set; then + withval=$with_par_queries; cat >>confdefs.h <<_ACEOF +#define PAR_QUERIES $withval +_ACEOF + +fi + + + +# Check whether --with-max-nameserver-ips was given. +if test "${with_max_nameserver_ips+set}" = set; then + withval=$with_max_nameserver_ips; cat >>confdefs.h <<_ACEOF +#define MAXNAMESERVIPS $withval +_ACEOF + +fi + + +# Check whether --enable-specbuild was given. +if test "${enable_specbuild+set}" = set; then + enableval=$enable_specbuild; specbuild=$enableval +fi + + + + + +# Check whether --with-thread-lib was given. +if test "${with_thread_lib+set}" = set; then + withval=$with_thread_lib; threadlib=$withval +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 +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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + +# Provide some information about the compiler. +$as_echo "$as_me:$LINENO: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ $as_echo "$as_me:$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 test "${ac_cv_c_compiler_gnu+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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:$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:$LINENO: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$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:$LINENO: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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" + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$LINENO: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:$LINENO: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +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="$CC" am_compiler_list= + +{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; 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'. + 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 8's {/usr,}/bin/sh. + touch 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 + ;; + 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:$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 + + +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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:$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:$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:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; }; } + +# Provide some information about the compiler. +$as_echo "$as_me:$LINENO: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ $as_echo "$as_me:$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 test "${ac_cv_c_compiler_gnu+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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:$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:$LINENO: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$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:$LINENO: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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" + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +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:$LINENO: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:$LINENO: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +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="$CC" am_compiler_list= + +{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; 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'. + 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 8's {/usr,}/bin/sh. + touch 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 + ;; + 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:$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 + + + +am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc + +if test "x$CC" != xcc; then + { $as_echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + test -f conftest2.$ac_objext && { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + test -f conftest2.$ac_objext && { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define NO_MINUS_C_MINUS_O 1 +_ACEOF + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != 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 + + +# 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:$LINENO: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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:$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' + + +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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:$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:$LINENO: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:$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:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:$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:$LINENO: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:$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:$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 + + +if test "$target" = "autodetect" ; then + { $as_echo "$as_me:$LINENO: checking for autodetect build target" >&5 +$as_echo_n "checking for autodetect build target... " >&6; } + uname_sys=`uname` + if test $? -ne 0 ; then + { $as_echo "$as_me:$LINENO: result: failed" >&5 +$as_echo "failed" >&6; } + { { $as_echo "$as_me:$LINENO: error: uname failed or was not found in path" >&5 +$as_echo "$as_me: error: uname failed or was not found in path" >&2;} + { (exit 1); exit 1; }; } + else + case "${uname_sys}" in + Linux) + { $as_echo "$as_me:$LINENO: result: Linux" >&5 +$as_echo "Linux" >&6; } + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_LINUX +_ACEOF + + target="Linux" + ;; + FreeBSD|NetBSD|OpenBSD|Darwin) + { $as_echo "$as_me:$LINENO: result: \"${uname_sys}\"" >&5 +$as_echo "\"${uname_sys}\"" >&6; } + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_BSD +_ACEOF + + target="BSD" + ;; + CYGWIN*) + { $as_echo "$as_me:$LINENO: result: \"${uname_sys}\"" >&5 +$as_echo "\"${uname_sys}\"" >&6; } + cat >>confdefs.h <<\_ACEOF +#define TARGET TARGET_CYGWIN +_ACEOF + + target="cygwin" + ;; + *) + { $as_echo "$as_me:$LINENO: result: failed" >&5 +$as_echo "failed" >&6; } + { { $as_echo "$as_me:$LINENO: error: Your system type could not be identified. Try setting it manually using +--with-target" >&5 +$as_echo "$as_me: error: Your system type could not be identified. Try setting it manually using +--with-target" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + fi +fi + +#if test "$target" = BSD ; then +# uname_sys=`uname` +# if test "$uname_sys" = FreeBSD ; then +# AC_MSG_CHECKING([for FreeBSD version]) +# osrel=`sysctl -n kern.osreldate` +# if test $osrel -ge 500016 ; then +# AC_MSG_RESULT([5.0 (>= 500016)]) +# freebsd_pthread="5" +# else +# AC_MSG_RESULT([<=5.0 (< 500016)]) +# freebsd_pthread="4" +# fi +# fi +#fi + +if test "$adisc" = "default"; then + if test "$target" = "cygwin" ; then +# Don't do UDP source address discovery on Cygwin platform by default. + adisc="no" + else + adisc="yes" + fi +fi + +test "$adisc" = "yes" && cat >>confdefs.h <<\_ACEOF +#define SRC_ADDR_DISC 1 +_ACEOF + + + +if test "$target" = "Linux"; then +{ $as_echo "$as_me:$LINENO: checking if we can compile and link with -pthread" >&5 +$as_echo_n "checking if we can compile and link with -pthread... " >&6; } +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -pthread" +cat >conftest.$ac_ext <<_ACEOF + +#include + +void *thread_func(void *data) +{ + *((int *)data)=1; + return data; +} + +int main() +{ + pthread_t thread; + void *retval; + int val; + + if(pthread_create(&thread, NULL, thread_func, &val)) + return 1; + + if(pthread_join(thread,&retval)) + return 1; + + return (*((int *)retval)!=1); +} + +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + gcc_pthread_flag="yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + gcc_pthread_flag="no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS="$old_CFLAGS" +{ $as_echo "$as_me:$LINENO: result: $gcc_pthread_flag" >&5 +$as_echo "$gcc_pthread_flag" >&6; } + + if test "$gcc_pthread_flag" = yes ; then + thread_CFLAGS="-pthread" + + else + +{ $as_echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 +$as_echo_n "checking for pthread_create in -lpthread... " >&6; } +if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_lib_pthread_pthread_create=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pthread_pthread_create=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + fi +fi +if test "$target" = "BSD" -a `uname` != Darwin ; then +# if test $freebsd_pthread = 4 ; then + thread_CFLAGS="-pthread" + +# else +# AC_CHECK_LIB(c_r, pthread_create, , +# AC_MSG_ERROR([You must have libc_r installed to build/run pdnsd!])) +# fi; +fi + +if test "$target" = "Linux" -a "$threadlib" = default; then +{ $as_echo "$as_me:$LINENO: checking if this is an NPTL-based system" >&5 +$as_echo_n "checking if this is an NPTL-based system... " >&6; } +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $thread_CFLAGS" +if test "$cross_compiling" = yes; then + + { $as_echo "$as_me:$LINENO: result: couldn't run test program" >&5 +$as_echo "couldn't run test program" >&6; } + threadlib=linuxthreads + +else + cat >conftest.$ac_ext <<_ACEOF + +#include +#include +#include +#include +#include +#include + +/* All this function does is return its PID (in a roundabout way). */ +void *thread_func(void *data) +{ + *((int *)data)=getpid(); + return data; +} + +int main() +{ + pthread_t thread; + void *retval; + int err,mainpid,thrdpid; + + err=pthread_create(&thread, NULL, thread_func, &thrdpid); + if(err) { + fprintf(stderr,"pthread_create failed: %s\n",strerror(err)); + return 1; + } + err=pthread_join(thread,&retval); + if(err) { + fprintf(stderr,"pthread_join failed: %s\n",strerror(err)); + return 1; + } + mainpid=getpid(); + /* In LinuxThreads implementations, the pids of the threads will usually differ + in a non Posix-compliant way. */ + fprintf(stderr,"main pid=%d, thread pid=%d\n",mainpid,*((int *)retval)); + return (*((int *)retval)!=mainpid); +} + +_ACEOF +rm -f 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + { $as_echo "$as_me:$LINENO: result: yes" >&5 +$as_echo "yes" >&6; } + threadlib=nptl + +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 + +( exit $ac_status ) + + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } + threadlib=linuxthreads + +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +CFLAGS="$old_CFLAGS" +fi + +if test "$threadlib" = nptl -o "$threadlib" = NPTL; then + cat >>confdefs.h <<\_ACEOF +#define THREADLIB_NPTL 1 +_ACEOF + +elif test "$threadlib" = linuxthreads2 -o "$threadlib" = LinuxThreads2 -o "$threadlib" = lt2; then + cat >>confdefs.h <<\_ACEOF +#define THREADLIB_LINUXTHREADS2 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +rm -f 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +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 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_sys_wait_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + + + + + + + +for ac_header in fcntl.h malloc.h sys/ioctl.h sys/time.h syslog.h unistd.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$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_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + +for ac_header in sys/types.h sys/socket.h net/if.h netinet/in.h sys/poll.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif + + +#include <$ac_header> +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if test "${ac_cv_c_const+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_const=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const /**/ +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for pid_t" >&5 +$as_echo_n "checking for pid_t... " >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_pid_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (pid_t)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((pid_t))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +$as_echo "$ac_cv_type_pid_t" >&6; } +if test "x$ac_cv_type_pid_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for size_t" >&5 +$as_echo_n "checking for size_t... " >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_size_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if (sizeof ((size_t))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +$as_echo "$ac_cv_type_size_t" >&6; } +if test "x$ac_cv_type_size_t" = x""yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if test "${ac_cv_header_time+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_time=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$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 test "${ac_cv_struct_tm+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_struct_tm=time.h +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_struct_tm=sys/time.h +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for socklen_t" >&5 +$as_echo_n "checking for socklen_t... " >&6; } +if test "${ac_cv_type_socklen_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_socklen_t=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof (socklen_t)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof ((socklen_t))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_socklen_t=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5 +$as_echo "$ac_cv_type_socklen_t" >&6; } +if test "x$ac_cv_type_socklen_t" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_SOCKLEN_T 1 +_ACEOF + + +else + cat >>confdefs.h <<\_ACEOF +#define socklen_t int +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for struct in6_addr" >&5 +$as_echo_n "checking for struct in6_addr... " >&6; } +if test "${ac_cv_type_struct_in6_addr+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_struct_in6_addr=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof (struct in6_addr)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof ((struct in6_addr))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_struct_in6_addr=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_struct_in6_addr" >&5 +$as_echo "$ac_cv_type_struct_in6_addr" >&6; } +if test "x$ac_cv_type_struct_in6_addr" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN6_ADDR 1 +_ACEOF + + +fi +{ $as_echo "$as_me:$LINENO: checking for struct in_pktinfo" >&5 +$as_echo_n "checking for struct in_pktinfo... " >&6; } +if test "${ac_cv_type_struct_in_pktinfo+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_struct_in_pktinfo=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof (struct in_pktinfo)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof ((struct in_pktinfo))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_struct_in_pktinfo=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_struct_in_pktinfo" >&5 +$as_echo "$ac_cv_type_struct_in_pktinfo" >&6; } +if test "x$ac_cv_type_struct_in_pktinfo" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN_PKTINFO 1 +_ACEOF + + +fi +{ $as_echo "$as_me:$LINENO: checking for struct ifreq" >&5 +$as_echo_n "checking for struct ifreq... " >&6; } +if test "${ac_cv_type_struct_ifreq+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_type_struct_ifreq=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof (struct ifreq)) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ +if (sizeof ((struct ifreq))) + return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_struct_ifreq=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_struct_ifreq" >&5 +$as_echo "$ac_cv_type_struct_ifreq" >&6; } +if test "x$ac_cv_type_struct_ifreq" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IFREQ 1 +_ACEOF + + +fi + + +{ $as_echo "$as_me:$LINENO: checking for CPP C99 Variadic macro support" >&5 +$as_echo_n "checking for CPP C99 Variadic macro support... " >&6; } +cat >conftest.$ac_ext <<_ACEOF + +#define a(...) junk(0,__VA_ARGS__) +extern void junk(int i,...); +int main() +{ + a(0); + a("a"); + a(0, "a", 1); + return 0; +} + +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + cpp_c99_variadic="yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cpp_c99_variadic="no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $cpp_c99_variadic" >&5 +$as_echo "$cpp_c99_variadic" >&6; } +if test $cpp_c99_variadic = yes; then + cat >>confdefs.h <<\_ACEOF +#define CPP_C99_VARIADIC_MACROS 1 +_ACEOF + +else + if test "$GCC" != yes; then + { { $as_echo "$as_me:$LINENO: error: Compiler must support C99 or gcc variadic macros" >&5 +$as_echo "$as_me: error: Compiler must support C99 or gcc variadic macros" >&2;} + { (exit 1); exit 1; }; } + fi; +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:$LINENO: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if test "${ac_cv_working_alloca_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_working_alloca_h=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_working_alloca_h=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +{ $as_echo "$as_me:$LINENO: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if test "${ac_cv_func_alloca_works+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func_alloca_works=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_alloca_works=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +{ $as_echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if test "${ac_cv_os_cray+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* 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 $ac_func (); +/* 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_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if test "${ac_cv_c_stack_direction+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + return find_stack_direction () < 0; +} +_ACEOF +rm -f 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +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 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } + +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if test "${ac_cv_prog_gcc_traditional+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +{ $as_echo "$as_me:$LINENO: checking for working memcmp" >&5 +$as_echo_n "checking for working memcmp... " >&6; } +if test "${ac_cv_func_memcmp_working+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_memcmp_working=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Some versions of memcmp are not 8-bit clean. */ + char c0 = '\100', c1 = '\200', c2 = '\201'; + if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) + return 1; + + /* The Next x86 OpenStep bug shows up only when comparing 16 bytes + or more and with at least one buffer not starting on a 4-byte boundary. + William Lewis provided this test program. */ + { + char foo[21]; + char bar[21]; + int i; + for (i = 0; i < 4; i++) + { + char *a = foo + i; + char *b = bar + i; + strcpy (a, "--------01111111"); + strcpy (b, "--------10000000"); + if (memcmp (a, b, 16) >= 0) + return 1; + } + return 0; + } + + ; + return 0; +} +_ACEOF +rm -f 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_memcmp_working=yes +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 + +( exit $ac_status ) +ac_cv_func_memcmp_working=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5 +$as_echo "$ac_cv_func_memcmp_working" >&6; } +test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +{ $as_echo "$as_me:$LINENO: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if test "${ac_cv_type_signal+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_signal=int +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_signal=void +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + + +for ac_func in vprintf +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* 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 $ac_func (); +/* 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_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +{ $as_echo "$as_me:$LINENO: checking for _doprnt" >&5 +$as_echo_n "checking for _doprnt... " >&6; } +if test "${ac_cv_func__doprnt+set}" = set; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _doprnt to an innocuous variant, in case declares _doprnt. + For example, HP-UX 11i declares gettimeofday. */ +#define _doprnt innocuous__doprnt + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _doprnt (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _doprnt + +/* 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 _doprnt (); +/* 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__doprnt || defined __stub____doprnt +choke me +#endif + +int +main () +{ +return _doprnt (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_func__doprnt=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func__doprnt=no +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 +$as_echo "$ac_cv_func__doprnt" >&6; } +if test "x$ac_cv_func__doprnt" = x""yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOPRNT 1 +_ACEOF + +fi + +fi +done + + +{ $as_echo "$as_me:$LINENO: checking for library containing nanosleep" >&5 +$as_echo_n "checking for library containing nanosleep... " >&6; } +if test "${ac_cv_search_nanosleep+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 nanosleep (); +int +main () +{ +return nanosleep (); + ; + 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 + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_search_nanosleep=$ac_res +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_nanosleep+set}" = set; then + break +fi +done +if test "${ac_cv_search_nanosleep+set}" = set; then + : +else + ac_cv_search_nanosleep=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_nanosleep" >&5 +$as_echo "$ac_cv_search_nanosleep" >&6; } +ac_res=$ac_cv_search_nanosleep +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:$LINENO: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if test "${ac_cv_search_socket+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 -lnsl $ac_func_search_save_LIBS" + fi + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_search_socket=$ac_res +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_socket+set}" = set; then + break +fi +done +if test "${ac_cv_search_socket+set}" = set; then + : +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:$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:$LINENO: checking for library containing inet_aton" >&5 +$as_echo_n "checking for library containing inet_aton... " >&6; } +if test "${ac_cv_search_inet_aton+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 + 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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + ac_cv_search_inet_aton=$ac_res +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_inet_aton+set}" = set; then + break +fi +done +if test "${ac_cv_search_inet_aton+set}" = set; then + : +else + ac_cv_search_inet_aton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:$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 + + + + + + + + + + +for ac_func in nanosleep gettimeofday mkfifo select socket strerror uname snprintf vsnprintf +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* 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 $ac_func (); +/* 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_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + true +else + { { $as_echo "$as_me:$LINENO: error: One of the functions required for pdnsd were not found." >&5 +$as_echo "$as_me: error: One of the functions required for pdnsd were not found." >&2;} + { (exit 1); exit 1; }; } +fi +done + + +for ac_func in poll +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* 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 $ac_func (); +/* 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_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + true +else + cat >>confdefs.h <<\_ACEOF +#define NO_POLL 1 +_ACEOF + +fi +done + + + + + + + + + + + + + +for ac_func in strdup strndup stpcpy stpncpy strlcpy mempcpy getline asprintf vasprintf getpwnam_r inet_ntop inet_pton +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* 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 $ac_func (); +/* 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_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +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:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_config_files="$ac_config_files pdnsd.spec Makefile file-list.base contrib/Makefile doc/Makefile doc/pdnsd.8 doc/pdnsd.conf.5 doc/pdnsd.conf src/Makefile src/pdnsd-ctl/Makefile src/rc/Makefile src/rc/RedHat/Makefile src/rc/RedHat/pdnsd src/rc/SuSE/Makefile src/rc/SuSE/pdnsd src/rc/Debian/Makefile src/rc/Debian/pdnsd src/rc/Slackware/Makefile src/rc/Slackware/rc.pdnsd src/rc/ArchLinux/Makefile src/rc/ArchLinux/pdnsd src/test/Makefile PKGBUILD" + +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:$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= ;; #( + *) $as_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 + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:$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= +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. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + 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_echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +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:$LINENO: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF || ac_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} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_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 + + + + +# PATH needs CR +# 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_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 +if (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 + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +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. +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); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# Required to use basename. +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 + + +# Name of the executable. +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'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. 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 + { (exit 1); exit 1; }; } + + # 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 +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +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 -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +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=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# 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 + +# 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 $as_me, which was +generated by GNU Autoconf 2.63. 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 from templates according to the +current configuration. + +Usage: $0 [OPTION]... [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, 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 ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.63, + with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2008 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=$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 ;; + --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"` ;; + esac + CONFIG_FILES="$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 + CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { $as_echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --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_echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$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" + +_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" ;; + "pdnsd.spec") CONFIG_FILES="$CONFIG_FILES pdnsd.spec" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "file-list.base") CONFIG_FILES="$CONFIG_FILES file-list.base" ;; + "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/pdnsd.8") CONFIG_FILES="$CONFIG_FILES doc/pdnsd.8" ;; + "doc/pdnsd.conf.5") CONFIG_FILES="$CONFIG_FILES doc/pdnsd.conf.5" ;; + "doc/pdnsd.conf") CONFIG_FILES="$CONFIG_FILES doc/pdnsd.conf" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/pdnsd-ctl/Makefile") CONFIG_FILES="$CONFIG_FILES src/pdnsd-ctl/Makefile" ;; + "src/rc/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/Makefile" ;; + "src/rc/RedHat/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/RedHat/Makefile" ;; + "src/rc/RedHat/pdnsd") CONFIG_FILES="$CONFIG_FILES src/rc/RedHat/pdnsd" ;; + "src/rc/SuSE/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/SuSE/Makefile" ;; + "src/rc/SuSE/pdnsd") CONFIG_FILES="$CONFIG_FILES src/rc/SuSE/pdnsd" ;; + "src/rc/Debian/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/Debian/Makefile" ;; + "src/rc/Debian/pdnsd") CONFIG_FILES="$CONFIG_FILES src/rc/Debian/pdnsd" ;; + "src/rc/Slackware/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/Slackware/Makefile" ;; + "src/rc/Slackware/rc.pdnsd") CONFIG_FILES="$CONFIG_FILES src/rc/Slackware/rc.pdnsd" ;; + "src/rc/ArchLinux/Makefile") CONFIG_FILES="$CONFIG_FILES src/rc/ArchLinux/Makefile" ;; + "src/rc/ArchLinux/pdnsd") CONFIG_FILES="$CONFIG_FILES src/rc/ArchLinux/pdnsd" ;; + "src/test/Makefile") CONFIG_FILES="$CONFIG_FILES src/test/Makefile" ;; + "PKGBUILD") CONFIG_FILES="$CONFIG_FILES PKGBUILD" ;; + + *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + 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= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + $as_echo "$as_me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# 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=' ' +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 {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } +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_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + + 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_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + 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 >>"\$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 >>"\$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 < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5 +$as_echo "$as_me: error: could not setup config files machinery" >&2;} + { (exit 1); exit 1; }; } +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ 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[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +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 >"$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_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5 +$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;} + { (exit 1); exit 1; }; } + 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_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5 +$as_echo "$as_me: error: could not setup config headers machinery" >&2;} + { (exit 1); exit 1; }; } +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_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5 +$as_echo "$as_me: error: invalid tag $ac_tag" >&2;} + { (exit 1); exit 1; }; };; + :[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="$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_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + ac_file_inputs="$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:$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 >"$tmp/stdin" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } ;; + 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" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + 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_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +$as_echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + 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:$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 "$tmp/subs.awk" >$tmp/out \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:$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 "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 +$as_echo "$as_me: error: could not create $ac_file" >&2;} + { (exit 1); exit 1; }; } + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5 +$as_echo "$as_me: error: could not create -" >&2;} + { (exit 1); exit 1; }; } + 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:$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"" || { + # Autoconf 2.62 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"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //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' -e 's/\$U/'"$U"'/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 + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + 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_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +$as_echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + + +# 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 || { (exit 1); exit 1; } +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/jni/pdnsd/configure.in b/jni/pdnsd/configure.in new file mode 100644 index 00000000..473abf17 --- /dev/null +++ b/jni/pdnsd/configure.in @@ -0,0 +1,548 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(src) + +package="pdnsd" +version=`cut -d - -f 1 "$srcdir"/version` +fullversion=`cat "$srcdir"/version` +packagerelease=`cut -d - -f 2- "$srcdir"/version` + +distribution="Generic" +target="autodetect" +cachedir="/var/cache/$package" +ipv4_default=1 +have_ipv4="yes" +#newrrs="yes" +query_m="udponly" +have_tcp_server="yes" +adisc="default" +slock="no"; +def_id="nobody" +#have_rcsids="no" +udp_queries="yes" +tcp_queries="yes" +tempdir="/tmp" +randomdev=default +freebsd_pthread="4" +specbuild=no +threadlib=default + +AM_INIT_AUTOMAKE($package, $version, [no-define]) +AM_CONFIG_HEADER(config.h) +AC_GNU_SOURCE +AC_DEFINE_UNQUOTED(VERSION,"$fullversion") +AC_SUBST(fullversion) +AC_SUBST(packagerelease) + +AC_ARG_WITH(distribution, +[ --with-distribution=distro Specify target distribution (default=Generic; + others: RedHat, SuSE, Debian, ArchLinux)], + distribution=$withval) +AC_SUBST(distribution) + +AC_ARG_WITH(target, +[ --with-target=platform Change compilation target platform (default: + autodetect; others: Linux, BSD, Cygwin)], + target=$withval) +case $target in + Linux|linux) + AC_DEFINE(TARGET, TARGET_LINUX) + target="Linux" + ;; + BSD| bsd) + AC_DEFINE(TARGET, TARGET_BSD) + target="BSD" + ;; + Cygwin|CYGWIN|cygwin) + AC_DEFINE(TARGET, TARGET_CYGWIN) + target="cygwin" + ;; + autodetect) + ;; + *) + AC_MSG_ERROR([--with-target must have Linux, BSD or Cygwin as parameter.]) + ;; +esac + +AC_ARG_WITH(cachedir, +[ --with-cachedir=dir Default directory for pdnsd cache + (default=/var/cache/pdnsd)], + cachedir=$withval) +AC_DEFINE_UNQUOTED(CACHEDIR, "$cachedir") +AC_SUBST(cachedir) + +AC_ARG_ENABLE(isdn, +[ --enable-isdn Enable ISDN support (may cause problems on + some systems; only for Linux)], + test $enableval = "yes" && AC_DEFINE(ISDN_SUPPORT)) + +AC_ARG_ENABLE(ipv4, +[ --disable-ipv4 Disable IPv4 networking support + (default=enabled)], + have_ipv4=$enableval) + +test $have_ipv4 = "yes" && AC_DEFINE(ENABLE_IPV4) + +AC_ARG_ENABLE(ipv6, +[ --enable-ipv6 Enable IPv6 networking support], +[ if test $enableval = "yes" ; then + AC_DEFINE(ENABLE_IPV6) + if test $have_ipv4 != "yes" ; then + ipv4_default=0 + fi + fi]) + +AC_ARG_ENABLE(ipv4-startup, +[ --disable-ipv4-startup Disable IPv4 on pdnsd startup by default + (default=enabled)], +[ if test $enableval = "yes" ; then + ipv4_default=1 + else + ipv4_default=0 + fi]) + +AC_ARG_ENABLE(ipv6-startup, +[ --enable-ipv6-startup Enable IPV6 on pdnsd startup by default + (default=IPv4)], +[ if test $enableval = "yes" ; then + ipv4_default=0 + else + ipv4_default=1 + fi]) + +AC_DEFINE_UNQUOTED(DEFAULT_IPV4, $ipv4_default) + +AC_ARG_ENABLE(udp-queries, +[ --disable-udp-queries Disable udp as query method.], + udp_queries=$enableval) + +AC_ARG_ENABLE(tcp-queries, +[ --disable-tcp-queries Disable tcp as query method.], + tcp_queries=$enableval) + +AC_ARG_WITH(query-method, +[ --with-query-method=qm Specify the query method (default=udponly; + others: tcponly, tcpudp, udptcp)], + query_m=$withval) +case $query_m in + udponly|UDPonly) + AC_DEFINE(M_PRESET, UDP_ONLY) + udp_queries=yes; + ;; + tcponly|TCPonly) + AC_DEFINE(M_PRESET, TCP_ONLY) + tcp_queries=yes; + ;; + tcpudp|TCPUDP) + AC_DEFINE(M_PRESET, TCP_UDP) + udp_queries=yes; + tcp_queries=yes; + ;; + udptcp|UDPTCP) + AC_DEFINE(M_PRESET, UDP_TCP) + udp_queries=yes; + tcp_queries=yes; + ;; + *) + AC_MSG_ERROR([--with-query-method must have udponly, tcponly, tcpudp or udptcp as parameter.]) + ;; +esac + +test $udp_queries != "yes" && AC_DEFINE(NO_UDP_QUERIES) +test $tcp_queries != "yes" && AC_DEFINE(NO_TCP_QUERIES) + +AC_ARG_ENABLE(tcp-server, +[ --disable-tcp-server Disable the TCP serving ability of pdnsd], + have_tcp_server=$enableval) + +test $have_tcp_server != "yes" && AC_DEFINE(NO_TCP_SERVER) + +AC_ARG_ENABLE(src-addr-disc, +[ --disable-src-addr-disc Disable the UDP source address discovery], + adisc=$enableval) + +AC_ARG_ENABLE(socket-locking, +[ --enable-socket-locking Enable the UDP socket locking], + slock=$enableval) + +test $slock = "yes" && AC_DEFINE(SOCKET_LOCKING) + +AC_ARG_ENABLE(poll, +[ --disable-poll Disable poll(2) and use select(2) + (default=enabled)], + test $enableval != "yes" && AC_DEFINE(NO_POLL)) + +AC_ARG_ENABLE(new-rrs, +[ --disable-new-rrs Disable new DNS RR types (obsolete, currently ignored)], + newrrs=$enableval) + +AC_ARG_ENABLE(strict-rfc2181, +[ --enable-strict-rfc2181 Enforce strict RFC 2181 compliance], + test $enableval = "yes" && AC_DEFINE(RFC2181_ME_HARDER)) + +AC_ARG_WITH(random-device, +[ --with-random-device=device Specify random device other than + /dev/random; default: C Library random() PRNG; + special value arc4random for BSD C Library + arc4random function (default on FreeBSD)], + randomdev=$withval) + +if test "$randomdev" = arc4random ; then + AC_DEFINE(R_ARC4RANDOM) +elif test "$randomdev" = random ; then + AC_DEFINE(R_RANDOM) +elif test "$randomdev" = default ; then + AC_DEFINE(R_DEFAULT) +else + AC_DEFINE_UNQUOTED(RANDOM_DEVICE, "$randomdev") +fi + +AC_ARG_ENABLE(underscores, +[ --enable-underscores Allow _ in domain names (obsolete, currently ignored)], + underscores=$enableval) + +AC_ARG_WITH(default-id, +[ --with-default-id=id Specify default uid/gid for pdnsd + (default=nobody)], + def_id=$withval) +AC_SUBST(def_id) + +AC_ARG_WITH(debug, +[ --with-debug=level Specify debugging level (0 means no debug support)], + AC_DEFINE_UNQUOTED(DEBUG, $withval)) + +AC_ARG_WITH(verbosity, +[ --with-verbosity=level Specify default message verbosity], + AC_DEFINE_UNQUOTED(VERBOSITY, $withval)) + +AC_ARG_WITH(hash-buckets, +[ --with-hash-buckets=num Number of hash buckets to use (default=1024). + The number actually used is the smallest power of two + greater or equal to the number specified here.], + powof2=1 + hashsz=0 + + while test $powof2 -lt "$withval" + do + powof2=`expr 2 '*' $powof2` + hashsz=`expr $hashsz '+' 1` + done + AC_DEFINE_UNQUOTED(HASH_SZ, $hashsz) +) + +AC_ARG_ENABLE(hash-debug, +[ --enable-hash-debug Debug hash tables (warning: massive output)], + test $enableval = "yes" && AC_DEFINE(DEBUG_HASH)) + +AC_ARG_ENABLE(rcsids, +[ --enable-rcsids Enable RCS IDs in executables (obsolete, currently ignored)], + have_rcsids=$enableval) + +AC_ARG_WITH(tcp-qtimeout, +[ --with-tcp-qtimeout=secs Specify default tcp query timeout (default=30)], + AC_DEFINE_UNQUOTED(TCP_TIMEOUT, $withval)) + +AC_ARG_ENABLE(tcp-subseq, +[ --enable-tcp-subseq Enable multiple dns querys using one + tcp connection], + test $enableval = "yes" && AC_DEFINE(TCP_SUBSEQ)) + +AC_ARG_WITH(par-queries, +[ --with-par-queries=num Specify default parallel query number (default=2)], + AC_DEFINE_UNQUOTED(PAR_QUERIES, $withval)) + +AC_ARG_WITH(max-nameserver-ips, +[ --with-max-nameserver-ips=num Specify maximum number of IP addresses used per nameserver obtained from NS records (default=3)], + AC_DEFINE_UNQUOTED(MAXNAMESERVIPS, $withval)) + +AC_ARG_ENABLE(specbuild, +[ --enable-specbuild Only used when building pdnsd from spec files], + specbuild=$enableval) + +AC_SUBST(specbuild) + +AC_ARG_WITH(thread-lib, +[ --with-thread-lib=lib Specify thread library, overriding automatic detection (for Linux only). + Possible values: LinuxThreads, + LinuxThreads2 (implements a fix for newer glibcs) + or NPTL (Native POSIX Thread Library)], + threadlib=$withval) + +AC_SUBST(threadlib) + +dnl Checks for programs. +AC_PROG_CC +AM_PROG_CC_STDC +AM_PROG_CC_C_O +AC_PROG_INSTALL + +dnl For dbm subsystem libraries +AC_PROG_RANLIB + +if test "$target" = "autodetect" ; then + AC_MSG_CHECKING([for autodetect build target]) + uname_sys=`uname` + if test $? -ne 0 ; then + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([uname failed or was not found in path]) + else + case "${uname_sys}" in + Linux) + AC_MSG_RESULT(Linux) + AC_DEFINE(TARGET, TARGET_LINUX) + target="Linux" + ;; + FreeBSD|NetBSD|OpenBSD|Darwin) + AC_MSG_RESULT("${uname_sys}") + AC_DEFINE(TARGET, TARGET_BSD) + target="BSD" + ;; + CYGWIN*) + AC_MSG_RESULT("${uname_sys}") + AC_DEFINE(TARGET, TARGET_CYGWIN) + target="cygwin" + ;; + *) + AC_MSG_RESULT([failed]) + AC_MSG_ERROR( +[Your system type could not be identified. Try setting it manually using +--with-target]) + ;; + esac + fi +fi + +#if test "$target" = BSD ; then +# uname_sys=`uname` +# if test "$uname_sys" = FreeBSD ; then +# AC_MSG_CHECKING([for FreeBSD version]) +# osrel=`sysctl -n kern.osreldate` +# if test $osrel -ge 500016 ; then +# AC_MSG_RESULT([5.0 (>= 500016)]) +# freebsd_pthread="5" +# else +# AC_MSG_RESULT([<=5.0 (< 500016)]) +# freebsd_pthread="4" +# fi +# fi +#fi + +if test "$adisc" = "default"; then + if test "$target" = "cygwin" ; then +# Don't do UDP source address discovery on Cygwin platform by default. + adisc="no" + else + adisc="yes" + fi +fi + +test "$adisc" = "yes" && AC_DEFINE(SRC_ADDR_DISC) + + +dnl Checks for libraries. +if test "$target" = "Linux"; then +AC_MSG_CHECKING([if we can compile and link with -pthread]) +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -pthread" +AC_LINK_IFELSE([ +#include + +void *thread_func(void *data) +{ + *((int *)data)=1; + return data; +} + +int main() +{ + pthread_t thread; + void *retval; + int val; + + if(pthread_create(&thread, NULL, thread_func, &val)) + return 1; + + if(pthread_join(thread,&retval)) + return 1; + + return (*((int *)retval)!=1); +} +], + gcc_pthread_flag="yes", gcc_pthread_flag="no") +CFLAGS="$old_CFLAGS" +AC_MSG_RESULT([$gcc_pthread_flag]) + + if test "$gcc_pthread_flag" = yes ; then + thread_CFLAGS="-pthread" + AC_SUBST(thread_CFLAGS) + else + AC_CHECK_LIB(pthread, pthread_create) + fi +fi +if test "$target" = "BSD" -a `uname` != Darwin ; then +# if test $freebsd_pthread = 4 ; then + thread_CFLAGS="-pthread" + AC_SUBST(thread_CFLAGS) +# else +# AC_CHECK_LIB(c_r, pthread_create, , +# AC_MSG_ERROR([You must have libc_r installed to build/run pdnsd!])) +# fi; +fi + +if test "$target" = "Linux" -a "$threadlib" = default; then +AC_MSG_CHECKING([if this is an NPTL-based system]) +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $thread_CFLAGS" +AC_RUN_IFELSE([ +#include +#include +#include +#include +#include +#include + +/* All this function does is return its PID (in a roundabout way). */ +void *thread_func(void *data) +{ + *((int *)data)=getpid(); + return data; +} + +int main() +{ + pthread_t thread; + void *retval; + int err,mainpid,thrdpid; + + err=pthread_create(&thread, NULL, thread_func, &thrdpid); + if(err) { + fprintf(stderr,"pthread_create failed: %s\n",strerror(err)); + return 1; + } + err=pthread_join(thread,&retval); + if(err) { + fprintf(stderr,"pthread_join failed: %s\n",strerror(err)); + return 1; + } + mainpid=getpid(); + /* In LinuxThreads implementations, the pids of the threads will usually differ + in a non Posix-compliant way. */ + fprintf(stderr,"main pid=%d, thread pid=%d\n",mainpid,*((int *)retval)); + return (*((int *)retval)!=mainpid); +} +], +[ + AC_MSG_RESULT([yes]) + threadlib=nptl +], +[ + AC_MSG_RESULT([no]) + threadlib=linuxthreads +], +[ + AC_MSG_RESULT([couldn't run test program]) + threadlib=linuxthreads +]) +CFLAGS="$old_CFLAGS" +fi + +if test "$threadlib" = nptl -o "$threadlib" = NPTL; then + AC_DEFINE(THREADLIB_NPTL) +elif test "$threadlib" = linuxthreads2 -o "$threadlib" = LinuxThreads2 -o "$threadlib" = lt2; then + AC_DEFINE(THREADLIB_LINUXTHREADS2) +fi + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h sys/time.h syslog.h unistd.h) +AC_CHECK_HEADERS(sys/types.h sys/socket.h net/if.h netinet/in.h sys/poll.h,,, +[#include +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM +AC_CHECK_TYPES(socklen_t,, AC_DEFINE(socklen_t,int),[#include +#include +#include +#include ]) +AC_CHECK_TYPES([struct in6_addr, struct in_pktinfo, struct ifreq],,,[#include +#include +#include +#include ]) + +AC_MSG_CHECKING([for CPP C99 Variadic macro support]) +AC_COMPILE_IFELSE([ +#define a(...) junk(0,__VA_ARGS__) +extern void junk(int i,...); +int main() +{ + a(0); + a("a"); + a(0, "a", 1); + return 0; +} +], + cpp_c99_variadic="yes", cpp_c99_variadic="no") +AC_MSG_RESULT([$cpp_c99_variadic]) +if test $cpp_c99_variadic = yes; then + AC_DEFINE(CPP_C99_VARIADIC_MACROS) +else + if test "$GCC" != yes; then + AC_MSG_ERROR([Compiler must support C99 or gcc variadic macros]) + fi; +fi + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MEMCMP +AC_TYPE_SIGNAL +AC_FUNC_VPRINTF +AC_SEARCH_LIBS(nanosleep, rt) +AC_SEARCH_LIBS(socket, socket,,,-lnsl) +AC_SEARCH_LIBS(inet_aton, resolv) +AC_CHECK_FUNCS(nanosleep gettimeofday mkfifo select socket strerror uname snprintf vsnprintf, true, + AC_MSG_ERROR([One of the functions required for pdnsd were not found.])) +AC_CHECK_FUNCS(poll, true, AC_DEFINE(NO_POLL)) +AC_CHECK_FUNCS(strdup strndup stpcpy stpncpy strlcpy mempcpy getline asprintf vasprintf getpwnam_r inet_ntop inet_pton) + +AC_OUTPUT([ +pdnsd.spec +Makefile +file-list.base +contrib/Makefile +doc/Makefile +doc/pdnsd.8 +doc/pdnsd.conf.5 +doc/pdnsd.conf +src/Makefile +src/pdnsd-ctl/Makefile +src/rc/Makefile +src/rc/RedHat/Makefile +src/rc/RedHat/pdnsd +src/rc/SuSE/Makefile +src/rc/SuSE/pdnsd +src/rc/Debian/Makefile +src/rc/Debian/pdnsd +src/rc/Slackware/Makefile +src/rc/Slackware/rc.pdnsd +src/rc/ArchLinux/Makefile +src/rc/ArchLinux/pdnsd +src/test/Makefile +PKGBUILD +]) diff --git a/jni/pdnsd/contrib/Makefile.am b/jni/pdnsd/contrib/Makefile.am new file mode 100644 index 00000000..5bdec20a --- /dev/null +++ b/jni/pdnsd/contrib/Makefile.am @@ -0,0 +1,2 @@ + +EXTRA_DIST = pdnsd_dhcp.pl dhcp2pdnsd change_pdnsd_server_ip.pl README diff --git a/jni/pdnsd/contrib/Makefile.in b/jni/pdnsd/contrib/Makefile.in new file mode 100644 index 00000000..a400dfe9 --- /dev/null +++ b/jni/pdnsd/contrib/Makefile.in @@ -0,0 +1,323 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = contrib +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = pdnsd_dhcp.pl dhcp2pdnsd change_pdnsd_server_ip.pl README +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) --gnu contrib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu contrib/Makefile +.PRECIOUS: 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): +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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 + +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 distclean \ + distclean-generic 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 pdf pdf-am ps ps-am uninstall uninstall-am + + +# 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/jni/pdnsd/contrib/README b/jni/pdnsd/contrib/README new file mode 100644 index 00000000..19e4f44d --- /dev/null +++ b/jni/pdnsd/contrib/README @@ -0,0 +1,30 @@ +Last revised: 27 July 2003 by Paul Rombouts + +This directory contains user-contributed scripts for use with pdnsd. +So far there are: + +pdnsd_dhcp.pl, save_ram.pl + A perl script contributed by Marko Stolle (derived from a script by + Mike Stella) to watch a ISC DHCPD leases file and add local records for + the hosts listed there. This makes pdnsd useable in a DHCP setup. + Please look into the script for usage instructions (you will probably + also need to customize some settings there). + For details about save_ram.pl, please look into pdnsd_dhcp.pl + +dhcp2pdnsd + A rc script for pdnsd, also by Marko Stolle. You might need to change + it slightly to make it run with your distro. + +change_pdnsd_server_ip.pl + A perl script contributed by Paul Rombouts for automatically updating + the configuration file if the DNS server configuration has changed. + For instance, you could place the following line in the script + /sbin/ifup-local + + /usr/local/sbin/change_pdnsd_server_ip.pl isplabel "$DNS" /etc/pdnsd.conf + + where $DNS contains the IP addresses (in comma separated format) of the + DNS servers obtained by DHCP negotiation. The perl script only + overwrites /etc/pdnsd.conf if the DNS configuration has actually + changed, in which case the previous configuration file is saved as + /etc/pdnsd.conf.save diff --git a/jni/pdnsd/contrib/change_pdnsd_server_ip.pl b/jni/pdnsd/contrib/change_pdnsd_server_ip.pl new file mode 100644 index 00000000..1eafca0d --- /dev/null +++ b/jni/pdnsd/contrib/change_pdnsd_server_ip.pl @@ -0,0 +1,124 @@ +#!/usr/bin/perl -w +# +# A Perl script to change the ip addresses of dns servers +# in the pdnsd configuration file. +# +# Written by Paul A. Rombouts +# +# This file Copyright 2002, 2004 Paul A. Rombouts +# It may be distributed under the GNU Public License, version 2, or +# any higher version. See section COPYING of the GNU Public license +# for conditions under which this file may be redistributed. +# + +use strict; + +unless(@ARGV) {die "Error: no label specified.\n"} +my $label=shift; +unless(@ARGV) {die "Error: no DNS addresses specified.\n"} +my $dns_str=shift; +my $pdnsd_conf='/etc/pdnsd.conf'; +if(@ARGV) { + $pdnsd_conf=shift; + if(@ARGV) {warn "Warning: spurious arguments ignored: @ARGV\n"} +} + +#unless($label =~ /^\".*\"$/) {$label="\"$label\""} +#unless($dns_str =~ /^\".*\"$/) {$dns_str =~ s/^[\s,]*/\"/; $dns_str =~ s/[\s,]*$/\"/} +#unless($dns_str =~ /\"\s*\,\s*\"/) {$dns_str =~ s/[\s,]+/","/g} + +my @lines=(); +my $found_section=0; +my $changed=0; +my $ip_patt = qr/^((?:[^#]*?(?:\{|;))*?)(\s*ip\s*=\s*)("?[\w.:]+"?(?:\s*,\s*"?[\w.:]+"?)*)\s*;/; + +open(CONFFILE,$pdnsd_conf) or die "Can't open $pdnsd_conf: $!\n"; + +while() { + if(/^\s*server\s*\{/) { + my $sect_beg=$#lines+1; + my $sect_end; + my $found_label=0; + LOOP: { + do { + push @lines,$_; + if(/^(?:.*(?:\{|;))?\s*label\s*=\s*"?\Q$label\E"?\s*;/) { + if($found_label++) { + warn "Server section with multiple labels found.\n"; + close(CONFFILE); + exit 2; + } + } + if(/\}\s*$/) { + $sect_end=$#lines; + last LOOP; + } + } while(); + } + unless(defined($sect_end)) { + warn "Server section without proper ending found.\n"; + close(CONFFILE); + exit 2; + } + if(!$found_label) {next} + if(!($found_section++)) { + my $found_ip=0; + for(my $i=$sect_beg; $i<=$sect_end;++$i) { + if($lines[$i] =~ $ip_patt) { + my $matched=''; my $rest; + do { + $rest=$'; + if(!($found_ip++)) { + if($3 eq $dns_str) { + $matched.=$&; + } + else { + $matched.="$1$2$dns_str;"; + $changed=1; + } + } + else { + $matched.=$1; + $changed=1; + } + } while($rest =~ $ip_patt); + $lines[$i] = $matched.$rest; + } + } + if(!$found_ip) { + unless($lines[$sect_end] =~ s/\}\s*$/ ip=$dns_str;\n$&/) { + warn "Can't add ip specification to server section labeled $label.\n"; + close(CONFFILE); + exit 2; + } + $changed=1; + } + } + else { + splice @lines,$sect_beg; + $changed=1; + } + } + else {push @lines,$_} +} + +close(CONFFILE) or die "Can't close $pdnsd_conf: $!\n"; + +if(!$found_section) { + warn "No server sections labeled $label found.\n"; + exit 2; +} +elsif(!$changed) { + exit 0; +} + +rename($pdnsd_conf,"$pdnsd_conf.save") or die "Can't rename $pdnsd_conf: $!\n"; + +unless((open(CONFFILE,">$pdnsd_conf") or (warn("Can't open $pdnsd_conf for writing: $!\n"),0)) and + (print CONFFILE (@lines) or (warn("Can't write to $pdnsd_conf: $!\n"),0)) and + (close(CONFFILE) or (warn("Can't close $pdnsd_conf after writing: $!\n"),0))) { + rename("$pdnsd_conf.save",$pdnsd_conf) or die "Can't rename $pdnsd_conf.save: $!\n"; + exit 3; +} + +exit 1; diff --git a/jni/pdnsd/contrib/dhcp2pdnsd b/jni/pdnsd/contrib/dhcp2pdnsd new file mode 100644 index 00000000..73b631cc --- /dev/null +++ b/jni/pdnsd/contrib/dhcp2pdnsd @@ -0,0 +1,45 @@ +#! /bin/sh +# +# dhcp2pdnsd Start/Stop DHCP to DNS update script +# +# chkconfig: 345 96 99 +# description: DHCP to DNS update script +# processname: dhcp2pdnsd.pl +# +# $Id: dhcp2pdnsd,v 1.1 2001/03/25 20:01:34 tmm Exp $ + +where="/usr/local/bin/" +name="pdnsd_dhcp.pl" + +# Source function library. +. /etc/rc.d/init.d/functions + +# Get config. +. /etc/sysconfig/network + +# See how we were called. +case "$1" in + start) + $where$name > /dev/null 2> /dev/null & + action "Starting DHCP to DNS update script: " /bin/true + ;; + stop) + p=`ps h -C $name | awk '{print $1}'` + [ $p -gt 0 ] 2> /dev/null && kill $p && action "Stopping DHCP to DNS update script: " /bin/true + [ $p -gt 0 ] 2> /dev/null || action "Stopping DHCP to DNS update script: " /bin/false + ;; + status) + p=`ps h -C $name | awk '{print $1}'` + [ $p -gt 0 ] 2> /dev/null && echo 'running as '$p + [ $p -gt 0 ] 2> /dev/null || echo 'not running' + ;; + restart|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: dhcp2pdnsd {start|stop|status|restart|reload}" + exit 1 +esac + +exit 0 diff --git a/jni/pdnsd/contrib/pdnsd_dhcp.pl b/jni/pdnsd/contrib/pdnsd_dhcp.pl new file mode 100644 index 00000000..9cf0c879 --- /dev/null +++ b/jni/pdnsd/contrib/pdnsd_dhcp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/perl +# $Id: pdnsd_dhcp.pl,v 1.2 2001/03/25 20:01:34 tmm Exp $ +########################################################################## +# +# Filename: pdnsd_dhcp.pl +# Description: Dynamic DNS-DHCP update script for pdnsd +# Author: Mike Stella +# Modified by: Marko Stolle +# Created: November 19, 2001 +# Last Updated: February 28, 2001 +# Email: fwd2m@gmx.de +# +########################################################################### +# +# This code is Copyright (c) 1998-2001 by Mike Stella and Marko Stolle +# +# NO WARRANTY is given for this program. If it doesn't +# work on your system, sorry. If it eats your hard drive, +# again, sorry. It works fine on mine. Good luck! +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +########################################################################### +# +# This script reads a dhcpd.leases file and dynamically updates pdnsd with +# hostname and ip information. +# +# It assumes that your DHCP server recieves hostnames from the +# clients, and that your clients offer their hostnames to the server. +# Some versions of Linux DHCP clients don't do that. I use ISC's +# DHCPD, found at http://www.isc.org - though others may work just +# fine. +# +# This version of the script updates the pdnsd database. The status +# control socket of pdnsd has to be enabled (psnsd -d -s). +# +########################################################################### +# +# 02/20/2001 - first working version +# 02/21/2001 - security patches by Thomas Moestl +# 02/22/2001 - re-read dhcpd.leases if ttl has expireds since last update +# 02/24/2001 - try to get domainname if not specified +# 02/28/2001 - randomized temporary filename +# added possibility to save some RAM (read below) +# +########################################################################### + + +# You may save some memory if you use absolute values with sysopen +# in sub update_dns and don't use tmpnam().. +# Just switch the '#' in front of the 'until sysopen' in the sub +# update_dns, check the necessary modes on your system using save_ram.pl +# and add a '#' in front of the following three lines. +# Not using the tmpnam() function may open a security breach on systems +# with not absolute trustworthy local users (Risk: a user may write a +# script which creates files with the same names as this script and block +# it that way. Unlikely because the filenames are now even without tmpnam() +# randomized and an attacker has to create a very large number of files.) + +use Fcntl; +use strict; +use POSIX qw(tmpnam); + +$|=1; + +########################################################################### +### Globals - you can change these as needed + +# Domain name +# if not changed script will try to get it from the system +my $domain_name = "domain"; + +# DHCPD lease file +my $lease_file = "/var/lib/dhcp/dhcpd.leases"; + +# path to pdnsd-ctl +my $pdnsd_ctl = "/usr/local/sbin/pdnsd-ctl"; + +# owning name server for the newly added records +my $nameserver = "localhost."; + +# TTL (Time To Live) for the new records +my $ttl = "86400"; + +# number of seconds to check the lease file for updates +my $update_freq = 30; + +my $debug = 0; + +########################################################################### +### Don't mess with anything below unless you REALLY need to modify the +### code. And if you do, please let me know, I'm always interested in +### in improving this program. + +# Make a pid file +`echo $$ > /var/run/pdnsd_update.pid`; + +my $logstr; +my $modtime = 0; +my $temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP}; + +use vars qw (%db); + +my $version = "1.03"; + + +########################################################################### +# Main Loop + + # try to find domainname if necessary + if ($domain_name eq "domain") { + $domain_name = `dnsdomainname`; + } + else { + $domain_name = "$domain_name\n"; + } + +while (1) { + + # check the file's last updated time, if it's been changed, update + # the DNS and save the time. Update DNS even if there a no changes on + # the leases file if ttl since last DNS update has expired. + # This will ALWAYS run once - on startup, since $modtime starts at zero. + + + my @stats = stat ($lease_file); + + + if (($stats[9] > $modtime) or (time >= $modtime+$ttl)){ + + # clear the old hash + undef %db; + + printf STDERR "updating DNS with dhcpd.leases\n"; + $modtime = time; + &read_lease_file; + &update_dns; + } + + # wait till next check time + sleep $update_freq; + +} # end main +########################################################################### + + +### write out the import file +sub update_dns { + my ($ip, $hostname, $fname); + + do { $fname = tmpnam() } + until sysopen(DNSFILE, $fname, O_WRONLY|O_CREAT|O_EXCL, 0600); +# do { $fname = "$temp_dir/d2d".int(rand(time())) } +# until sysopen(DNSFILE, $fname, 1|64|128, 0600); + + while (($hostname,$ip) = each (%db)) { + print DNSFILE "$ip $hostname.$domain_name"; + } + close DNSFILE; + + system ("$pdnsd_ctl source $fname $nameserver $ttl"); + unlink($fname); +} + + +### reads the lease file & makes a hash of what's in there. +sub read_lease_file { + + unless (open(LEASEFILE,$lease_file)) { + #`logger -t dns_update.pl error opening dhcpd lease file`; + print STDERR "Can't open lease file\n"; + return; + } + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + my $curdate = sprintf "%02d%02d%02d%02d%02d%20d%20d", + ($year+1900),($mon+1),$mday,$hour,$min,$sec; + + ## Loop here, reading from LEASEFILE + while () { + my ($ip, $hostname, $mac, $enddate,$endtime); + + if (/^\s*lease/i) { + + # find ip address + $_ =~ /^\s*lease\s+(\S+)/; + $ip = $1; + + # do the rest of the block - we're interested in hostname, + # mac address, and the lease time + while ($_ !~ /^}/) { + $_ = ; + # find hostname + if ($_ =~ /^\s*client/i) { + #chomp $_; + #chop $_; + $_ =~ /\"(.*)\"/; + $hostname = $1; + + # change spaces to dash, remove dots - microsoft + # really needs to not do this crap + $hostname =~ s/\s+/-/g; + $hostname =~ s/\.//g; + } + # get the lease end date + elsif ($_ =~ /^\s*ends/i) { + $_ =~ m/^\s*ends\s+\d\s+([^;]+);/; + $enddate = $1; + $enddate =~ s|[/: ]||g; + } + } + # lowercase it - stupid dhcp clients + $hostname =~ tr/[A-Z]/[a-z]/; + + ($debug < 1 ) || print STDERR "$hostname $ip $enddate $curdate\n"; + + # Store hostname/ip in hash - this way we can do easy dupe checking + if (($hostname ne "") and ($enddate > $curdate)) { + $db{$hostname} = $ip; + } + } + } + close LEASEFILE; +} + +### left around for testing +sub print_db { + my ($key,$value); + + while (($key,$value) = each (%db)) { + print "$key - $value\n"; + } +} + diff --git a/jni/pdnsd/depcomp b/jni/pdnsd/depcomp new file mode 100644 index 00000000..04701da5 --- /dev/null +++ b/jni/pdnsd/depcomp @@ -0,0 +1,530 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-07-09.11 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# 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 outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +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" + +# 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 + +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. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## 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). +## - 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 -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## 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. + tr ' ' ' +' < "$tmpdepfile" | +## 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. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -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 -eq 0; then : + else + 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 ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +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. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + 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" + ;; + +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. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in 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.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#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 $1 != '--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:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + 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 $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + 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. + -*|$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" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + 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 $1 != '--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, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +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-end: "$" +# End: diff --git a/jni/pdnsd/doc/Makefile.am b/jni/pdnsd/doc/Makefile.am new file mode 100644 index 00000000..b3e21984 --- /dev/null +++ b/jni/pdnsd/doc/Makefile.am @@ -0,0 +1,28 @@ + +man_MANS = pdnsd.8 pdnsd-ctl.8 pdnsd.conf.5 + +# Note: pdnsd-ctl.8, pdnsd.conf.5.in, dl.html and the txt docs are handled by dist-hook rule. +EXTRA_DIST = pdnsd.conf.in pdnsd.8.in \ + html/dl.html.in html/doc.html html/faq.html html/index.html \ + doc_makefile html/doc_makefile txt/doc_makefile \ + html2confman.pl html/htmlsubst.pl + +# XXX: Do not insist to set the config file owner to root to avoid breaking RPM +# builds +install-data-hook: + $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" + if test `whoami` = "root"; then \ + $(INSTALL) -o 0 -g 0 -m 644 pdnsd.conf "$(DESTDIR)$(sysconfdir)/pdnsd.conf.sample" ; \ + else \ + $(INSTALL) -m 644 pdnsd.conf "$(DESTDIR)$(sysconfdir)/pdnsd.conf.sample" ; \ + fi + +dist-hook: doc_makefile + @$(MAKE) -f doc_makefile doc + cp -p --parents pdnsd-ctl.8 pdnsd.conf.5.in \ + html/dl.html txt/faq.txt txt/intro.txt txt/manual.txt \ + $(distdir) + +distclean-local: doc_makefile + @$(MAKE) -f doc_makefile clean + diff --git a/jni/pdnsd/doc/Makefile.in b/jni/pdnsd/doc/Makefile.in new file mode 100644 index 00000000..7f07fe69 --- /dev/null +++ b/jni/pdnsd/doc/Makefile.in @@ -0,0 +1,483 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/pdnsd.8.in $(srcdir)/pdnsd.conf.5.in \ + $(srcdir)/pdnsd.conf.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdnsd.8 pdnsd.conf.5 pdnsd.conf +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +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' +man5dir = $(mandir)/man5 +am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man_MANS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +man_MANS = pdnsd.8 pdnsd-ctl.8 pdnsd.conf.5 + +# Note: pdnsd-ctl.8, pdnsd.conf.5.in, dl.html and the txt docs are handled by dist-hook rule. +EXTRA_DIST = pdnsd.conf.in pdnsd.8.in \ + html/dl.html.in html/doc.html html/faq.html html/index.html \ + doc_makefile html/doc_makefile txt/doc_makefile \ + html2confman.pl html/htmlsubst.pl + +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) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: 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): +pdnsd.8: $(top_builddir)/config.status $(srcdir)/pdnsd.8.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +pdnsd.conf.5: $(top_builddir)/config.status $(srcdir)/pdnsd.conf.5.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +pdnsd.conf: $(top_builddir)/config.status $(srcdir)/pdnsd.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-man5: $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" + @list=''; test -n "$(man5dir)" || exit 0; \ + { 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'; \ + } | 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,.,'`; \ + test -z "$$files" || { \ + echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man5dir)" && rm -f $$files; } +install-man8: $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" + @list=''; test -n "$(man8dir)" || exit 0; \ + { for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.8[a-z]*$$/p'; \ + } | 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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.8[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + test -z "$$files" || { \ + echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically \`make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @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 + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; 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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +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-man5 install-man8 + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man5 uninstall-man8 + +.MAKE: install-am install-data-am install-strip + +.PHONY: all all-am check check-am clean clean-generic dist-hook \ + distclean distclean-generic distclean-local distdir dvi dvi-am \ + html html-am info info-am install install-am install-data \ + install-data-am install-data-hook install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-man5 \ + install-man8 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-man uninstall-man5 uninstall-man8 + + +# XXX: Do not insist to set the config file owner to root to avoid breaking RPM +# builds +install-data-hook: + $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)" + if test `whoami` = "root"; then \ + $(INSTALL) -o 0 -g 0 -m 644 pdnsd.conf "$(DESTDIR)$(sysconfdir)/pdnsd.conf.sample" ; \ + else \ + $(INSTALL) -m 644 pdnsd.conf "$(DESTDIR)$(sysconfdir)/pdnsd.conf.sample" ; \ + fi + +dist-hook: doc_makefile + @$(MAKE) -f doc_makefile doc + cp -p --parents pdnsd-ctl.8 pdnsd.conf.5.in \ + html/dl.html txt/faq.txt txt/intro.txt txt/manual.txt \ + $(distdir) + +distclean-local: doc_makefile + @$(MAKE) -f doc_makefile clean + +# 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/jni/pdnsd/doc/doc_makefile b/jni/pdnsd/doc/doc_makefile new file mode 100644 index 00000000..f5e8f86d --- /dev/null +++ b/jni/pdnsd/doc/doc_makefile @@ -0,0 +1,38 @@ +# This file was written by Paul Rombouts. +# Because pdnsd currently has a very idiosyncratic method of building documentation +# I prefer to keep the actual build rules outside of the Makefiles an ordinary user +# would use to compile pdnsd and therefore I have put them into separate 'doc_makefile's. +# +# To rebuild pdnsd docs after you have modified something that other files depend on, +# run 'make -f doc_makefile doc' in the doc/ directory. +# This makefile is also invoked when you build a pdnsd distribution tarball +# using 'make dist' in the toplevel pdnsd source directory. +# +# If anyone thinks there is a much more elegant method for building the pdnsd docs +# using a conventional autoconf/automake process, please let me know. + +versionfile = ../version + +doc: pdnsd-ctl.8 pdnsd.conf.5.in html txt +.PHONY: pdnsd-ctl.8 doc html txt clean + +pdnsd-ctl.8: + @pver=`cat $(versionfile)` && \ + mver=`perl -e 'while(<>) {if(/^\s*\.TH(?:\s+(?:"[^"]*"|[^"\s]+)){3}\s+"pdnsd\s+([^"]*)"/) {print "$$1\n";exit 0}} \ + die "Cannot find version in $$ARGV\n"' $@` && { \ + test "$$mver" = "$$pver" || { \ + perl -p -i.makesave -e 's/^(\s*\.TH(?:\s+(?:"[^"]*"|[^"\s]+)){3}\s+"pdnsd\s+)[^"]*(")/$${1}'"$$pver"'$${2}/' $@ && \ + echo "Updated version in $@: $$mver -> $$pver"; \ + }; \ + } + +pdnsd.conf.5.in: html/doc.html html2confman.pl + perl html2confman.pl $< > $@ + +html txt: + @cd $@ && $(MAKE) -f doc_makefile + +clean: + @rm -fv pdnsd.conf.5.in + @cd html && $(MAKE) -f doc_makefile clean + @cd txt && $(MAKE) -f doc_makefile clean diff --git a/jni/pdnsd/doc/html/dl.html b/jni/pdnsd/doc/html/dl.html new file mode 100644 index 00000000..3f9c6140 --- /dev/null +++ b/jni/pdnsd/doc/html/dl.html @@ -0,0 +1,96 @@ + + + + pdnsd Download Page + + + + + + + + + + + + + +
+ pdnsd Homepage + + pdnsd FAQ + + Documentation + + GNU GPL (pdnsd's License) + + Download Section +
+ +

pdnsd Download Page

+ +

The original author of pdnsd is Thomas Moestl, + but since 2003, he no longer maintains pdnsd. + However, Paul A. Rombouts has extensively revised the code and maintains + a version with many fixes and improvements at + http://members.home.nl/p.a.rombouts/pdnsd.html.
+ He has pre-patched tarballs and RPM packages available for download at this site.
+

+

+ If you are interested in the very latest code or if you want to participate in + pdnsd development, checkout the pdnsd git repository + at gitorious.org. +

+ + The most recent tarball is pdnsd-1.2.9b-par.tar.gz + (GPG signature).
+ The most recent RPM packages are: + + + + + + + + + + + + + + + + + + + + + +
Package NameSizeDescription
pdnsd-1.2.9b-par.src.rpm514kBSource RPM (binary packages can also be built directly from the tarball). +
pdnsd-1.2.9b-par_sl6.i686.rpm???i686 binary built on a Scientific Linux 6.2 system. +
pdnsd-1.2.9b-par_sl6.x86_64.rpm282kBx86_64 binary built on a Scientific Linux 6.2 system. +
+ If you want to check the signatures on these packages you will need a copy of my GPG key + which you can get here + or from a public key server. +

+ There are also Debian, + Ubuntu, + Gentoo, + Mandriva + and FreeBSD + packages, but these may not include the latest version.
+ If you are looking for other versions released by Paul Rombouts, visit this + download directory. +

+
+
+

+ Last revised: 24 Apr 2012 by Paul A. Rombouts +

+ + diff --git a/jni/pdnsd/doc/html/dl.html.in b/jni/pdnsd/doc/html/dl.html.in new file mode 100644 index 00000000..dffe2b02 --- /dev/null +++ b/jni/pdnsd/doc/html/dl.html.in @@ -0,0 +1,96 @@ + + + + pdnsd Download Page + + + + + + + + + + + + + +
+ pdnsd Homepage + + pdnsd FAQ + + Documentation + + GNU GPL (pdnsd's License) + + Download Section +
+ +

pdnsd Download Page

+ +

The original author of pdnsd is Thomas Moestl, + but since 2003, he no longer maintains pdnsd. + However, Paul A. Rombouts has extensively revised the code and maintains + a version with many fixes and improvements at + http://members.home.nl/p.a.rombouts/pdnsd.html.
+ He has pre-patched tarballs and RPM packages available for download at this site.
+

+

+ If you are interested in the very latest code or if you want to participate in + pdnsd development, checkout the pdnsd git repository + at gitorious.org. +

+ + The most recent tarball is pdnsd-$version.tar.gz + (GPG signature).
+ The most recent RPM packages are: + + + + + + + + + + + + + + + + + + + + + +
Package NameSizeDescription
pdnsd-$version.src.rpm$sizeof("$HOME/rpmbuild/SRPMS/pdnsd-$version.src.rpm")Source RPM (binary packages can also be built directly from the tarball). +
pdnsd-${version}${extver}.${arch}.rpm$sizeof("$HOME/rpmbuild/RPMS/pdnsd-${version}${extver}.${arch}.rpm")${arch} binary built on a $system. +
pdnsd-${version}${extver}.${arch2}.rpm$sizeof("$HOME/rpmbuild/RPMS/pdnsd-${version}${extver}.${arch2}.rpm")${arch2} binary built on a $system. +
+ If you want to check the signatures on these packages you will need a copy of my GPG key + which you can get here + or from a public key server. +

+ There are also Debian, + Ubuntu, + Gentoo, + Mandriva + and FreeBSD + packages, but these may not include the latest version.
+ If you are looking for other versions released by Paul Rombouts, visit this + download directory. +

+
+
+

+ Last revised: $date by Paul A. Rombouts +

+ + diff --git a/jni/pdnsd/doc/html/doc.html b/jni/pdnsd/doc/html/doc.html new file mode 100644 index 00000000..95828c5c --- /dev/null +++ b/jni/pdnsd/doc/html/doc.html @@ -0,0 +1,2630 @@ + + + + pdnsd Documentation + + + + + + + + + + + + + + +
+ pdnsd Homepage + + pdnsd FAQ + + Documentation + + GNU GPL (pdnsd's License) + + Download Section +
+ +

pdnsd Documentation

+ This is the "official" pdnsd documentation and reference written by + Thomas Moestl with revisions by + Paul A. Rombouts.
+ This manual is a part of the pdnsd package, and may be distributed in + original or modified form under terms of the GNU General Public + License, as published by the Free Software Foundation; either version + 3, or (at your option) any later version.
+ You can find a copy of the GNU GPL in the file COPYING in the source or documentation directory.
+ This manual is up-to-date for version 1.2.9b. For older documentation, please refer to the doc + directory of the respective pdnsd package.
+ If you want a quicker introduction to pdnsd, you can try some of the + HOWTOs available on the web. + For Apple Mac users, Brian Wells has published a good HOWTO at + http://web.mac.com/brianwells/main/pdnsd.html. + + +

0. Installation

+

0.1 Installing binary RPM's

+ To install a binary RPM, just do
+

rpm -i pdnsd-<version>.rpm

+ This should install pretty much everything automatically. The only thing left + for you to do is adapt your configuration file (stored in /etc/pdnsd.conf) + according to your needs (see below). + In the Red Hat and SuSE RPMs, a start script is also installed; read the section + 0.4, Start at Boot Time about that. + +
+

0.2 Building RPM's

+ It is possible to build a binary RPM from a source package using the command
+

rpmbuild --rebuild pdnsd-<version>.src.rpm

+ or alternatively from a tarball using the command
+

rpmbuild -tb pdnsd-<version>.tar.gz

+ You can do this as root, but it is safer to build a binary package first as a normal user, + and then, when all has gone well, install the resulting binary package as root as in the previous section. + How to build an RPM package without being root is described at + + http://www.ibm.com/developerworks/linux/library/l-rpm1/.

+ Several pdnsd-specific options are available when building RPM packages: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ --with isdn + + Has the same effect as --enable-isdn (see below). +
+ --without poll + + Has the same effect as --disable-poll (see below). +
+ --without nptl + + Has the same effect as --with-thread-lib=linuxthreads (see below). +
+ --with ipv6 + + Has the same effect as --enable-ipv6 (see below). +
+ --without tcpqueries + + Has the same effect as --disable-tcp-queries (see below). +
+ --without debug + + Has the same effect as --with-debug=0 (see below). +
+ --define "distro <distro>" + + Has the same effect as --with-distribution=<distro> (see below). +
+ --define "run_as_user <user>" + + Has the same effect as --with-default-id=<user> (see below).
+ For RPMs the default <user> is "pdnsd". +
+ --define "run_as_uid <uid>" + + If the user defined by the previous option does not exist when the RPM is installed, + the pre-install script will try to create a new user with numerical id <uid>. + The default is to let the system choose the numerical id at install time. +
+ --define "cachedir <dir>" + + Has the same effect as --with-cachedir=<dir> (see below). +
+ You can also configure which compiler flags will be used by setting the environment variable + CFLAGS. + Using a bash shell, you can do that on the command line like this: +  CFLAGS="-O1 -Wall" rpmbuild ...
+ This is useful if you prefer a different level of optimization, for instance. + +
+

0.3 Installing from pure sources (tar archives or git repositories)

+

0.3.1 Setting up the source code tree

+ Source code is available in the form of snapshots (tarballs) or a git repository + with the very latest development code and a (nearly) complete history of all the revisions. + Cloning a git repository is useful if you need a recent fix or feature + that is not yet contained in a main release or you want to participate in pdnsd development. + Otherwise you will probably find the tarballs more convenient because they are much more compact. +
0.3.1.1 Unpacking a tar archive
+ The pdsnsd snapshot releases come in the form of a gzip'ed tar archive. + To decompress it (using a modern tar) do
+

tar -xzf pdnsd-<version>.tar.gz

+ If your tar doesn't do this, use:
+

gzip -dc pdnsd-<version>.tar.gz | tar -xf -

+
0.3.1.2 Cloning a git repository
+ To clone a git repository you need to install, if not already installed, + the git version control system, which is available as a package in most modern Linux distributions. + Then run the command:
+

git clone git://gitorious.org/pdnsd/pdnsd.git pdnsd

+ In rare cases, if you are behind some kind of firewall, the special git protocol can't be used + and you will need to fall back to the http protocol. + See the gitorious.org website or git documentation for more information. + +

0.3.2 Configuring the source

+ Change into the pdnsd source directory and run configure. It takes the following command line + options (if you do not specify an option, defaults will be used):
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ --prefix=dir + + Specify the prefix directory. The pdnsd files are installed in subdirectories + of the prefix, the pdnsd and pdnsd-ctl executables are for example installed + in the sbin subdirectory of the prefix. The default for this is /usr/local; + you might want to set this to /usr (using --prefix=/usr). +
+ --sysconfdir=dir + + Specify the config directory. pdnsd expects its pdnsd.conf file to reside + there if the -c option is not given at startup. + The default for this is the etc subdirectory of your prefix, e.g. /usr/local/etc + if you did not specify a prefix. To set this e.g. to /etc, use --sysconfdir=/etc. +
+ --with-distribution=distro + + Specify target distribution (default=Generic; others: RedHat, SuSE, Debian)
+ See below for the effect of these settings. +
+ --with-target=platform + + Change compilation target platform (default: autodetect; others: Linux, BSD, Cygwin).
+ autodetect will attempt to detect whether you are using Linux, *BSD or Cygwin and + should normally be sufficient. If this does not work, try specifying + your system manually (for the Darwin platform (Apple Mac OS X) specify BSD here). +
+ --with-cachedir=dir + + Default directory for pdnsd cache (default=/var/cache/pdnsd)
+ This setting can be changed via config file settings when pdnsd has been built. +
+ --with-hash-buckets=num + + Number of hash buckets to use (default=1024). The default should be + sufficient for most purposes, but if you want to store a large number of names + in the cache, cache lookups may be faster if the number of hash buckets + is comparable to the number of names stored in the cache. + The number actually used is the smallest power of two + greater or equal to the number specified here. +
+ --enable-isdn + + Enable ISDN support
+ This option will work only on Linux and may cause problems with 2.0.x or + old 2.2.x kernels. You will need it for a proper if uptest + under Linux for ISDN ppp devices. +
+ --disable-ipv4 + + Disable IPv4 networking support (default=enabled) +
+ --enable-ipv6 + + Enable IPv6 networking support.
+ If your OS does support IPv6 properly, you should be able to serve also + IPv4 queries using this. Normally, this is disabled and you won't need + it. +
+ --disable-ipv4-startup + + Disable IPv4 on pdnsd startup by default (default=enabled) +
+ --enable-ipv6-startup + + Enable IPV6 on pdnsd startup by default (default=IPv4). + These options are only defaults, you can specify on + the command line or in the config files which IP version + will really be used. + Normally, you won't need to change these. +
+ --disable-udp-queries + + Disable UDP as query method. You shouldn't need to change + this. +
+ --disable-tcp-queries + + Disable TCP as query method. This only effects the querying of + name servers by pdnsd, not the ability of pdnsd to answer + TCP queries from clients. + TCP queries are slower than UDP queries, but can be more secure + against certain types of attacks and are able to handle large answers. + For normal use this can be disabled. + (Note that the default has changed: TCP-query support + is now compiled in by default, but it still depends on the run-time + options whether it is actually used.) +
+ --with-query-method=qm + + Specify the query method (default=udponly, others: tcponly, tcpudp, udptcp). + If you have enabled both UDP and TCP queries, this lets you control + which query method pdnsd will use by default. tcpudp will try TCP + first and fall back to UDP if TCP is not supported by the server; + udptcp will try UDP first and, if the answer was truncated, will repeat + the query using TCP. + udponly and tcponly should be clear. Note that this only effects + the compiled-in default; the query method can still be changed using + command-line options or options in the configuration file. +
+ --disable-tcp-server + + Disable the TCP server. + In this case pdnsd will not be able to respond to TCP queries from clients. + This may cause problems with very large answers. +
+ --disable-src-addr-disc + + Disable the UDP source address discovery.
+ You need this only if you have trouble with messages saying + "could not discover udp source address".
+ For the Cygwin target, this option is disabled by default. +
+ --disable-poll + + Disable poll(2) and use select(2) (default=enabled)
+ You will normally not need this. +
+ --disable-new-rrs + + Since version 1.2.9 this option is obsolete and ignored. + It is now possible to configure for each RR type separately whether it is + cacheable by pdnsd by editing the file src/rr_types.in. + The comments in this file explain how to do this. +
+ --enable-strict-rfc2181 + + Enforce strict RFC 2181 compliance.
+ This will cause pdnsd to reject DNS answers with incorrect + timestamp settings (multiple RRs of the same type and for the same domain with + different TTLs). Normally not needed. +
+ --enable-underscores + + This option is obsolete. Since version 1.2, pdnsd places no restrictions + on the types of characters in domain names (there are still a few restrictions + for locally defined names, though). +
+ --with-random-device=device + + Specify random device; default: C Library random() PRNG
+ pdnsd uses (pseudo-) random numbers as query IDs for security reasons + (this makes forging DNS answers more difficult). This option + controls where pdnsd gets these from. The default is the C library + random() function, which is relatively weak. + You can specify a device like /dev/urandom here if you like; pdnsd will read + random numbers from it 16-bit-wise. /dev/urandom is present under Linux and + most BSD derivates. You should not use /dev/random - it is more secure, but + may block and delay pdnsd's answers for a long time.
+ You can specify arc4random to use the BSD arc4random() + library function (default for FreeBSD target), which is considered safe.
+ You can also specify random as device to use the C Library + random() function (described above). +
+ --with-default-id=user + + Specify default user for pdnsd (default=nobody). + This is the user that will be entered for the run_as + option in the config file (see below) that will be installed during make install. + You can change this any time in your config file. +
+ --with-debug=level + + Specify debugging level. Normally you can safely switch debugging off + by setting the level to 0. This will increase speed (although only + marginally) and save space in the executable (only about 12kB). + However, more significant may be the savings in stack space, especially + if pdnsd is put under heavy load and there are many simultaneous + running threads.
+ Presently the only defined debug levels are in the range 0 - 9. + Setting the level to 9 enables hex dumps of the queries and replies + pdnsd receives and should normally not be needed. Debug output will only + be generated if you turn on special switches; it might be useful for + debugging your config files, so I recommend using the default (1). + However, if you use pdnsd under heavy load, a better strategy may be + to compile one version of pdnsd without debug support (configured with + --with-debug=0) for production use, and one version with + with debug support (e.g. --with-debug=9) + for diagnostic purposes. +
+ --with-verbosity=level + + Specify default message verbosity. The default should be ok. +
+ --enable-rcsids + + Enable RCS IDs in executables (default=disabled).
+ For personal use, there is no need to do this. If you build rpm's, it + might have advantages. +
+ --enable-tcp-subseq + + Enable subsequent tcp queries. The DNS protocol standard + requires that servers must be capable of answering multiple + subsequent queries that are sent over the same tcp connection, and that + the server may only close the connection by himself after a certain + timeout. This feature is rarely used, but may make denial-of-service + attacks easier, as it allows for an attacker to hold a connection open + a long time (although the attacker's IP is most likely revealed then). + For full standard compliance, you should use this option. + If you do not use --enable-tcp-server, is option is not honored. +
+ --with-tcp-qtimeout=secs + + Specify default tcp query timeout after which the connection is closed + if no full query has been received. The default is 30s. + You can also change this option at run time using the tcp_qtimeout + config file option. + If you do not use --enable-tcp-server, is option is not honored. +
+ --with-par-queries=num + + Specify the default number of queries that can be executed in parallel. + You can also change this option at run time using the par_queries + config file option. See the description of that option for an explanation + of what it really does.
+ The default for this option is 2. +
+ --with-max-nameserver-ips=num + + New in version 1.2.9b: + Specify the maximum number of IP addresses that can be used per nameserver obtained + from NS records (when resolving names recursively). + Just one IP address per nameserver is sufficient in the vast majority of cases + (and this was the strategy used by pdnsd in previous versions), + but in rare cases this will cause unnecessary resolve failures if the address chosen + for each nameserver happens to be unreachable while the other addresses would lead to + successful resolution.
+ The default for this option is 3. +
+ --with-thread-lib=lib + + Added by Paul Rombouts: Use this option if you experience problems with + signal handling under Linux. The usual symptom is that pdnsd fails to save + the cache to disk, and /var/cache/pdnsd/pdnsd.cache remains empty. + If you experience this kind of trouble, try reconfiguring with different values + for the --with-thread-lib option. The allowable values are + linuxthreads (or lt for short), linuxthreads2 + (or lt2 for short), and nptl. + By default the configure script tries to detect automatically whether + linuxthreads or nptl is more appropriate for your system, + but the method used is not foolproof. Look for the line: + checking if this is an NPTL-based system...
+ If the automatic test mistakenly indentifies the thread library on your system as + NPTL based, you should reconfigure with --with-thread-lib=lt and recompile. + If the result of the automatic test is "no" or if + --with-thread-lib=lt does not have the desired effect, try again using + --with-thread-lib=lt2 . +
+ Normally, you will need only --prefix, --sysconfdir and + --with-distribution. + If you specify your distribution using --with-distribution, this has the + following effects: +
    +
  • An rc script is copied in the appropriate localtion, which enables pdnsd to start + at machine boot time (see 0.4) +
  • Distribution-specific portions might be included in the generated pdnsd.spec + file (only important if you want to build rpm archives yourself). +
+ If you choose Generic, no rc script is installed, and a generic spec + file is generated.
+ + Further instructions are in the INSTALL document in the pdnsd source directory. + ./configure --help will give you a list of all supported command line + options.

+ Note added by Paul Rombouts: Some people may want change the compiler optimization flag. + I use the -O2 flag, but it might be safer to use a lower level of + optimization or no optimization at all. In that case prefix the + configure command with the desired compiler flags like this + (assuming you're using a bash shell): +

CFLAGS="-O1 -Wall" ./configure ...

+ + +
+

0.3.3 Building & installing

+ Type make in the source directory. Should work by now.
+ To install, type make install or do the installation by hand (see 0.3.4).
+ make install will do the following ($prefix is the prefix directory; see above):
+
    +
  1. copies pdnsd to $(prefix)/sbin/ +
  2. copies pdnsd-ctl to $(prefix)/sbin/ +
  3. copies docs/pdnsd.conf.sample (a sample configuration) to the pdnsd config directory. +
  4. creates your cache directory if it is not there. + After installation, you should check the file permissions and create or edit + /etc/pdnsd.conf to fit your needs (see below). + If you use the run_as option, please make sure that your + cache directory is owned by the user you specified with this option! +
+ You must be root for this installation!
+ Security notes: never make the pdnsd cache directory + writeable for untrusted users, or you will get several security holes: + the users might modify the cache contents, or plant dangerous links.
+ If you use a pidfile, you should be aware that you introduce security + problems if you place the pidfile in a directory in a NFS filesystem that + is writeable for untrusted users. Generally, the pidfile directory + (typically /var/run) should not be writeable for untrusted users. +
+

0.3.4 Manual installation

+ For a manual installation, you need to do the following steps: +
    +
  1. Copy pdnsd and pdnsd-ctl from your build directory to an appropriate location (e.g. /usr/sbin). +
  2. Copy docs/pdnsd.conf into the directory you want it to reside (/etc by default, + and change it according to your needs (see below). +
  3. Create your caching directory; default is /var/cache/pdnsd (you may change this + in your pdnsd.conf); Permissions should be at max rwxr-xr-x (if you want to + protect your cache and status socket, make it rwx------). +
+ Thats it! +
+ +

0.4 Start at boot time

+ In the src/rc folder of the pdnsd distribution are start scripts + for pdnsd designed for different Linux distros. There are scripts + for SuSE, Redhat, Debian, Arch Linux and Slackware now.
+ The start scripts are automatically installed during RPM install, and also during make install + if you specified your distro.
+ For Slackware Linux there is a start-up script contributed by Nikola Kotur, but presently + it must be installed manually. + See src/rc/README and src/rc/Slackware/rc.pdnsd for details. + +

0.4.1 SuSE Linux startup

+ rc/SuSE/pdnsd is a start script for SuSE Linux. It was tested for 6.? but should run on some + versions below. You can do make install as root in the rc/SuSE + directory to install it, or you can install manually:
+ + + + + + + +
+ manual installation +
+ For manual installation, copy rc/SuSE/pdnsd into /sbin/init.d/, go to + /sbin/init.d/rc2.d/ and create there the following two symlinks:
+ S11pdnsd to ../pdnsd (do ln -s ../pdnsd S11pdnsd in that dir)
+ K34pdnsd to ../pdnsd (do ln -s ../pdnsd K34pdnsd in that dir)
+ The numbers dictate the order different services are started and + might need to be modified. Then edit your /etc/rc.config file and + add the line START_PDNSD=yes to start pdnsd at boot time. +
+

+ If you used the make install command, START_PDNSD=yes has been + appended to your /etc/rc.config file, causing pdnsd to be started + at boot time. If you don't want that, change the yes into no. +

+ This start script was created from /sbin/init.d/skeleton by me, so the + most is copyrighted by SuSE. They put it under the GPL, however, so + the license stated in COPYING also applies to this script. + There is NO WARRANTY OF ANY KIND on these scripts. + This is no official SuSE script, and SuSE naturally does NO support + for it. +

0.4.2 Red Hat Linux startup

+ rc/Redhat/pdnsd is a start script for Red Hat Linux. It was contibuted by Torben + Janssen.
+ This was tested for 6.1 but should run on 5.0+. You can do make install as root in the + rc/Redhat directory to install it, or you can install manually:
+ + + + + + + +
+ manual installation +
+ For manual installation, copy rc/Redhat/pdnsd into /etc/rc.d/init.d/
+ Then go to /etc/rc.d/rc3.d and create there the following symlink:
+ S78pdnsd -> ../init.d/pdnsd + (do ln -f -s ../init.d/pdnsd S78pdnsd in that dir)
+ + Then go to /etc/rc.d/rc0.d and create there the following symlink:
+ K78pdnsd -> ../init.d/pdnsd + (do ln -f -s ../init.d/pdnsd K78pdnsd in that dir)
+ + Then go to /etc/rc.d/rc6.d and create there the following symlink:
+ K78pdnsd -> ../init.d/pdnsd + (do ln -f -s ../init.d/pdnsd K78pdnsd in that dir) +
+ This script is also covered by license stated in COPYING. + Again, there is NO WARRANTY OF ANY KIND on these scripts. + This is no offical Redhat script, and Redhat naturally does NO support + for it +
+

0.5 Notes for FreeBSD users

+ The special handling of ISDN ppp devices is only supported on Linux. It is not needed in FreeBSD, the normal + device handling also works fine with isdn4bsd devices.
+ When compiled for FreeBSD, pdnsd as a small RFC compatability issue: RFC2181 demands answers on dns querys + to be sent with the same source address the query packet went to. In seldom cases, this will not be the case, + because the kernel selects the source address depending on the interface that was used for sending the answer.
+ Setting the source address currently does not work for IPv4. I have written a kernel patch that will provide an easy way + to program this. We'll see if or when it gets commited.
+
+
+

1 Invocation

+ When invoking pdnsd, you can specify various options at the command line. Command line options + always override config file options. The various --noX options are present to override + config file options. +

+ pdnsd --help (or -h) gives you an overview of the pdnsd command line options. +

+

+ pdnsd --version (or -V for short) prints licence and version information. +

+

+ To start pdnsd as background daemon, specifiy --daemon (or -d for short) on + the command line. Diagnostic and error messages after the actual daemon start + will be printed to the syslog instead of the console. --nodaemon will disable this. +

+

+ When starting pdnsd as a daemon, the -p option may be helpful: It writes the pid + of the server process to the file of the name given as argument to this option.
+ Example: pdnsd -d -p /var/run/pdnsd.pid +

+

+ If you want to specify a configuration file other than /etc/pdnsd.conf, specify + -c or --config-file on the command line, followed by a filename. +

+

+ If pdnsd was compiled with debugging support, you may specify -g or + --debug on the command line. This will cause extra diagnostic messages to be + printed. When pdnsd runs in daemon mode, the messages will be written to the pdnsd.debug + file in your cache directory. --nodebug disables debugging. +

+

+ pdnsd -vn sets the verbosity level of pdnsd. n is normally a digit from 0 to 3, + where 0 means normal operation, while 3 will most verbose. + Level 9 can be used in combination with the --debug option for very + extensive debug information.
+ Note: The current implementation mostly ignores the verbosity level, + so you may not notice much difference between the various levels. +

+

+ The option -s or --status enables the status control socket. This is a named socket in + the cache directory called pdnsd.status. This socket allows run-time configuration of pdnsd + using the utility pdnsd-ctl. See below for more details about pdnsd-ctl. + --nostatus disables status control. + See also the configuration option status_ctl in the global section. +

+

+ The option --notcp disables the seldom needed TCP server thread, which may + save you some resources. -t or --tcp will enable it. + See also the tcp_server configuration option. +

+

+ Using the -m option, you can select the method pdnsd uses to query other name servers. + Following methods are supported (see also the query_method + configuration option):
+ -muo: pdnsd will use UDP only. This is the fastest method, and should be supported by all name servers + on the Internet.
+ -mto: pdnsd will use TCP only. TCP queries usually take longer time than UDP queries, but are more secure + against certain attacks, where an attacker tries to guess your query id and to send forged answers. TCP queries + are not supported by some name servers.
+ -mtu: pdnsd will try to use TCP, and will fall back to UDP if its connection is refused or times out.
+ -mut: New in version 1.2.5: pdnsd will try to use UDP, and will repeat the query using TCP if the UDP reply was truncated + (i.e. the tc bit is set). This is the behaviour recommended by the DNS standards.
+

+

+ The -4 option switches to IPv4 mode, providing pdnsd was compiled with IPv4 support.
+ The -6 option switches to IPv6 mode, providing pdnsd was compiled with IPv6 support.
+ The -a option is only available when pdnsd was compiled with both IPv4 and IPv6 support. + With this option, pdnsd will try to detect automatically if a system supports IPv6, and fall back to IPv4 otherwise.
+

+

+ With -i prefix or --ipv4_6_prefix=prefix you can set the prefix pdnsd uses (when running in IPv6 + mode) to map IPv4 addresses in the configuration file to IPv6 addresses. + There is also a corresponding option for the config file, see below. + Must be a valid IPv6 address. + The default is ::ffff:0.0.0.0 +

+ +

2 The configuration file

+ This section describes the layout of the configuration file and the available + configuration options. + The default location of the file is /etc/pdnsd.conf. This may be changed + with the -c command line option. + An example pdnsd.conf comes with the pdnsd distribution in the docs directory + and will be installed to /etc/ by make install. + +
+

2.1 Layout

+ The configuration file is divided into sections. Each section is prefixed with + the section name and opening curlies ({) and closed with closing curlies (}). + In each section, configuration options can be given in the form +
+ option_name=option_value; +
+ Option value may be a string literal, a number, a time specification or a constant. + In previous versions of pdnsd strings had to be enclosed + in quotes ("), but since version 1.1.10 this is no longer necessary, unless + a string contains a special character such as whitespace, a token that normally starts + a comment, or one of ",;{}\". + Since version 1.2.9 a backslash (\) inside a string is interpreted as an escape character, + so it is possible to include special characters in strings (both quoted or unquoted) + by preceding them with a backslash. Some escape sequences are in interpreted as in the C + programming language, e.g. \t becomes a tab, + \n becomes a new-line control char.
+ A time specification consists a sequence of digits followed by a one-letter suffix. + The following suffixes are recognized: + s (seconds), m (minutes), h (hours), + d (days) and w (weeks). + If the suffix is missing, seconds are assumed. + If several time specifications are concatenated, their values are added together; + e.g. 2h30m is interpreted as 2*60*60 + 30*60 = 9000 seconds.
+ Some options take more than one value; in this case, the values are separated with commas.
+ If you may supply one of a set of possible values to an option, this is noted + in the documentation as + (option1|option2|option3|...)
+ The constants true|false and yes|no + are accepted as synonyms for the constants on|off.
+ Comments may be enclosed in /* and */, nested comments are possible. If the + # sign or two slashes (//) appear in the configuration file, everything from + these signs to the end of the current line is regarded as a comment and ignored.
+ There are examples for nearly all options in the sample config file. +
+

2.1.1 global Section

+ The global section specifies parameters that affect the overall behaviour of the + server. If you specify multiple global sections, the settings of those later in + the file will overwrite the earlier given values.
+ These are the possible options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ perm_cache=(number|off);
+ Switch the disk cache off or supply a maximum cache size in kB. If the disk + cache is switched off, 8 bytes will still be written to disk. + The memory cache is always 10kB larger than the file cache. + This value is 2048 (2 MB) by default. +
+ cache_dir=string;
+ Set the directory you want to keep the cache in. + The default is "/var/cache/pdnsd" + (unless pdnsd was compiled with a different default). +
+ server_port=number;
+ Set the server port. This is especially useful when you want to start the + server and are not root. Note that you may also not specify uptest=ping in + the server section as non-root.
+ The default port is 53, the RFC-standard one. Note that you should only use + non-standard ports when you only need clients on your machine to communicate + with the server; others will probably fail if the try to contact the server + on the basis of an NS record, since the A record that supplies the address for + (among others) name servers does not have a port number specification. +
+ server_ip=string;
+ or
+ interface=string;
+ Set the IP address pdnsd listens on for requests. This can be useful + when the host has several interfaces and you want pdnsd not to listen on + all interfaces. For example, it is possible to bind pdnsd to listen on + 127.0.0.2 to allow pdnsd to be a forwarder for BIND. + The default setting for this option is server_ip=any, which means that + pdnsd will listen on all of your local interfaces. + Presently you can only specify one address here; if you want pdnsd to listen on multiple + interfaces but not all you will have to specify server_ip=any + and use firewall rules to restrict access.
+ The IP address used to need quotation marks around it, but since version 1.1.10 + this is no longer necessary.
+ If pdnsd has been compiled with both IPv4 and IPv6 support, and you want to + specify an IPv6 address here, then unless pdnsd was compiled to start up in IPv6 mode + by default, you will need to use the -6 command-line option or + set run_ipv4=off first (see below) in order to ensure that the + IPv6 address is parsed correctly.
+ If pdnsd is running in IPv6 mode and you specify an IPv4 address here, + it will automatically be mapped to an IPv6 address.
+ New in version 1.2: You may also give the name of an interface + such as "lo" or "eth0" here, instead of an IP address + (this has been tested on Linux, and may or may not work on other platforms). + pdnsd will not bind to the interface name, but will look up the address of the + interface at start-up and listen on that address. If the address of the interface + changes while pdnsd is running, pdnsd will not notice that. You will need to + restart pdnsd in that case. +
+ outgoing_ip=string;
+ or
+ outside_interface=string;
+ New in version 1.2.9: + Set the IP address of the interface used by pdnsd for outgoing queries. + This can be useful when the host has several interfaces and you want pdnsd + to send outgoing queries via only one of them. + For example, if pdnsd is running on a host with one interface with IP address + 192.168.1.1 connected to the local network, and another with IP address 123.xxx.yyy.zzz + connected to the internet, you may specify server_ip=192.168.1.1 + and outgoing_ip=123.xxx.yyy.zzz to enforce that pdnsd only responds + to queries received from the local network, and only sends outgoing queries via + the interface connected to the internet.
+ The default setting for this option is any, which means that + the kernel is free to decide which interface to use. + Like with the server_ip option, you may also give the name of an + interface here, instead of an IP address. +
+ linkdown_kluge=(on|off);
+ This option enables a kluge that some people might need: when all servers are + marked down, with this option set the cache is not even used when a query is + received, and a DNS error is returned in any case. The only exception from this + is that local records (as specified in rr and source + sections are still served normally. + In general, you probably want to get cached entries even when the network is down, + so this defaults to off. +
+ max_ttl=timespec;
+ This option sets the maximum time a record is held in cache. All dns + resource records have a time to live field that says for what period of time the + record may be cached before it needs to be requeried. If this is more than the + value given with max_ttl, this time to live value is set to max_ttl. + This is done to prevent records from being cached an inappropriate long period of time, because + that is almost never a good thing to do. Default is 604800s (one week). +
+ min_ttl=timespec;
+ This option sets the minimum time a record is held in cache. All dns + resource records have a time to live field that says for what period of time the + record may be cached before it needs to be requeried. If this is less than the + value given with min_ttl, this time to live value is set to min_ttl. + Default is 120 seconds. +
+ neg_ttl=timespec;
+ This option sets the time that negatively cached records will remain valid in the + cache if no time to live can be determined. This is always the case when whole + domains are being cached negatively, and additionally when record types are cached + negatively for a domain for which no SOA record is known to pdnsd. If a SOA is present, + the ttl of the SOA is taken. +
+ neg_rrs_pol=(on|off|auth|default);
+ This sets the RR set policy for negative caching; this tells pdnsd under which circumstances + it should cache a record type negatively for a certain domain. off will + turn the negative caching of record types off, on will always add a negative + cache entry when a name server did not return a record type we asked it for, and auth + will only add such entries if the answer came from an authoritative name server for that + domain.
+ New in version 1.2.8: The default setting will add a negatively cached record + if either the answer was authoritive or the answer indicated the name server had "recursion available" + while the query explicitly requested such recursion.
+ The preset is "default" (used to be auth). +
+ neg_domain_pol=(on|off|auth);
+ This is analogue to neg_rrs_pol for whole domain negative caching. It should be safe + to set this on, because I have not seen a caching server that will falsely claim that a + domain does not exist.
+ The default is auth. +
+ run_as=string;
+ This option allows you to let pdnsd change its user and group id after operations that needed + privileges have been done. This helps minimize security risks and is therefore recommended. The + supplied string gives a user name whose user id and primary group id are taken.
+ A little more details: after reading the config file, becoming a daemon (if specified) and starting + the server status thread, the main thread changes its gid and uid, as do all newly created threads + thereafter. By taking another uid and gid, those threads run with the privileges of the + specified user. + Under Linux and FreeBSD, the server status thread runs with the original privileges only when the strict_setuid option + is set to off (see below, on by default), because these may be needed + for exec uptests. The manager thread also retains its original privileges in this case. + You should take care that the user you specify has write permissions on your cache file and + status pipe (if you need a status pipe). You should look out for error messages like "permission denied" + and "operation not permitted" to discover permission problems.
+
+ strict_setuid=(on|off);
+ When used together with the run_as option, this option lets you specify that all threads of the + program will run with the privileges of the run_as user. This provides higher security than + the normal run_as + option, but is not always possible. See the run_as option for further discussion.
+ This option is on by default.
+ Note that this option has no effect on Non-Linux systems. +
+ paranoid=(on|off);
+ Normally, pdnsd queries all servers in recursive mode (i.e. instructs servers to query other servers themselves + if possible, + and to give back answers for domains that may not be in its authority), and accepts additional records with information + for servers that are not in the authority of the queried server. This opens the possibility of so-called cache poisoning: + a malicious attacker might set up a dns server that, when queried, returns forged additional records. This way, he might + replace trusted servers with his own ones by making your dns server return bad IP addresses. This option protects + you from cache poisoning by rejecting additional records + that do not describe domains in the queried servers authority space and not doing recursive queries any more. + An exception + to this rule are the servers you specify in your config file, which are trusted.
+ The penalty is a possible performance decrease, in particular, more queries might be necessary for the same + operation.
+ You should also notice that there may be other similar security problems, which are essentially problems of + the DNS, i.e. + any "traditional" server has them (the DNS security extensions solve these problems, but are not widely + supported). + One of this vulnerabilities is that an attacker may bombard you with forged answers in hopes that one may match a + query + you have done. If you have done such a query, one in 65536 forged packets will be succesful (i.e. an average packet + count of 32768 is needed for that attack). pdnsd can use TCP for queries, + which has a slightly higher overhead, but is much less vulnerable to such attacks on sane operating systems. Also, pdnsd + chooses random query ids, so that an attacker cannot take a shortcut. If the attacker is able to listen to your network + traffic, this attack is relatively easy, though.
+ This vulnerability is not pdnsd's fault, and is possible using any conventional + name server (pdnsd is perhaps a little more secured against this type of attacks if you make it use TCP).
+ The paranoid option is off by default.
+
+ ignore_cd=(on|off);
+ New in version 1.2.8: This option lets you specify that the CD bit of a DNS query will be ignored. + Otherwise pdnsd will reply FORMERR to clients that set this bit in a query. + It is safe to enable this option, as the CD bit refers to 'Checking Disabled' + which means that the client will accept non-authenticated data.
+ This option is on by default. Turn it off if you want the old behaviour (before version 1.2.8). +
+ scheme_file=string;
+ In addition to normal uptests, you may specify that some servers shall only be queried when a certain + pcmcia-cs scheme is active (only under linux). For that, pdnsd needs to know where the file resides that + holds the pcmcia scheme information. Normally, this is either /var/lib/pcmcia/scheme or + /var/state/pcmcia/scheme. +
+ status_ctl=(on|off);
+ This has the same effect as the -s command line option: the status control is enabled when + on is specified.
+ Added by Paul Rombouts: Note that pdnsd-ctl allows run-time configuration of pdnsd, + even the IP addesses of the name servers can be changed. If you're not using pdnsd-ctl and + you want maximum security, you should not enable this option. It is disabled by default. +
+ daemon=(on|off);
+ This has the same effect as the -d command line option: the daemon mode is enabled when + on is specified.
+ Default is off. +
+ tcp_server=(on|off);
+ tcp_server=on has the same effect as the -t or --tcp + command-line option: it enables TCP serving. + Similarly, tcp_server=off is like the --notcp command-line option.
+ Default is on. +
+ pid_file=string;
+ This has the same effect as the -p command line option: you can specify a file that pdnsd + will write its pid into when it starts in daemon mode. +
+ verbosity=number;
+ This has the same effect as the -v command line option: you can set the verbosity of pdnsd's + messages with it. The argument is a number between 0 (few messages) to 3 (most messages). +
+ query_method=(tcp_only|udp_only|tcp_udp|udp_tcp);
+ This has the same effect as the -m command line option. + Read the documentation for the command line option on this. + tcp_only corresponds to the to, udp_only to the uo, + tcp_udp to the tu and udp_tcp to the ut + argument of the command line option.
+ If you use query_method=tcp_udp, it is recommended that you also set the global timeout option to at least twice the longest server timeout. +
+ run_ipv4=(on|off);
+ This has the same effect as the -4 or -6 command line option: + if on is specified, IPv4 support is enabled, and IPv6 support is disabled (if available). + If off is specified, IPv4 will be disabled and IPv6 will be enabled. + For this option to be meaningful, pdnsd needs to be compiled with support for the protocol you choose. + If pdnsd was compiled with both IPv4 and IPv6 support, and you want to include IPv6 addresses + in the configuration file, you will probably need to specify run_ipv4=off first to + ensure that the IPv6 addresses are parsed correctly. +
+ debug=(on|off);
+ This has the same effect as the -g command line option: the debugging messages are enabled when + on is specified. +
+ ctl_perms=number;
+ This option allows you to set the file permissions that the pdnsd status control socket will have. These + are the same as file permissions. The owner of the file will be the run_as user, or, if none is specified, + the user who started pdnsd. If you want to specify the permissions in octal (as usual), don't forget + the leading zero (0600 instead of 600!). To use the status control, write access is needed. The default + is 0600 (only the owner may read or write).
+ Please note that the socket is kept in the cache directory, and that the cache directory permissions + might also need to be adjusted. Please ensure that the cache directory is not writeable for untrusted + users. +
+ proc_limit=number;
+ With this option, you can set a limit on the pdnsd threads that will be active simultaneously. If + this number is exceeded, queries are queued and may be delayed some time. + See also the procq_limit option.
+ The default for this option is 40. +
+ procq_limit=number;
+ When the query thread limit proc_limit is exceeded, connection attempts to pdnsd will be queued. + With this option, you can set the maximum queue length. + If this length is also exceeded, the incoming queries will be dropped. + That means that tcp connections will be closed and udp queries will just be dropped, which + will probably cause the querying resolver to wait for an answer until it times out.
+ See also the proc_limit option. A maximum of proc_limit+procq_limit + query threads will exist at any one time (plus 3 to 6 threads that will always + be present depending on your configuration).
+ The default for this option is 60. +
+ tcp_qtimeout=timespec;
+ This option sets a timeout for tcp queries. If no full query has been received on a tcp connection + after that time has passed, the connection will be closed. The default is set using the + --with-tcp-qtimeout option to configure. +
+ par_queries=number;
+ This option used to set the maximum number of remote servers that would be queried simultaneously, + for every query that pdnsd receives.
+ Since version 1.1.11, the meaning of this option has changed slightly. + It is now the increment with which the number of parallel queries is + increased when the previous set of servers has timed out. + For example, if we have a list server1, server2, server3, etc. of available servers + and par_queries=2, then pdnsd will first send queries to server1 and server2, + and listen for responses from these servers.
+ If these servers do not send a reply within their timeout period, pdnsd will send additional + queries to server3 and server4, and listen for responses from + server1, server2, server3 and server4, and so on until a useful reply is + received or the list is exhausted.
+ In the worst case there will be pending queries to all the servers in the list of available servers. + We may be using more system resources this way (but only if the first servers in the list + are slow or unresponsive), but the advantage is that we have a greater chance of catching a reply. + After all, if we wait longer anyway, why not for more servers.
+ See also the explanation of the global timeout option below.
+ 1 or 2 are good values for this option. + The default is set at compile time using the --with-par-queries option to configure. +
+ timeout=timespec;
+ This is the global timeout parameter for dns queries. + This specifies the minimum period of time pdnsd will wait after sending the + first query to a remote server before giving up without having + received a reply. The timeout options in the configuration file are + now only minimum timeout intervals. Setting the global timeout option + makes it possible to specify quite short timeout intervals in the + server sections (see below). This will have the effect that pdnsd will start + querying additional servers fairly quickly if the first servers are + slow to respond (but will still continue to listen for responses from + the first ones). This may allow pdnsd to get an answer more quickly in + certain situations.
+ If you use query_method=tcp_udp it is recommended that + you make the global timeout at least twice as large as the largest + server timeout, otherwise pdnsd may not have time to try a UDP query + if a TCP connection times out.
+ Default value is 0. +
+ randomize_recs=(on|off);
+ If this option is turned on, pdnsd will randomly reorder the cached records of one type + when creating an answer. This supports round-robin DNS schemes and increases fail + safety for hosts with multiple IP addresses, so this is usually a good idea.
+ On by default. +
+ query_port_start=(number|none);
+ If a number is given, this defines the start of the port range used for queries of pdnsd. The + value given must be >= 1024. The purpose of this option is to aid certain firewall + configurations that are based on the source port. Please keep in mind that another application + may bind a port in that range, so a stateful firewall using target port and/or process uid may + be more effective. In case a query start port is given pdnsd uses this port as the first port of a + specified port range (see query_port_end) used for queries. + pdnsd will try to randomly select a free port from this range as local port for the query.
+ To ensure that there are enough ports for pdnsd to use, the range between query_port_start and + query_port_end should be adjusted to at least (par_queries * proc_limit). + A larger range is highly recommended for security reasons, and also because other applications may + allocate ports in that range. If possible, this range should be kept out of the space + that other applications usually use.
+ The default for this option is 1024. Together with the default value of query_port_end, + this makes it the hardest for an attacker to guess the source port used by the pdnsd resolver. + If you specify none here, pdnsd will let the kernel choose the source port, but + this may leave pdnsd more vulnerable to an attack. +
+ query_port_end=number;
+ Used if query_port_start is not none. Defines the last port of the range started by query_port_start + used for querys by pdnsd. The default is 65535, which is also the maximum legal value for this option. + For details see the description of query_port_start. +
+ delegation_only=string;
+ Added by Paul Rombouts: This option specifies a "delegation-only" zone. + This means that if pdnsd receives a query for a name that is in a + subdomain of a "delegation-only" zone but the remote name server + returns an answer with an authority section lacking any NS RRs for + subdomains of that zone, pdnsd will answer NXDOMAIN (unknown domain). + This feature can be used for undoing the undesired effects of DNS + "wildcards". Several "delegation-only" zones may be specified together. + If you specify root servers in a server section it is + important that you set root_server=on in such a section.
+ Example: +

delegation_only="com","net";

+ This feature is off by default. It is recommended that you only use + this feature if you actually need it, because there is a risk that + some legitimate names will be blocked, especially if the remote + name servers queried by pdnsd return answers with empty authority + sections. +
+ ipv4_6_prefix=string;
+ This option has the same effect as the -i command-line option. + When pdnsd runs in IPv6 mode, this option specifies the prefix pdnsd uses to convert IPv4 addresses in + the configuration file (or addresses specified with pdnsd-ctl) + to IPv6-mapped addresses. + The string must be a valid IPv6 address. Only the first 96 bits are used. + Note that this only effects the parsing of IPv4 addresses listed after this option.
+ The default is "::ffff.0.0.0.0". +
+ use_nss=(on|off);
+ If this option is turned on, pdnsd will call initgroups() to set up the group access list, + whenever pdnsd changes its user and group id (see run_as option). + There is a possible snag, though, if initgroups() uses NSS (Name Service Switch) and + NSS in turn uses DNS. In such a case you may experience lengthy timeouts and stalls. + By setting use_nss=off, you can disable the initgroups() call + (only possible in versions 1.2.5 and later).
+ This option was contributed by Jan-Marek Glogowski.
+ On by default. +
+ udpbufsize=number;
+ New in version 1.2.9: + This option sets the upper limit on the size of UDP DNS messages. The default is 1024.
+ See also the edns_query server option below. +
+ +
+

2.1.2 server Section

+ Each server section specifies a set of name servers that pdnsd should try to get + resource records or authoritative name server information from. The servers are + queried in the order of their appearance (or parallel to a limited extend). + If one fails, the next one is taken and so on.
+ You probably want to specify the dns server in your LAN, the caching dns servers + of your internet provider or even a list of root servers in one or more server sections.
+ The supported options in this section are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ label=string;
+ Specify a label for the server section. This can be used to refer to this section + when using pdnsd-ctl, the pdnsd control utility.
+ You can give several server sections the same label, but if you want to change the addresses + of a server section (see ip option below) during run-time with + "pdnsd-ctl server label up dns1,dns2,...", + the label must be unique. +
+ ip=string;
+ Give the IP (the address, not the host name) of the server.
+ Multiple IP addresses can be given per server section. + This can be done by entering multiple lines of the form ip=string; + or a single line like this: +

ip=string,string,string;

+ IP addresses do not have to be specified in the configuration file. + A server section without IP addresses will remain inactive until it is assigned + one or more addresses with pdnsd-ctl, + the pdnsd control utility.
+ If pdnsd has been compiled with both IPv4 and IPv6 support, any IPv6 addresses you specify + here will be skipped with a warning message, unless pdnsd is running in IPv6 mode. + Thus, unless pdnsd was compiled to startup in IPv6 mode by default, you need to use the + command-line option -6 or set run_ipv4=off + first (see global section) in order to ensure + that IPv6 addresses are parsed correctly.
+ If pdnsd is running in IPv6 mode and you specify an IPv4 address here, + it will automatically be mapped to an IPv6 address. +
+ file=string;
+ New in version 1.2: This option allows you to give the name of a resolv.conf-style file. + Of the lines beginning with the nameserver keyword, the second field will be parsed as an + IP address, as if it were specified with the ip= option. The remaining lines will be ignored. + If the contents of the file changes while pdnsd is running, you can make pdnsd aware of the changes through the + use of pdnsd-ctl, the pdnsd control utility. + This is usually most conveniently done by placing the command "pdnsd-ctl config" in a script + that is automatically run whenever the DNS configuration changes.
+ For example, suppose you have a ppp client that writes the DNS configuration for your ISP to the file + /etc/ppp/resolv.conf and runs the script /etc/ppp/ip-up when a new + connection is established. One way of ensuring that pdnsd is automatically reconfigured is to + add a server section in the config file with file=/etc/ppp/resolv.conf and to + add the command "pdnsd-ctl config" to /etc/ppp/ip-up. +
+ port=number;
+ Give the port the remote name server listens on. Default is 53 (the official + dns port) +
+ uptest=(ping|none|if|dev|diald|exec|query);
+ Determine the method to check whether the server is available. Currently + defined methods are: + +
    +
  • ping: Send an ICMP_ECHO request to the server. If it doesn't respond + within the timeout, it is regarded to be unavailable until the next probe. +
  • none: The availability status is not changed, only the time stamp is updated. +
  • if: Check whether the interface (specified in the interface= option) is + existent, up and running. This currently works for all "ordinary" + network interfaces, interfaces that disappear when down (e.g. ppp?), + and additionally for Linux isdn interfaces (as of kernel 2.2). Note that + you need a /dev/isdninfo device file (major#45, minor#255), or the + isdn uptest will always fail. +
  • dev and diald: Perform an if uptest, and, if that + was succesful, additionally check whether a program is running that + has locked a given (modem-) device. The needed parameters are an interface (specified as for the if + uptest, e.g. "ppp0") and a device relative to /dev (e.g. + "modem" for /dev/modem specified using the device= option. + pdnsd will then look for a pid file for the given interface in /var/lock (e.g. + /var/run/ppp0.pid) and for a lockfile for the given device (e.g. /var/lock/LCK..modem), + and then test whether the locking process is the process that created the pid file and this process is still + alive. If this is the case, the normal if uptest is executed for the given interface.
    + The dev option is for pppd dial-on-demand, diald is the same for diald users. +
  • exec: Executes a given command in the /bin/sh shell + (as /bin/sh -c <command>) + and evaluates the result (the return code of the last command) in the shell's way of handling return codes, + i.e. 0 indicates success, all other indicate failure. The shell's process name will be + uptest_sh. The command is given with the uptest_cmd option (see below). + For secuity issues, also see that entry. +
  • query: New in version 1.2: + This works like the ping test, except it sends an (empty) DNS query to the remote server. + If the server sends a well-formed response back within the timeout period (except SERVFAIL), + it will be regarded as available. + This test is useful if a remote server does not respond to ICMP_ECHO requests at all, + which unfortunately is quite common these days. + It can also happen that a remote server is online but ignores empty DNS queries. + Then you will need the set the query_test_name option (see below). + In many cases this test will be a more reliable indicator of availability + than the ones mentioned before. +
+

+ The default value is none. +

+ NOTE: If you use on-demand dialing, use none, if, + dev, diald or exec, + since ping or query will send packets + in the specified interval and the interface will thus frequently dial! +

+ ping_timeout=number;
+ Sets the timeout for the ping test in tenths of seconds + (this unit is used for legacy reasons; actually the current implementation is + only accurate to a second).
+ The default is 600 (one minute). +
+ ping_ip=string;
+ The IP address for the ping test. The default is the IP of the name server. +
+ query_test_name=string;
+ New in version 1.2.9: + Sets the name to be queried when using uptest=query availability test. + If the string is the unquoted constant none, + an empty query is used (this the default), otherwise a query of type A will be + sent for the domain name specified here. It is not necessary for the domain name + to exist or have a record of type A in order for the uptest to succeed.
+ If the the remote server ignores empty queries, you will probably want to set + query_test_name="." (the root domain). +
+ uptest_cmd=string,string;
+ or
+ uptest_cmd=string;
+ Sets the command for the uptest=exec function to the first string. + If the second string is given, it specifies a user with whose user + id and primary group id the command is executed.
+ This is especially useful if you are executing the server as root, + but do not want the uptest to be performed with root privileges. + In fact, you should never execute the uptest as root if you can help + it.
+ If the server is running setuid or setgid, the privileges thus gained + are attempted to be dropped even before changing identity to the + specified user to prevent setuid/gid security holes (otherwise, any + user might execute commands as root if you setuid the executable).
+ Note that this is not always possible, and that pdnsd should never + be installed as setuid or setgid. + The command is executed using /bin/sh, so you should be able to use + shell builtin commands. +
+ interval=(timespec|onquery|ontimeout);
+ Sets the interval for the server up-test. The default is 900 seconds; + however, a test is forced when a query times out and the timestamp is reset then.
+ If you specify onquery instead of a timeout, the interface will be + tested before every query. This is to prevent automatically dialing + interfaces (diald/pppd or ippp) to dial on dns queries. It is intended to be + used in connection with an interface-testing uptest ;-)
+ Note that using uptest=exec, you might run into performance problems + on slow machines when you use that option. + DON'T use onquery with uptest=ping or + uptest=query, as it may cause delays if the server does not answer + (btw, it doesn't make sense anyway). + Note also that using onquery is no guarantee that the interface + will not be used. When another (reachable) dns server tells pdnsd + to query a third dns server for data, pdnsd will do that and has + no means of checking whether this will dial up the interface or not. + This however should be a rare situation.
+ New in version 1.2.3: + A third possibility is to specify interval=ontimeout. + In this case the server is not tested at startup/reconfiguration, nor at regular intervals, + but only after a DNS query to a server times out. Certain types of network problems + such as a refused connection will also cause the server to be considered unavailable. + However, once a server is declared dead it is never considered again unless it is revived using a + pdnsd-ctl config or server command. + The idea behind this option is to minimize uptests by assuming all + servers are available until there is reason to believe otherwise. +
+ interface=string;
+ The network interface (or network device, e.g. "eth0") for the uptest=if option. + Must be specified if uptest=if is given. +
+ device=string;
+ The (modem-) device that is used for the dev uptest. If you use this for a dial-on-demand + ppp uptest (together with uptest=dev), you need to enter the device you are using for your + pppd here, e.g. modem for /dev/modem.
+ Must be specified if uptest=dev is given. +
+ timeout=timespec;
+ Set the timeout for the dns query. The default is 120 seconds. You probably want to set this lower.
+ Timeouts specified in the configuration file are only treated as the + minimum period of time to wait for a reply. A queries to a remote + server are not canceled until a useful reply has been received, or all + the other queries have timed out or failed.
+ If you have also set the global timeout option, you may consider setting a fairly small value here. + See the explanation of the timeout option in the global + section for what that means. +
+ purge_cache=(on|off);
+ In every fetched dns record, there is a cache timeout given, which + specifies how long the fetched data may be cached until it needs to be + reloaded. If purge_cache is set to off, the stale records are not purged + (unless the cache size would be exceeded, in this case the oldest records are purged). + Instead, they are still served if they cannot succesfully be + updated (e.g. because all servers are down).
+ Default is off. +
+ caching=(on|off);
+ Specifies if caching shall be performed for this server at all. Default is + on. +
+ lean_query=(on|off);
+ Specifies whether to use the "lean" query mode. In this mode, only the + information actually queried from pdnsd is resolved and cached. This has + the advantage that usually less cache space is used and the query is + usually faster. In 90% of the cases, only address (A) records are needed + anyway. If switched off, pdnsd will always cache all data about a host + it can find and will specifically ask for all available records + (well, at least it is a good approximation for what it really does ;-) + This will of course increase the answer packet sizes.
+ Some buggy name servers may not deliver CNAME records when not asked for + all records. I do not know if such servers are around, but if you have + trouble resolving certain host names, try turning this option off.
+ A last note: If you use multiple pdnsd's that access each other, turning + this option on is probably a big win.
+ This on by default. +
+ edns_query=(on|off);
+ New in version 1.2.9: + Specifies whether to use EDNS (Extension mechanisms for DNS) for outgoing queries. + Currently this is only useful for allowing UDP message sizes larger than 512 bytes. + Note that setting this option on can give problems in combination with some legacy + systems or software, including, embarrassingly enough, previous versions of pdnsd.
+ The default is off, but if your network can handle UDP payloads + significantly larger than 512 bytes, the recommended value is on.
+ Note that this option only effects outgoing queries. If pdnsd receives a query using + EDNS, it will reply using EDNS regardless of the value of this option. +
+ See also the udpbufsize option above. +
+ scheme=string;
+ You can specify a pcmcia-cs scheme that is used in addition to the uptests. If you specify + a scheme here, the server this section is for will only be queries if the given scheme + is active. Shell wildcards (* and ?) are allowed in the string under their special + meanings. You need to use the scheme_file option on the global + section to make this option work. +
+ preset=(on|off);
+ This allows you to specify the initial state of a server before any uptest is performed. + on specifies that the server is regarded available. The default is on. + This is especially useful when you set uptest=none; and want to change + the status of a server only via pdnsd-ctl. +
+ proxy_only=(on|off);
+ When this option is set to on, answers given by the servers are always accepted, and no + other servers (as, for example, specified in the NS records of the query domain) are + queried. If you do not turn this option on, pdnsd will do such queries in some cases + (in particular when processing ANY queries).
+ This option is useful when you do not want pdnsd to make connections to outside servers + for some reasons (e.g. when a firewall is blocking such queries).
+ I recommend that you turn on lean_query when using this option.
+ Default is off. +
+ root_server=(on|off|discover);
+ Set this option to on if the servers specified in a section are root servers. + A root server will typically only give the name servers for the top-level domain in its reply. + Setting root_server=on will cause pdnsd to try to use cached information about + top-level domains to reduce to number of queries to root servers, making the resolving of + new names more efficient. + You can get a list of available root servers by running the command + "dig . ns".
+ This option is also necessary if you use the delegation_only option.
+ New in version 1.2.8: This option may also be set to "discover". + This will cause pdnsd to query the servers provided with the ip= option + to obtain the full list of root servers. The root-server addresses will replace the addresses + specified with the ip= option. + This will only be done once on startup, or after a "pdnsd-ctl config" command. + In this case the name servers specified with the ip= option don't have to be + root servers, they just have to know the names and addresses of the root servers. + After root-server discovery pdnsd will behave just as if root_server=on + had been specified.
+ Default is off. +
+ randomize_servers=(on|off);
+ New in version 1.2.6: Set this option to on to give each name server + in this section an equal chance of being queried. If this option is off, the name servers + are always queried starting with the first one specified. Even with this option on, the + query order is not truly random. Only the first server is selected randomly; the following + ones are queried in consecutive order, wrapping around to the beginning of the list when + the end is reached. Note that this option only effects the order within a section. The + servers in the first (active) section are always queried before those in the second one, + etc.
The default is off, but if you are resolving from root servers setting this + option on is highly recommended. If root_server=on this option also effects + the query order of the name servers for the top-level domains. +
+ reject=string;
+ New in version 1.2.6: This option can be used to make pdnsd reject replies that + contain certain IP addresses. You can specify a single IP address, which will be matched + exactly, or a range of addresses using an address/mask pair. + The mask can be specified as a simple integer, indicating the number of initial 1 bits in + the mask, or in the usual IP address notation. IP addresses may be either IPv4 or IPv6 + (provided there is sufficient support in the C libraries and support for AAAA records was + not disabled). + When addresses in the reject list are compared with those in a reply, only the bits + corresponding to those set in the netmask are significant, the rest are ignored.
+ Multiple addresses or address/mask pairs may be specified; this can be done by entering + multiple lines of the form reject=string; + or a single line like this: +

reject=string,string,string;

+ How pdnsd reacts when an address in the reply matches one in the reject list, + depends on the reject_policy option, see below. +
+ reject_policy=(fail|negate);
+ New in version 1.2.6: + This option determines what pdnsd does when an address in the reply from a name server + matches the reject list (see above). If this option is set to + fail, pdnsd will try another server, or, if there no more servers to try, + return the answer SERVFAIL. If this option is set to negate, pdnsd will + immediately return the answer NXDOMAIN (unknown domain) without querying additional + servers. The fail setting is useful if you don't always trust the servers in + this section, but do trust the servers in the following section. The negate + setting can be used to completely censor certain IP addresses. In this case you should put + the same reject list in every server section, and also set the + reject_recursively option (see below) to true.
+ The default is fail. +
+ reject_recursively=(on|off);
+ New in version 1.2.6: Normally pdnsd checks for addresses in the + reject list (see above) only when the reply comes directly from a name server + listed in the configuration file. With this option set to on, pdnsd will + also do this check for name servers that where obtained from NS records in the authority + section of a previous reply (which was incomplete and non-authoritative).
+ Default is off. +
+ policy=(included|excluded|simple_only|fqdn_only);
+ pdnsd supports inclusion/exclusion lists for server sections: with include= + and exclude= (see below) you can specify domain names for which this server + will be used or will not be used. The first match counts (i.e., the first include or + exclude rule in a server section that matches a domain name is applied, and the + search for other rules is terminated). If no rule matched a given domain name, + the policy= option determines whether this server is used for the + lookup for that domain name; when included is given, the server will + be asked, and when excluded is given, it will not. + If simple_only is given the server will be used if the name to lookup + is a simple (single-label) domain name, on the other hand if fqdn_only + is given the server will be used only for names consisting of two or more labels + (i.e. the name has at least one dot in-between).
+ If no server is available for a queried domain, pdnsd will return an error message + to the client that usually will stop the client's attempts to resolve a specific + domain from this server (the libc resolver will e.g. return an error to the application that + tried to resolve the domain if no other servers are available in the resolv.conf). + This may be of use sometimes.
+ Note: the simple_only and fqdn_only constants + were added by Paul Rombouts. + They are useful for controlling which name servers (if any) will be used by + pdnsd for resolving simple (single-label) host names. + fqdn_only used to stand for "fully qualified domain name only", but this is + actually a misnomer. The names in queries received by pdnsd are always considered to be + fully qualified. If you do not exactly understand what the options simple_only and + fqdn_only are good for, you are probably better off not using them.
+ The default for this option is included. +
+ include=string;
+ This option adds an entry to the exclusion/inclusion list. If a domain matches + the name given as string, the server is queried if this was the first matching rule + (see also the entry for policy).
+ If the given name starts with a dot, the whole subdomain + of the given name including the one of that name is matched, e.g. ".foo.bar." + will match the domain names a.foo.bar., a.b.c.foo.bar. and foo.bar.
+ If it does not start in a dot, only exactly the given name (ignoring the case, of course) + will be matched (hint: if you want to include all subdomains, but not the domain of the given + name itself, place an exact-match exclude rule before the include rule, e.g: + exclude="foo.bar."; include=".foo.bar.";
+ Previous versions of pdnsd + required that names given with this and the next option ended in a dot, but since + version 1.1.8b1-par8, pdnsd automatically adds a dot at the end if it + is missing.
+ pdnsd now also accepts a more compact notation for adding several "include" entries in + one line, e.g.: +

include=".foo",".bar",".my.dom";

+
+ exclude=string;
+ This option adds an entry to the exclusion/inclusion list. If a domain matches + the name given as string, the server is not queried if this was the first matching rule + (see also the entry for policy).
+ If the given name starts with a dot, the whole subdomain + of the given name including the one of that name is matched, e.g. ".foo.bar." + will match the domain names a.foo.bar., a.b.c.foo.bar. and foo.bar.
+ If it does not start in a dot, only exactly the given name (ignoring the case, of course) + will be matched (hint: if you want to exclude all subdomains, but not the domain of the given + name itself, place an exact-match include rule before the exclude rule, e.g: + include="foo.bar."; exclude=".foo.bar.";
+ pdnsd now also accepts a more compact notation for adding several "exclude" entries in + one line, e.g.: +

exclude=".foo",".bar",".my.dom";

+
+
+

2.1.3 rr Section

+ Every rr section specifies a dns resource record that is stored locally. It + allows you to specify own dns records that are served by pdnsd in a limited way. + Only A, PTR, CNAME, MX, NS and SOA records are implemented.
+ This option is intended to allow you to define RRs for 1.0.0.127.in-addr.arpa. + and localhost. (and perhaps even one or two hosts) without having to start an + extra named if your cached name servers do not serve those records. + It is NOT intended and not capable to work as a full-featured name server. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ name=string;
+ Specifies the name of the resource records, i.e. the domain name of + the resource the record describes. This option must be specified + before any a, ptr, cname, + mx, ns or soa records. + Names are interpreted as absolute domain names + (i.e. pdnsd assumes they end in the root domain). + For this and all following arguments that take domain names, you need to + specify domain names in dotted notation (example venera.isi.edu.).
+ Previous versions of pdnsd + required that domain names given in the configuration file ended in a + dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a + dot at the end if it is missing.
+ New in version 1.2: It is also possible to specify a name starting + with the label *. Such a name is called a wildcard. The * in a wildcard + can match one or more labels in a queried name, but only whole labels. + Any other * characters in a wildcard, apart from the leading one, + will only match a literal *.
+ For example, *.mydomain will match a.mydomain or www.a.mydomain, but not + mydomain. *.a*.mydomain will match www.a*.mydomain, but not www.ab.mydomain. + *a.mydomain will only match itself.
+ Before you can specify an rr section with name=*.mydomain + you must define some records for mydomain, typically NS and/or SOA records. + Example: +
+    rr {
+	name = mydomain;
+	ns = localhost;
+	soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400;
+    }
+    rr {
+	name = *.mydomain;
+	a = 192.168.1.10;
+    }
+ In this example, www.mydomain and ftp.mydomain will resolve to the numeric + address 192.168.1.10 (unless you add rr sections explicitly + specifying different addresses for www.mydomain or ftp.mydomain). + If you want mydomain also to resolve to a numeric address, + add an A record to the first rr section. +
+ ttl=timespec;
+ Specifies the ttl (time to live) for all resource records in this section after this entry. + This may be redefined. The default is 86400 seconds (=1 day). +
+ authrec=(on|off);
+ If this is turned on, pdnsd will create authoritative local records for this rr section. + This means that pdnsd flags the domain record so that records of this domain that are not + present in the cache are treated as non-existent, i.e. no other servers are queried for + that record type, and an response containing none of those records is returned. This is + most time what people want: if you add an A record for a host, and it has no AAAA record + (thus no IPv6 address), you normally don't want other name servers to be queried for it.
+ This is on by default.
+ Please note that this only has an effect if it precedes the name option! +
+ reverse=(on|off);
+ New in version 1.2: If you want a locally defined name to resolve to a numeric address + and vice versa, you can achieve this by setting reverse=on before defining the A record + (see below). The alternative is to define a separate PTR record, but you will + probably find this option much more convenient.
+ The default is off. +
+ a=string;
+ Defines an A (host address) record. The argument is an IPv4 address in dotted notation. + pdnsd will serve this address for the host name given in the name option.
+ Provided there is sufficient support in the C libraries and support for AAAA records was not + disabled, the argument string may also be an IPv6 address, in which case an AAAA record + will be defined.
+ This option be may used multiple times within an rr section, causing + multiple addresses to be defined for the name. However, if you put the different addresses + in different rr sections for the same name, the definition in the last + rr section will cancel the definitions in the previous ones. +
+ ptr=string;
+ Defines a PTR (domain name pointer) record. The argument is a host name in + dotted notation (see name). The ptr record is for resolving adresses into names. For example, if + you want the adress 127.0.0.1 to resolve into localhost, and localhost into 127.0.0.1, you need something + like the following sections:
+
+    rr {
+	name = localhost;
+	a = 127.0.0.1;
+	owner = localhost;
+	soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400;
+    }
+    rr {
+	name = 1.0.0.127.in-addr.arpa;
+	ptr = localhost;
+	owner = localhost;
+	soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400;
+    }
+ The second section is for reverse resolving and uses the ptr option. + Note that you can get the same effect by specifying only the first rr section + with reverse=on.
+ There is something special about the name in the second section: + when a resolver wants to get a host name from an internet address, + it composes an address that is built of the IP address in reverse byte order + (1.0.0.127 instead of 127.0.0.1) where each byte of the adress written + as number constitutes a sub-domain under the domain in-addr.arpa.
+ So, if you want to compose an adress for reverse resolving, take your ip in dotted notation (e.g. 1.2.3.4), + reverse the byte order (4.3.2.1) and append in-addr.arpa. (4.3.2.1.in-addr.arpa.) + Then, define an rr section giving this address as name and the domain name corresponding to + that ip in the ptr option. +
+ cname=string;
+ Defines a CNAME (canonical name) record. + The argument should be a fully-qualified host name in dotted notation (see name). + A CNAME is the DNS equivalent of an alias or symbolic link.
+ A useful application for CNAMEs is giving short, easy to remember nicknames to hosts with complicated names. + For example, you might want the name "news" to refer to your ISP's news server "nntp2.myisp.com". + Instead of adding an A record for "news" with the same address as "nntp2.myisp.com", you could + put in a CNAME pointing to "nntp2.myisp.com", so that if the IP address of the news server changes, + there is no need to update the record for "news".
+ To implement this with pdnsd, you could add the following section to your configuration file:
+
+    rr {
+	name = news;
+	cname = nntp2.myisp.com;
+	owner = localhost;
+    }
+
+ mx=string,number;
+ Defines an MX (mail exchange) record. The string is the host name of the mail server in dotted notation (see name). + The number specifies the preference level.
+ When you send mail to someone, your mail typically goes from your E-mail client to an SMTP server. + The SMTP server then checks for the MX record of the domain in the E-mail address. + For example, with joe@example.com, it would look for the MX record for example.com and find + that the name of mail server for that domain is, say, mail.example.com. + The SMTP server then gets the A record for mail.example.com, and connects to the mail server.
+ If there are multiple MX records, the SMTP server will pick one based on the preference level + (starting with the lowest preference number, working its way up).
+ Don't define MX records with pdnsd unless you know what you're doing. +
+ owner=string;
+ or
+ ns=string;
+ Defines an NS (name server) record. Specifies the name of the host which should be authoritative for the records + you defined in the rr section. This is typically the host pdnsd runs on.
+ Note: In previous versions of pdnsd this option had to be specified before + any a, ptr, cname, mx or soa entries. + In version 1.2, the restrictions on this option are same as the options just mentioned, + and it must listed after the name= option. + This can be a pain if you want to use an old config file which specifies owner= + before name= (sorry about that). + Apart from greater consistency, the advantage is that you can now specify as many NS records as you like (including zero). +
+ soa=string,string,number,timespec,timespec,timespec,timespec;
+ This defines a soa (start of authority) record. The first string is the + domain name of the server and should be equal to the name you specified as + owner.
+ The second string specifies the email address of the maintainer of the name + server. It is also specified as a domain name, so you will have to replace the + @ sign in the name with a dot (.) to get the name you have to specify here. + The next parameter (the first number) is the serial number of the record. You + should increment this number if you change the record.
+ The 4th parameter is the refresh timeout. It specifies after what amount + of time a caching server should attempt to refresh the cached record.
+ The 5th parameter specifies a time after which a caching server should attempt + to refresh the record after a refresh failure.
+ The 6th parameter defines the timeout after which a cached record expires if it + has not been refreshed.
+ The 7th parameter is the ttl that is specified in every rr and should be the + same as given with the ttl option (if you do not specify a ttl, use the default 86400). +
+ txt=string,...,string;
+ New in version 1.2.9: + Defines an TXT record. You can specify one or more strings here. +
+
+

2.1.4 neg Section

+ Every neg section specifies a dns resource record or a dns domain that should be + cached negatively locally. Queries for negatively cached records are always answered + immediatley with an error or an empty answer without querying other hosts as long + as the record is valid. The records defined with neg sections remain + valid until they are explicitely invalidated or deleted by the user using + pdnsd-ctl.
+ This is useful if a certain application asks periodically for nonexisting hosts or + RR types and you do not want a query to go out every time the cached record has + timed out. Example: Netscape Communicator will ask for the servers news and mail + on startup if unconfigured. If you do not have a dns search list for your network, + you can inhibit outgoing queries for these by specifying
+
+    neg {
+	name = news;
+	types = domain;
+    }
+    neg {
+	name = mail;
+	types = domain;
+    }
+ in your config file. If you have a search list, you have to repeat that for any + entry in your search list in addition to the entries given above!
+ In versions 1.1.11 and later, if you negate whole domains this way, all subdomains + will be negated as well. Thus if you specify
+ neg {name=example.com; types=domain;} in the + config file, this will also negate www.example.com, xxx.adserver.example.com, etc. +

+ + + + + + + + + + +
+ name=string;
+ Specifies the name of the domain for which negative cache entries are created. + This option must be specified before the types option. + Names are interpreted as absolute domain names (i.e. pdnsd + assumes they end in the root domain). + You need to specify domain names in dotted notation (example venera.isi.edu.).
+ Previous versions of pdnsd + required that domain names given in the configuration file ended in a + dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a + dot at the end if it is missing. +
+ ttl=timespec;
+ Specifies the ttl (time to live) for all resource records in this section after this entry. + This may be redefined. The default is 86400 seconds (=1 day). +
+ types=(domain|rr_type[,rr_type[,rr_type[,...]]]);
+ Specifies what is to be cached negatively: domain will cache the whole + domain negatively; alternatively, you can specify a comma-separated list of RR types + which are to be cached negatively. You may specify multiple types options, but + domain and the RR types are mutually exclusive.
+ The RR types are specified using their official names from the RFC's in capitals, + e.g. A, CNAME, NS, PTR, MX, + AAAA, ...
+ The command pdnsd-ctl list-rrtypes will give you a complete list + of those types. pdnsd-ctl is built along with pdnsd + and will be installed in the same directory as the pdnsd binary during make install. +
+
+

2.1.5 source Section

+ Every source section allows you to let pdnsd read the records from a file in an + /etc/hosts-like format. pdnsd will generate records to resolve the entries + address from its host name and vice versa for every entry in the file. This is + normally easier than defining an rr for every of your addresses, since localhost + and your other FQDNs are normally given in /etc/hosts.
+ The accepted format is as follows: The #-sign initiates a comment, the rest of + the line from the first occurence of this character on is ignored. Empty lines + are tolerated.
+ The first entry on a line (predeceded by an arbitrary number of tabs and spaces) + is the IP in dotted notation, the second entry on one line (separated by the + first by an arbitrary number of tabs and spaces) is the FQDN (fully qualified + domain name) for that ip. The rest of the line is ignored by default (in the original + /etc/hosts, it may contain information not needed by pdnsd). +

+ + + + + + + + + + + + + + + + +
+ owner=string;
+ Specifies the name of the host pdnsd runs on and that are specified in dns + answers (specifically, nameserver records). + Must be specified before any file entries.
+ Names are interpreted as absolute domain names (i.e. pdnsd + assumes they end in the root domain). + You need to specify domain names in dotted notation (example venera.isi.edu.).
+ Previous versions of pdnsd + required that domain names given in the configuration file ended in a + dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a + dot at the end if it is missing. +
+ ttl=timespec;
+ Specifies the ttl (time to live) for all resource records in this section after + this entry. This may be redefined. The default is 86400 seconds (=1 day). +
+ file=string;
+ The string specifies a file name. For every file entry in a source section, + pdnsd will try to load the given file as described above. Failure is indicated + only when the file cannot be opened, malformed entries will be ignored. +
+ serve_aliases=(on|off);
+ If this is turned on pdnsd will serve the aliases given in a hosts-style file. + These are the third entry in a line of a hosts-style file, which usually give a "short name" for the host. + This may be used to support broken clients without a proper domain-search option. + If no aliases are given in a line of the file, pdnsd behaves as without this option for this line.
+ This feature was suggested by Bert Frederiks.
+ It is off by default. +
+ authrec=(on|off);
+ If this is turned on, pdnsd will create authoritative local records with the data from the hosts file. + Please see the description of the option of the same name in the rr section for a closer description of + what this means. Please note that this only has an effect for files sourced with file options + subsequent to this option.
+ This is on by default. +
+
+

2.1.6 include Section

+ A configuration file may include other configuration files. + However, only the top-level configuration file may contain global + and server sections, + thus include files are effectively limited to sections that add local definitions to the cache.
+ Include sections currently only have one type of option, which may be given multiple times within a single section. +

+ + + + +
+ file=string;
+ The string specifies a file name. For every file option in an include section, + pdnsd will parse the given file as described above. The file may contain include sections itself, + but as a precaution pdnsd checks that a certain maximum depth is not exceeded to guard against + the possibility of infinite recursion. +
+
+

3 pdnsd-ctl

+

+ pdnsd-ctl allows you to configure pdnsd at run time. To make this work, you have to start pdnsd with the -s + option (or use the status_ctl option in the config file). You also should make sure that you + have appropriate permissions on the control socket (use the ctl_perms option to make this sure) and of your pdnsd + cache directory (pdnsd keeps its socket there). Please make sure the pdnsd cache directory is not writeable for untrusted users!

+

+ pdnsd-ctl accepts two command-line options starting with a dash.
+ -c may be used to specify the cache directory (and takes this as argument). + The default for this setting is the pdnsd default cache directory (specified at compile time). + The cache directory for pdnsd-ctl must be the same pdnsd uses!
+ -q can be used to make the output of pdnsd-ctl less verbose.

+

+ The following table lists the commands that pdnsd-ctl supports. The command must always be + the first command-line option (not starting with a dash), the arguments to the command must follow in the given order.
+ In the following table, keywords are in a normal font, while placeholders are in italics.
+ Alternatives are specified like (alt1|alt2|alt3). + Optional arguments are placed between square brackets [].

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandArgumentsDescription
helpPrint a command summary.
versionPrint version and license info.
status + Print a description of pdnsd's cache status, thread status and configuration. + Also shows which remote name servers are assumed to be available. +
server(index|label)  (up|down|retest)  [dns1[,dns2[,...]]] + Set the status of the server with the given index or label (where the given label + matches the one given with the label option in the respective server section in the config file) + to up or down, or force a retest. The index is assigned in the order of definition in + pdnsd.conf starting with 0. Use the status command to view the indices and labels. + You can specify all instead of an index or label to perform the action for all + servers registered with pdnsd. Example:
+ pdnsd-ctl server 0 retest
+ An optional third argument consisting of a list of IP addresses (separated by commas or + white-space characters) can be given. + This list will replace the previous list of addresses of name servers used by pdnsd in the + specified section of the config file. + For example in the /etc/ppp/ip-up script called by pppd you could + place the following line:
+ pdnsd-ctl server isplabel up $DNS1,$DNS2
+ If white space is used to separate addresses the list will have to be quoted. + Spurious commas and white-space characters are ignored. + The last argument may also be an empty string, in which case the existing IP addresses are + removed and the corresponding server section becomes inactive. +
recordname  (delete|invalidate) + Delete or invalidate the records of the given domain name if it is in the + cache. Invalidation means that the records are marked as timed out, and + will be reloaded if possible (if purge_cache is set to on, they will + be deleted in any case).
+ For local records (i.e., records that were given in the config file + using a rr section, records read from a hosts-style file + and records added using pdnsd-ctl), invalidation has no effect. Deletion + will work, though. Example:
+ pdnsd-ctl record localhost. delete +
sourcefn  owner  [ttl]  [(on|off)]  [noauth] + Load a hosts-style file. Works like using the pdnsd + source configuration section. + owner and ttl are used as in the source section. ttl has a default + of 900 (it does not need to be specified). The next to last argument corresponds + to the serve_aliases option, and is off by default (i.e. if it is not specified). + noauth is used to make the domains non-authoritative - please see + the description of the authrec config file options for a description of what + that means. + fn is the filename. The file must be readable by pdnsd! Example:
+ pdnsd-ctl source /etc/hosts localhost. 900 off +
adda  addr  name  [ttl]  [noauth] + Add a record of the given type to the pdnsd cache, replacing existing + records for the same name and type. The 2nd argument corresponds + to the value of the option in the rr section that is named like + the first argument: a is a record for hostname-to-address mapping, + aaaa is the same thing for IPv6 addresses, and ptr is for address-to-hostname + mapping. See the documentation for the rr section for more details. + In case of A and AAAA records, the addr argument may be a list of IP addresses, + separated by commas or white space, causing multiple addresses to be defined + for the same name. + The ttl is optional, the default is 900 seconds. + noauth is used to make the domains non-authoritative - please see + the description of the authrec config file options for a description of what + that means. + If you want no other record than the newly added in the cache, do
+ pdnsd-ctl record name delete + before adding records. This is also better when overwriting local records. Example:
+ pdnsd-ctl add a 127.0.0.1 localhost. 900 +
addaaaa  addr  name  [ttl]  [noauth]
addptr  host  name  [ttl]  [noauth]
addcname  host  name  [ttl]  [noauth]
addmx  host  name  pref  [ttl]  [noauth]
addns  host  name  [ttl]  [noauth]
negname  [type]  [ttl] + Add a negatively cached record to pdnsd's cache, replacing existing + records for the same name and type. If no type is given, the whole + domain is cached negatively. For negatively cached records, errors are + immediately returned on a query, without querying other servers first. + The ttl is optional, the default is 900 seconds.
+ You can get a list of all types you can pass to this command using + pdnsd-ctl list-rrtypes. The type is treated case-sensitive! + Example:
+ pdnsd-ctl neg foo.bar A 900
+ pdnsd-ctl neg foo.baz 900
+
config[filename] + Reload pdnsd's configuration file.
+ The config file must be owned by the uid that pdnsd had when it was + started, and be readable by pdnsd's run_as uid. If no file name is + specified, the config file used at start-up is reloaded.
+ Note that some configuration changes, like the port or IP address pdnsd listens on, + cannot be made this way and you will receive an error message. + In these cases, you will have to restart pdnsd instead. +
includefilename + Parse the given file as an include file, see the documentation on + include sections for a description + what this file may contain.
+ This command is useful for adding definitions to the cache without reconfiguring pdnsd. +
evalstring + Parse the given string as if it were part of pdnsd's configuration file. + The string should hold one or more complete configuration sections. + However, global and + server sections are not allowed, + just as in include files. + If multiple strings are given, they will be joined using newline chars + and parsed together.
+ This command is useful for adding records interactively to the cache + that cannot be defined using the "pdnsd-ctl add" command, + (e.g. soa records). +
empty-cache[[+|-]name ...] + If no arguments are provided, the cache will be completely emptied, + freeing all existing entries. + Note that this also removes local records, as defined by the config file. + To restore local records, run "pdnsd-ctl config" or + "pdnsd-ctl include filename" immediately afterwards.
+ The "pdnsd-ctl empty-cache" command now accepts additional arguments; + these are interpreted as include/exclude names. If an argument starts with a '+' + the name will be included. If an argument starts with a '-' it will be + excluded. If an argument does not begin with '+' or '-', a '+' is + assumed. If the domain name of a cache entry ends in one of the names in + the list, the first match will determine what happens. If the matching + name is to be included, the cache entry is deleted, otherwise not. + If there are no matches, the default action is not to delete. + Note that if you want to delete exactly one name and no others, you should + use "pdnsd-ctl record name delete", + this is also much more efficient.
+ Examples:
+ pdnsd-ctl empty-cache
+ This command will remove all cache entries.
+
+ pdnsd-ctl empty-cache microsoft.com msft.net
+ This will remove all entries ending in microsoft.com or msft.net.
+
+ pdnsd-ctl empty-cache -localdomain -168.192.in-addr.arpa .
+ This will remove all entries except those ending in localdomain or + 168.192.in-addr.arpa. Note that '.' is the root domain which matches any + domain name. +
dump[name] + Print information stored in the cache about name. + If name begins with a dot and is not the root domain, information about + the names in the cache ending in name (including name without + the leading dot) will be printed. + If name is not specified, information about all the names in the cache will + be printed.
+ For each RR record the time and date that this record has been added to the cache + will be printed in the form mm/dd HH:MM:SS (locally defined records are printed without a time stamp). + After that the type of record is printed with the data. For the more common types + of RR records the data will be printed in human readable form, the remaining ones in a + hexadecimal representation.
+ This command is mainly useful for diagnostic purposes.
+ Note that if you pipe the output of this command through an application that + reads only part of the output and then blocks (such as more or less), + pdnsd will not be able to add new entries to the cache until the pipe is closed. + It is preferable to capture the output in a file in such a case. +
list-rrtypes + List available rr types for the neg command. + Note that those are only used for the neg command, not for add! +
+
+
+

4 contrib/

+ The contrib directory in the pdnsd distribution contains useful user-contributed scripts.
+ So far, there are scripts contributed by Marko Stolle and Paul Rombouts that make pdnsd + usable in a DHCP setup. + Please take a look into the README file in the contrib directory for further information. +
+
+

5 Problems...

+ If you have problems with configuring or running pdnsd, be sure to read the FAQ. + If this does not help you, pdnsd crashes or you find bugs, please mail one of the authors.
+ Note added by Paul A. Rombouts: + Thomas Moestl no longer maintains the code. I have revised the code and added new features. + See README.par and the + ChangeLog in the source directory + (or /usr/share/doc/pdnsd-<version> if you have installed a binary package) + for more details. + If you have questions about my modifications, you can find my email address at the end of + README.par. +
+
+

6 Hacking

+ Here comes some information you might find useful for hacking pdnsd. +
+

6.1 Source files

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Makefile.am, configure.in, acconfig.h + autoconf/automake/autoheader scripts. Makefile.am's are in most subdirectories. +
pdnsd.spec.in + A template from which configure generates a spec file for building rpm's for various + distributions. +
version + Contains only the program version string. Needed for several templates. +
src/rc/* + rc (start-up) scripts for various linux distributions. +
src/cache.c + The pdnsd cache subsystem(s) as defined in src/cache.h. + This is the "traditional" pdnsd system which keeps the cache in memory and uses hash tables for accesses. + Sourav K. Mandal is working on a system using gdbm. +
src/pdnsd-ctl/* + Contains the code for pdnsd-ctl, a program that allows you to control pdnsd at run time. +
src/conf-lex.l.in + The lex/flex source file for the config file lexer. This is a template because there might be + inserted "%option yylineno" for proper flex support. + (obsolete, superseded by src/conf-parser.c) +
src/conf-lex.l + This is automatically generated by configure from conf-lex.l.in. It may be overwritten + in any make, so never modify this, but conf-lex.l.in instead! + (obsolete, superseded by src/conf-parser.c) +
src/conf-parse.y + The yacc/bison source of the config file parser. + (obsolete, superseded by src/conf-parser.c) +
src/conf-parser.c, src/conf-parser.h, src/conf-keywords.h + The config file parser written purely in C (versions 1.1.10-par and later). +
src/conff.c, src/conff.h + The configuration handler functions and their prototypes. The parser is called from here. +
src/consts.h + Some constants used by the parser, config file handler functions and in the server status thread, + among others. +
src/dns.c, src/dns.h + Define dns message structures, constants, and some common dns data handlers. dns.h contains gcc-specific + code (in praticular, "__attribute__((packed))"). +
src/dns_answer.c, src/dns_answer.h + Define functions that answer incoming dns queries. +
src/dns_query.c, src/dns_query.h + Define functions to manage outgoing dns queries. +
src/error.c, src/error.h + Functions for error output to stderr or the syslog, and debug output to stderr or pdnsd.debug. +
src/hash.c, src/hash.h + Contains the code for storing and looking up cache entries in the hash table. +
src/helpers.c, src/helpers.h + Define miscellaneous helper functions. +
src/icmp.c, src/icmp.h + Define a function for performing a ping test. This contains OS-specific code. +
src/main.c + Contains main(), which holds the command line parser, performs initialisations and signal handling. +
src/make_hashconvtable.c + Contains the code for the executable make_hashconvtable, which is only run once, during build time, to generate the file hashconvtable.h, used by src/hash.c (versions 1.1.10-par and later). + (obsolete since version 1.2) +
src/make_rr_types_h.pl + A perl script for generating src/rr_types.h, + a C header file containing macro definitions and tables needed for handling the + RR types known to pdnsd, from the text file src/rr_types.in. +
src/rr_types.c, src/rr_types.h, src/rr_types.in + These define tables and macros needed for handling the RR types known to pdnsd. + Since version 1.2.9, rr_types.h is an automatically generated file, + see make_rr_types_h.pl. +
src/netdev.c, src/netdev.h + Define functions for network device handling. OS-specific. +
src/servers.c, src/servers.h + Define functions for the server status thread that performs the periodical uptests. +
src/status.c, src/status.h + Define functions for the status control thread. This is pdnsd's interface to pdnsd-ctl. +
+ +
+
+
+ Copyright (C) 2000, 2001 Thomas Moestl
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2012 Paul A. Rombouts +
+

+ Last revised: 19 April 2012 by Paul A. Rombouts +

+ + diff --git a/jni/pdnsd/doc/html/doc_makefile b/jni/pdnsd/doc/html/doc_makefile new file mode 100644 index 00000000..28fb7d50 --- /dev/null +++ b/jni/pdnsd/doc/html/doc_makefile @@ -0,0 +1,23 @@ + +versionfile = ../../version +arch = i686 +arch2 = x86_64 +extver = _sl6 +system = Scientific Linux 6.2 system + +doc: dl.html +.PHONY: doc clean + +# If the existing dl.html contains '???', then certain packages were missing +# during the previous build and dl.html needs to be built again. +ifneq ($(shell grep -F -l -e '???' dl.html),) +.PHONY: dl.html +endif + +dl.html: %.html: %.html.in htmlsubst.pl $(versionfile) + perl htmlsubst.pl version=`cat $(versionfile)` \ + baseurl='http://members.home.nl/p.a.rombouts/pdnsd/' \ + arch=$(arch) arch2=$(arch2) extver=$(extver) system="$(system)" $< > $@ + +clean: + @rm -fv dl.html diff --git a/jni/pdnsd/doc/html/faq.html b/jni/pdnsd/doc/html/faq.html new file mode 100644 index 00000000..eec65993 --- /dev/null +++ b/jni/pdnsd/doc/html/faq.html @@ -0,0 +1,412 @@ + + + + The pdnsd FAQ + + + + + + + + + + + + + + +
+ pdnsd Homepage + + pdnsd FAQ + + Documentation + + GNU GPL (pdnsd's License) + + Download Section +
+ +

The pdnsd FAQ

+ + + + + + + + + + +
Q: + There are complete and well-tested name servers around, such as the BIND. + These do also perform caching. Why should I use pdnsd? +
A: + pdnsd does not aim to be a complete name server implementation, such as the + BIND. It is optimized for caching, and you can only specify a small subset of all + dns record types pdnsd knows in your local "zone" definitions. + This of course reduces the code size drastically, and such the memory footprint. + There are some features especially interesting for dialin networks, ordinary + (non-server) internet hosts and computers that are often not connected to + to their network, e.g. notebooks (I originally wrote this program for use + with my notebook). + These features are: +
    +
  • permanent disk cache (useful for frequent power-offs/reboots) +
  • usually smaller memory footprint (depends on cache size) (see next question) +
  • offline-detection prevents hangs (e.g. the typical hang on startup of some + Netscape Navigator versions if not dialled in) +
  • better control about timeouts (also to prevent hangs) +
  • better control over the cache +
  • better run-time control +
+
+
+ + + + + + + + + + +
Q: + When I look at the process size with ps, top, gtop, or a similar tool, I see + some processes with a total size well above 3.5 MB. This is much more than + e.g. BIND named (about 1.4 MB). Why? +
A: + Really, it is not. + pdnsd uses multithreading, not multiprocessing. That means that the processes + share most of their process space. In the LinuxThreads library + or NPTL (Native Posix Thread Libary), + which are used by pdnsd on Linux, in fact the total process address space is shared + (although the processes have different stacks, these are in one process + address space). You may check this by looking at the at the process sizes of + the pdnsd threads: all should be the same. The effective size that pdnsd + occupies is thus the size of any of the processes, not the sum of those. + So, pdnsd with empty cache occupies about 800 kB, and the maximum size + should be about the cache size plus this size (in fact, ca 5-10% more). +
+
+ + + + + + + + + + +
Q: + What do I need the status control (option -s) for? +
A: + It enables you to do some things you might or might not need. With it, you can: +
    +
  • query pdnsd's settings at runtime to debug configuration files and + see which servers are regarded to be available +
  • mark servers as available or unavailable, or force a status retest - very + handy if you want to control which servers pdnsd queries, e.g for muliple + dial-up accounts +
  • delete, invalidate or add DNS records - useful e.g. when you want to build + records for dynamically assigned IP addresses or domain names +
  • reload pdnsd's configuration file without restarting pdnsd +
  • print information about the contents of pdnsd's cache. +
+
+
+ + + + + + + + + + +
Q: + What do I need local records (rr- and source-sections in the config file) for? +
A: + Some resolver programs, e.g. nslookup, want to look up the name of the + server they are using before doing anything else. This option is for defining + a PTR record for your IP such that those programs get an answer even if the + name server you are caching is not available or does not offer these records. + By extension, you may also define A and SOA records. This allows you to build + very small zones without having to use a "big" name server. It is NOT + intended to replace such a complete server in anything but VERY small + networks. Alternatively, you may start a named on another host or on the + same host on another port and cache it with pdnsd in addition to other (more + distant) name servers. +
+ The source section allows you to let pdnsd read in your + /etc/hosts file on startup and serve its contents. This file is used by your local + resolver before it even tries the name servers and usually contains + fully-qualified domain names (FQDNs) for all of the internet addresses your host has. + If you source this file, you usually won't need any additional rr sections. Sourcing it also allows + other hosts (eg. in your local network) to access the names defined in your + hosts file. You can of course just add other hosts in your local network to the + servers hosts file, thus making them known to your server's resolver + and pdnsd (if you sourced that file). +
+ If you don't know what this answer was all about, you should just take the + source section in the sample config file that comes with pdnsd, copy it + into your config file and forget about it. +
+
+ + + + + + + + + + +
Q: + When compiling, I get an error message like
Please define __BYTE_ORDER to + be __LITTLE_ENDIAN or __BIG_ENDIAN
What's up? +
A: + Normally, this macros should be defined in your C library's header files. + There are two different methods, most C libraries support both (and pdnsd + honors both): either __BYTE_ORDER is set to __LITTLE_ENDIAN + or __BIG_ENDIAN, or __LITTLE_ENDIAN or __BIG_ENDIAN + are directly defined as macros. +
+ Linux glibc, for example, does set those macros correctly. Never mind. You just have to know + whether your machine is little-endian or big-endian, this means wheter your + machine saves the least significant byte of a word or double-word first in memory (little-endian) or + the most significant first (big-endian). + All intel x86 and Alpha machines are little-endian, for example, while SPARC + and PowerPC architectures are big-endian. + If your machine is little-endian, add the following line to your config.h: +
+ #define __BYTE_ORDER __LITTLE_ENDIAN +
+ Likewise, if your machines byte order is big-endian: +
+ #define __BYTE_ORDER __BIG_ENDIAN +
+ Pathological byte orders like pdp-endian are not yet supported really; + However, for the place the endianess is needed, __LITTLE_ENDIAN should do + (it deals only with 16 bits; for all other occurances, ntoh[sl]/hton[sl] is used). +
+
+ + + + + + + + + + +
Q: + At startup, I get a warning saying:
+ + Uptest command [...] will implicitly be executed as root +
+ What does that mean? +
A: + This warning only occurs if you use the uptest=exec option in your + configuration. It means that the uptest command is run as root + because pdnsd is running as root, and this was not explicitely specified. + The idea is that it may introduce security holes (in the programs being run) + when they run as root, and so they shouldn't do that if possible. + You can specify the user that shall run the command by appending its name + comma-separated as string to the uptest_cmd line:
+ + uptest_cmd="<your command>","<user>"; +
+ If it is correctly running as root, just append the user string "root" to + the command and the warning will not occur again. +
+
+ + + + + + + + + + +
Q: + I cannot run my uptest_cmd command as root (it says permission denied), + although the pdnsd executable is setuid root. Why? +
A: + pdnsd will drop privileges gained through setuid/setgid before executing the + uptest commands (you shouldn't set the pdnsd executable setuid/setgid anyway). + The reason is clear: if you install the pdnsd + executable as setuid root and this wouln't be done, any user could execute + shellcode with root privileges using that option! +
+
+ + + + + + + + + + +
Q: + At startup, I get an error saying:
+ + Bad config file permissions: the file must be only writeable by the user +
+ Why is that? +
A: + pdnsd has an option (uptest=exec) that allows the execution of arbitrary + shell code (for testing whether an interface is up). This must be + of course secured against unauthorized use. One of these + protection is the one that produces the error message: if you routinely run + pdnsd, e.g. at system startup, and your config file is editable for others, + someone could change it and insert shell code that is executed in the next + pdnsd run -- with your user privileges! To prevent this, pdnsd will exit if the config file is writeable + by others than the owner. + To get rid of this message, just do
+ + chmod go-w <filename> +
+ on your config + file (for the default file: chmod go-w /etc/pdnsd.conf). + You should also check that the ownership is set correct. +
+
+ + + + + + + + + + +
Q: + serve_aliases does not seem to work. +
A: + Some resolvers (e.g. of the glibc 2.1) seem sometimes not to look up unmodified names, but the names with + an entry of the search path already appended. Since pdnsd will serve short names with this + option anyway, you can delete the search an domain options from your /etc/resolv.conf. This is reported to + work in some cases. +
+
+ + + + + + + + + + +
Q: + Some queries for domains that have many records (e.g. www.gmx.de) fail mysteriously. +
A: + pdnsd versions prior to 1.1.0 had the tcp server thread disabled by default. Most resolvers + repeat their query using tcp when they receive a truncated answer (the answer is truncated + when it exceeds a length of 512 bytes). You need to recompile pdnsd with the option + --enable-tcp-server to fix this. +
+
+ + + + + + + + + + +
Q: + I am behind some kind of firewall. In the configuration file + I have only listed addresses of name servers on the local (ISP's) network, + but pdnsd is slow and DNS queries frequently time out. +
A: + In some cases pdnsd will not consider the answer of the local name server + authoritative enough, and will try to get answers from the name servers listed in the + authority section of the reply message. If pdnsd is behind a firewall that blocks the + UDP reply packets from remote name servers, pdnsd will wait in vain for a reply. + One solution is to set proxy_only=on + in the servers sections of the configuration file. + This will prevent pdnsd from querying name servers that are not listed in the configuration + file. + Another solution that can be tried is specifying + query_method=tcp_only + in the global section of the configuration file, because a firewall that blocks + UDP packets from outside might still allow outgoing TCP connections to port 53. +
+
+ + + + + + + + + + +
Q: + Is pdnsd vulnerable to DNS cache poisoning as described in + CERT vulnerability note VU#800113? +
A: + Short answer: Yes.
+ Somewhat longer answer: The problem is not so much that pdnsd's implementation is flawed + but rather that the DNS protocol currently being used is fundamentally flawed from + a security viewpoint. As long as a more secure protocol is not in place, + all that the developers of pdnsd can do is to try to tweak the current implementation + to make it as difficult as possible for an attacker to succeed.
+ From version 1.2.7 onwards, the default for the query_port_start option + is 1024, which means that the pdnsd resolver will randomly select source ports + in the range 1024-65535. (In previous versions the default was to let the kernel select + the source ports, which will often result in a more or less predictable sequence of ports.) + It also helps to use a good quality source of random numbers. On platforms where this is + supported, it is preferable to configure with --with-random-device=/dev/urandom. + There is still more that can be done to make pdnsd less vulnerable, but this remains + (as of this writing) a work in progress. +
+ Please note that pdnsd was designed for small (private) networks, and that it is generally + not recommended to let untrusted users access pdnsd. +
+ +
+
Thomas Moestl + and Paul Rombouts +
+
+

+ Last revised: 18 August 2008 by Paul Rombouts +

+ + + diff --git a/jni/pdnsd/doc/html/htmlsubst.pl b/jni/pdnsd/doc/html/htmlsubst.pl new file mode 100644 index 00000000..a9e3e9ff --- /dev/null +++ b/jni/pdnsd/doc/html/htmlsubst.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl -w + +# Primitive ad-hoc script for updating pdnsd html doc files. +# Written by Paul Rombouts. + +use strict; +use integer; +use POSIX qw(strftime); + +my %paramvals=(); + +while(@ARGV && $ARGV[0]=~/^([^=]*)=(.*)$/) { + my $param=$1; my $val=$2; + if($param =~ /^[[:alpha:]]\w*$/) { + $paramvals{$param}=$val; + } + else {warn "Warning: invalid parameter '$param' ignored.\n"} + shift @ARGV; +} + +sub sizeof { + my($arg)=@_; + (my $str= $arg) =~ s/\$(?:([[:alpha:]]\w*)\b|\{([[:alpha:]]\w*)\})/ + defined($paramvals{$+})?$paramvals{$+}:defined($ENV{$+})?$ENV{$+}:''/eg; + my $filename=eval($str); + (-f $filename) or return '???'; + (((-s $filename)+1023)/1024).'kB'; +} + +while(<>) { + s/\$(?:date\b|\{date\})/strftime("%d %b %Y",localtime)/eg; + s/\$sizeof\(([^()]*)\)/sizeof($1)/eg; + s/\$(?:([[:alpha:]]\w*)\b|\{([[:alpha:]]\w*)\})/ + defined($paramvals{$+})?$paramvals{$+}:defined($ENV{$+})?$ENV{$+}:''/eg; + print; +} diff --git a/jni/pdnsd/doc/html/index.html b/jni/pdnsd/doc/html/index.html new file mode 100644 index 00000000..d2e426aa --- /dev/null +++ b/jni/pdnsd/doc/html/index.html @@ -0,0 +1,686 @@ + + + + pdnsd homepage + + + + + + + + + + + + + + + +
+ About pdnsd + + pdnsd FAQ + + Documentation + + GNU GPL (pdnsd's License) + + Download Section +
+

The pdnsd Homepage

+

News

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
2012-03-17Version 1.2.9a-par has been released. + Version 1.2.9a fixes a bug in the 1.2.9 release that causes a build failure when pdnsd is + configured with --enable-strict-rfc2181. + If you do not use this option to compile pdnsd, there is no need to upgrade from 1.2.9 to 1.2.9a. +
2012-02-27Version 1.2.9-par has been released. + Version 1.2.9 supports many more RR types (including those necessary for DNSSEC) and + EDNS (Extension mechanisms for DNS) to enable UDP messages larger than 512 bytes. + It also has support for defining local TXT records and has several new options and bugfixes + (including file descriptor leaks that effect FreeBSD users). +
2011-05-03The latest source code is available from a + git repository.
+ In response to frequent requests I have uploaded a git tree including the latest code + and a fairly extensive history of pdnsd development to + gitorious.org. + Anyone who wants to participate in pdnsd development is free to create a + clone repo on gitorious.org + and push his modifications there. +
2010-02-22Version 1.2.8-par has been released. + The main new feature of version 1.2.8 is automatic discovery of root servers. + Furthermore, there are some additional improvements in the resolver. +
2008-09-04Version 1.2.7-par has been released. + Foremost, this release fixes some security problems. + It contains a fix for a "dangling pointer" bug that could cause pdnsd to + crash when it received a long reply. It also addresses some of the issues + raised in the CERT + vulnerability note VU#800113 by making the default of + query_port_start equal to 1024, thereby ensuring that source + ports are randomly selected by the pdnsd resolver in the range 1024-65535. + This release also fixes problems with compiling pdnsd for the ARM architecture + and for the Darwin platform (Max OS X). +
+ There are a number of (minor) new features. + pdnsd now supports "include" files, essentially configuration files that + only contain definitions for local records. + It is now possible to define interactively, using pdnsd-ctl, + any local record that can be defined in a configuration file. +
2007-09-04Version 1.2.6-par has been released. + pdnsd's license has been upgraded to GPL version 3. + A bug has been fixed which which caused pdnsd to handle NXDOMAIN replies + inefficiently when configured with neg_domain_pol=on. The + code that implements the ping test has been fixed, which was broken for + 64-bit systems. A new option randomize_servers can be used + to give each server in a section of the configuration file an equal + chance of being queried. The new options reject, + reject_policy and reject_recursively make it + possible to check for the presence of certain IP addresses in the + replies of name servers and to avoid some types of unwanted replies. + The pdnsd-ctl 'add a' and 'add aaaa' commands + now allow multiple IP addresses to be specified for the same name. + pdnsd's ability to resolve from root servers has been improved. +
2006-09-02Version 1.2.5-par has been released. + This release introduces a new query method: udp_tcp. + With this method a UDP query is tried first and, if the UDP answer is + truncated, the query is repeated using TCP, which is the behaviour that + seems to be recommended by the DNS standards. There is a new + configuration option use_nss, which can be turned off to + prevent lengthy timeouts and stalls in certain situations. A bug has + been fixed which could cause pdnsd to crash if debug output was + generated before the debug output stream was properly initialized. +
2006-01-09Version 1.2.4-par has been released. + A memory leak and a minor buffer-overflow problem have been fixed. + There is now a fix for some situations that would previously cause pdnsd to + exit prematurely (such as ACPI S3 sleep or trying to attach strace to pdnsd). + Time intervals specified in the configuration file can now be expressed in + minutes, hours, days and weeks as well as seconds. + Support for Apple Mac OS X v10.4 Tiger has been improved. + The "pdnsd-ctl status" command now also provides some + information about the status of the running threads. + There are some further improvements in the debugging information provided by pdnsd.
+ TCP-query support is now compiled in by default (but can still be disabled using + the configure option --disable-tcp-queries). +
2005-07-11Version 1.2.3-par has been released. + New feature in this release: the "pdnsd-ctl empty-cache" command can + be provided with an include/exclude list, allowing the user to specify a + selection of names to be removed, instead of emptying the cache completely.
+ Additional improvements: pdnsd should now remain responsive while executing the + "pdnsd-ctl empty-cache" command. + With the query_method=tcp_udp option pdnsd will now also + try a UDP query after a TCP connection times out, which should allow + pdnsd to resolve the same names with query_method=tcp_udp + as with query_method=udp_only, although perhaps with an + occasional delay. + "pdnsd-ctl config" or "pdnsd-ctl server" + commands should now run without delays, even if pdnsd is performing + ping or query uptests at the time. + Some problems with resolving certain names using root servers have been fixed. +
2005-04-03Version 1.2.2-par has been released. + The main emphasis of this release is improved portability. + A bug has been fixed that prevented pdnsd from compiling successfully on some + 64 bit architectures. + This release has (experimental) support for the Darwin (Apple Mac OS X) platform. + On Linux systems, the configure script will now try to detect automatically whether + the system implements the Native POSIX Thread Library, but the method used may not + necessarily be foolproof. + In addition, the debug features have been improved and should make it easier to find out + why pdnsd considers some queries or replies malformed. +
2004-11-07Version 1.2.1-par has been released. + The main new feature of this release is improved support for non-Linux platforms.
+ This release has (experimental) support for the Cygwin platform, and should also fix + some compilation glitches that have been reported by FreeBSD users. +
2004-10-10Version 1.2-par has been released. + pdnsd is new and improved! Most of the changes effect the internal workings + of pdnsd, but there also a number of interesting new features (well, I think they are interesting).
+ Among the bugs fixed are two rather nasty ones which involve the handling of NXT and NAPTR records + and which can cause pdnsd to crash or abort.
+ The new features include a new server availability test which can be specified with uptest=query, + support for reading the DNS configuration from resolv.conf files, + a new option for optimizing the use of root servers, + a new option that makes defining local records for reverse resolving easier, + support for defining wildcard records, + a new pdnsd-ctl command for reloading the config file without restarting pdnsd, and + a new pdnsd-ctl command for dumping information about the names stored in the cache. + The documentation has also been updated: there is now a pdnsd.conf man page.
+ For a more complete list of the changes I'll have to refer you to README.par and the ChangeLog. +
2004-05-22Version 1.1.11a-par has been released. + This release contains a fix for FreeBSD users that bypasses a problem + with the macro ENONET, which can cause a compilation failure when it is undefined. + Linux users will notice no difference between 1.1.11a-par and 1.1.11-par. +
2004-05-10Version 1.1.11-par has been released. + This version has a rather large number of small changes, which are rather difficult to summarize. + Among the bugs fixed are a race condition in the cache lookup code, a + flaw in the code that caused a busy spin when a remote server answered + with "Not Implemented", and problems with the -4 and -6 command-line + options. Among the improvements are an alternative sorting algorithm + which should allow pdnsd to start up faster when reading a large cache + file from disk, automatic mapping of IPv4 to IPv6 addresses when running + in IPv6 mode, somewhat more efficient memory use, better compression of + the replies and changes in the parallel querying algorithm that should + improve the chances of catching a reply from a remote server.
+ + For a more complete list of the changes I'll have to refer you to README.par and the ChangeLog. +
2004-02-10Version 1.1.10-par has been released. + + The main new feature of this release is a new parser for configuration + files, completely rewritten from scratch in C. The main advantages are: + (f)lex and yacc/bison are no longer needed to build pdnsd, more + informative error messages instead of merely "parse error", + and string literals no longer need to be enclosed in quotes in most + cases.
Furthermore, a bug has been fixed that caused incorrect + IPV6-type PTR records to be generated when sourcing + /etc/hosts like files.
+ + There have been other small changes, more details can be found in the ChangeLog. +
2004-01-08Version 1.1.9-par has been released. + "maintenance" release by Paul Rombouts.
+ + The change of version number is not very significant; the + difference between 1.1.9-par and the previous 1.1.8b1-par8 is marginal. + However, I felt the need to simplify the numbering, because it was + becoming rather baroque.
+ + I've added some missing pieces to the documentation (the pdnsd manual and the man page for pdnsd-ctl). BTW, did you + know that it's possible to define aliases for domain names with pdnsd? I + had plans to implement such a feature when I discovered that pdnsd + already supports it. It was just poorly documented. (If want to try this + for your self, look for the new information about CNAME records under + the rr Section in the manual.)
The + changes to the code consist mostly of optimizations, removal of some + size limits due to fixed-size buffers, and some cleaning up. I've also + tried to make the error responses of pdnsd-ctl more helpful.
+ + More details can be found in the ChangeLog. +
2003-10-10Version 1.1.8b1-par8 has been released. + "maintenance" release by Paul Rombouts.
+ This version introduces a "delegation-only" feature that may be useful + for blocking Verisign's Sitefinder.
+ The parser for the configuration file now tolerates domain names missing + a dot at the end.
+ I have provided alternative implementations for some GNU extensions that I + used in an effort to make the code more portable. In particular, the + code should build on FreeBSD again.
+ More details can be found in the README.par file. +
2003-09-19Version 1.1.8b1-par7 has been released. + "maintenance" release by Paul Rombouts. Besides fixing a number of bugs I have + reworked some of the code for adding and removing entries in the cache in an + effort to improve efficiency and stability.
+ More details can be found in the ChangeLog. +
2003-07-28Version 1.1.8b1-par6 has been released. + "maintenance" release by Paul Rombouts. In addition to some further code cleanup, + the documentation has been revised. +
2003-07-10Version 1.1.8b1-par5 has been released. + A troublesome allocation size error has been discovered in Thomas Moestl's code. + In practice this bug only wastes memory but it could + also potentially lead to memory corruption. Upgrading is recommended. + More details can be found in the ChangeLog. +
2003-06-30Version 1.1.8b1-par4 has been released. + Due to incompatibilities between various implementations of + the pthread library on Linux systems, problems can occur with signal handling in + pdnsd. The usual symptom is failure by pdnsd to save the cache to disk, and + /var/cache/pdnsd/pdnsd.cache remaining empty. If you experience + this kind of trouble, try reconfiguring with different values for the new + --with-thread-lib option. The allowable values are + described in the documentation. +
2003-04-07pdnsd is no longer maintained by Thomas Moestl: + I have not had time to maintain pdnsd for quite a while now, and have been very slow to + respond to issues, or did not respond at all. It is time that I officially announce that + pdnsd is no longer actively maintained; I apologize to all those who reported bugs or + asked questions without receiving any reply. However, Paul A. Rombouts has published + a patch set against the last released version at + http://members.home.nl/p.a.rombouts/pdnsd.html, + which cleans up a lot of code fixes many bugs. +
2002-07-19Documentation update. + Please note that pdnsd should never be installed with setuid or setgid attributes, + as it is not always possible to give up all privileges due to operating system restrictions. + While this was never intended and I don't think that anybody would actually do this, the + documentation was updated to explicitely mention this to avoid misunderstandings. +
2002-01-15Version 1.1.7a has been released. + This fixes a reversed test in an assertion that would cause pdnsd to termintate when the ping uptest + was used. No other changes were made. +
2002-01-15Version 1.1.7 has been released. + This fixes some problems that might be remotely exploitable to gain access as the user pdnsd runs as + (an unprivileged user by default). To do this, an attacker needs to control a name server that is + queried by pdnsd, and send a malicious reply to such a query.
+ Upgrading is strongly recommended!
+ There are also minor bug fixes and stability improvements. +
+ +
+

About pdnsd

+ pdnsd is a proxy DNS server with permanent caching (the cache contents + are written to hard disk on exit) that is designed to cope with unreachable + or down DNS servers (for example in dial-in networking).
+ Since version 1.1.0, pdnsd supports negative caching.
+
+ It is licensed under the GNU General Public License (GPL, + also available in html and + translated into various languages.). + This, in short, means that the sources are distributed togehter with the program, and + that you are free to modify the sources and redistribute them as long as you + also license them under the GPL. You do not need to pay anything for pdnsd. + It also means that there is ABSOLUTELY NO WARRANTY for pdnsd or any part + of it. For details, please read the GPL. +

+ pdnsd can be used with applications that do DNS lookups, e.g. on startup, and + can't be configured to change that behaviour, to prevent the often minute-long + hangs (or even crashes) that result from stalled DNS queries. Some Netscape Navigator + versions for Unix, for example, expose this behaviour. +

+ pdnsd is configurable via a file and supports run-time configuration using the program pdnsd-ctl that comes + with pdnsd. This allows you to set the status flags of servers that pdnsd knows (to influence which servers + pdnsd will query), and the addition, deletion and invalidation of DNS records in pdnsd's cache. +
+ Parallel name server queries are supported. This is a technique that allows + querying several servers at the same time so that very slow or unavailable + servers will not block the answer for one timeout interval. +
+ Since version 1.0.0, pdnsd has full IPv6 support. +

+ There is also a limited support for local zone records, intended for defining + 1.0.0.127.in-addr.arpa. and localhost. , since some clients request that + information and it must be served even if the cached servers are not available + or do not serve these records. pdnsd may also read your /etc/hosts file + (this file is normally used by your local resolver and usually contains + information for localhost as well as for your machines FQDN) and serve its + contents. +

+ pdnsd was started on Linux, and has since been ported to FreeBSD (and Cygwin and Darwin). + 90% of the source code should be easily portable to POSIX- + and BSD-compatible systems, provided that those systems support the POSIX threads (pthreads). + The rest might need OS-specific rewrites. +

+ Currently, pdnsd is only compileable by gcc. This should be easy to fix, but I just + do not have documentation for other compilers. If you are not able or do not want + to use gcc, I would recommend you just try to do the minor changes. +

+

+ pdnsd must be started as root in some cases (raw sockets are needed for icmp + echoes for the option uptest=ping, and the default port is 53, this must be + >1024 to allow non-root execution). However, pdnsd can be configured to change it's user + and group id to those of a non-privileged user after opening the sockets needed for this. +

+ The server should support the full standard DNS queries following the rfcs 1034 + and 1035. As of version 1.0.0, the rfc compliance has been improved again, and pdnsd is now + believed (or hoped?) to be fully rfc-compatible. It completely follows rfc 2181 (except + for one minor issue in the FreeBSD port, see the documentation). + It does not support the + following features, of which most are marked optional, experimental or obsolete + in these rfcs: +

+
    +
  • Inverse queries +
  • Status queries +
  • Completion queries +
  • Namespaces other than IN (Internet) +
  • AXFR and IXFR queries (whole zone transfers); since pdnsd does not maintain zones, that should not violate the standard +
+ The following record types, that are extensions to the original DNS standard, are supported for caching since version 1.2.9 + (if you do not need most of them, you can disable runtime support for the unneeded ones before compiling pdnsd and save a little cache and executable space, see the source file src/rr_types.in): +
    +
  • RP (responsible person, RFC 1183) +
  • AFSDB (AFS database location, RFC 1183) +
  • X25 (X25 address, RFC 1183) +
  • ISDN (ISDN number/address, RFC 1183) +
  • RT (route through, RFC 1183) +
  • NSAP (Network Service Access Protocol address , RFC 1348) +
  • PX (X.400/RFC822 mapping information, RFC 1995) +
  • GPOS (geographic position, deprecated) +
  • AAAA (IPv6 address, RFC 1886) +
  • LOC (location, RFC 1876) +
  • EID (Nimrod EID) +
  • NIMLOC (Nimrod locator) +
  • SRV (service record, RFC 2782) +
  • ATMA (ATM address) +
  • NAPTR (URI mapping, RFC 2168) +
  • KX (key exchange, RFC 2230) +
  • CERT (Certificate record, RFC 4398) +
  • DS (Delegation Signer, RFC 4034) +
  • RRSIG (Resource Record Signature, RFC 4034) +
  • NSEC (Next Secure, RFC 4034) +
  • DNSKEY (record containing the public key for a zone, RFC 4034) +
  • NSEC3 (Next Secure version 3, RFC 5155) +
  • NSEC3PARAM (NSEC3 parameters, RFC 5155) +
+

+ Note: This list is incomplete. For the complete list see the source file src/rr_types.in. +

+ There are FreeBSD and OpenBSD ports available for pdnsd (ports/net/pdnsd for both). + Thanks go to Roman Shterenzon for the FreeBSD port Sebastian Stark for the OpenBSD one! + Thanks to Kiyo Kelvin Lee now also runs on the Cygwin platform! + Thanks goes to Rodney Brown for extending portability to the Darwin (Apple Mac OS X) platform! +

+ If you have questions left, you should take a look into the FAQ. +
+ Bugfixes, patches and compatability fixes for other OSs are very welcome! +

+

Features in detail

+

+ This section describes some of pdnsds features in detail. Most of the options are set + in the config file. For more information on the configuration file, see + the documenation page. +


+ +

Uptests

+ pdnsd provides several methods to test whether a remote DNS server should be regarded as available + (so that pdnsd can query it), in + addition to the obvious "none" test (the server is always regarded as available, + or availability is set on or off using the pdnsd-ctl utility). + These tests are: +
    +
  • ping: a given adress is ping'ed in a given interval. If it there is no response + or the host is unreachable, the server is seen to be not available (for those who don't know: + pinging is sending a certain Internet packet type to a host to which any standard-conformant + host is required to reply). +
  • if: a given network interface is tested whether it is existent, up and running. If + it is not, the server is regarded to be not available. This is especially useful for ppp and + similar interfaces. A special case test for Linux isdn (ippp*) interfaces is integrated, so that the uptests + should also work for these. +
  • dev: this is a variant of the if uptest for use with Linux dial-on-demand ppp interfaces. In addition + to performing an if-style interface uptest, it also tests whether a specified program (e.g. pppd) owns + a lock to a given (modem-) device. +
  • exec: a given shell command line is executed and the exit status of the whole command line (which + is normally the exit status of the last command) is evaluated. If it is not zero, the server is regarded + to be not available. This is a very flexible testing method with which it should be able to perform + virtually any needed test. +
  • query: New in version 1.2: + This works like the ping test, except it sends an (empty) DNS query to the remote server. + If the server sends a well-formed response back within the timeout period (except SERVFAIL), + it will be regarded as available. + This test is useful if a remote server does not respond to ICMP_ECHO requests at all, + which unfortunately is quite common these days. + In many cases this test will be a more reliable indicator of availability + than the ones mentioned above. +
+
+

Local Records ("Zones")

+ As mentioned above, there are only very basic local record types (ie the record types that you may use in record + declarations in your local configuration for records that pdnsd shall serve in addion to the cached ones). + They are organized roughly in zones but have not complete zone declarations, so I generally do not use the + term "zone" for them, but rather "local records". + These are the local record types pdnsd can understand: +
    +
  • SOA (information about the name server) +
  • A (domain-name-to-address mapping) +
  • PTR (pointer, used normally for address-to-domain-name mapping) +
  • NS (name server, generated automatically by pdnsd for any local record set) +
  • CNAME (canonical host name) +
  • MX (mail exchange for the domain) +
  • TXT (arbitrary text strings, often used for Sender Policy Framework) +
+ You can specify these records in the configuration file.
+ You may "source" a file in a format like that used in the /etc/hosts file, that means + that pdnsd reads this file, extracts addresses and domain names from it and automatically generates + A records for name to address mapping, PTR records for address to name mapping and NS records (name + server specifiation) for each entry in the file.
+ Records can also be changed dynamically at run time.
+ A script contributed by Marko Stolle makes pdnsd usable in a DHCP setup using this feature. +
+

System requirements

+ As mentioned, pdnsd currently runs under Linux, FreeBSD and Cygwin. + Other BSD flavours may or may not work (feedback is very welcome!). + The system and software requirements under Linux are: +
    +
  • Kernel version >2.2.0 +
  • glibc version >2.0.1 (aka libc6) with LinuxThreads (normally included) + or NPTL (Native Posix Thread Library, recommended).
    + Due to a bug, pdnsd 0.9.8 does not run with glibc2.1.1. This behaviour was + fixed in pdnsd 0.9.9. +
  • For IPv6: glibc>=2.1 +
+ The system requirements under FreeBSD are: +
    +
  • FreeBSD versions >=2.6 (prior ones may or may not work) +
  • For IPv6: FreeBSD >=4.0 is recommended (no idea if it runs on prior versions) +
+ + The common software requirements for all supported systems are: +
    +
  • GCC, preferably egcs-2.* or 3.* (other compilers are currently not supported; the needed patch for another compiler + should not be difficult, however) +
  • GNU or BSD make +
  • the standard commands install, grep, sed, awk, touch and which (along with the REALLY + standard ones mv, cp, ln, rm, pwd, test, echo, cat, mkdir, chown, chmod, tar). In + any standard Unix installation, this should be no problem. +
  • for hacking and building own packages, you might also need gzip, bzip2, perl and rpmbuild +
+
+

Download

+ If you want to download pdnsd, please visit the download page. +
+

Authors

+

+ pdnsd was originally written by Thomas Moestl, + but is no longer maintained by him. Paul A. Rombouts + has revised large portions of the code and has added a number of new features. + See README.par and the ChangeLog + in the source directory (or /usr/share/doc/pdnsd-<version> + if you have installed a binary package) for more details. + If you have questions about the recent modifications, you can find + the email address of the current maintainer + at the end of README.par. +

+

+ Daniel Smolik has contributed RedHat RPMs (the most recent RPMs are available here).
+ Torben Janssen contributed start scripts for Red Hat Linux.
+ Soenke J. Peters contributed patches and suggestions for Red Hat compatability.
+ Wolfgang Ocker has contributed the code and documentation for the server_ip option.
+ Markus Mohr contributed a Debian rc script.
+ Nikita V. Youschenko contributed extensions to the "if" uptest.
+ Lyonel Vincent extended the serve_aliases option to support an arbitrary number of aliases.
+ Sourav K. Mandal wrote the autoconf scripts and contributed many fixes and suggestions.
+ Stephan Boettcher contributed the SCHEME= option.
+ Ron Yorston contributed the uptest for Linux ppp dial-on-demand devices.
+ Alexandre Nunes fixed some bugs in the autoconf files.
+ Sverker Wiberg contributed fixes for IPv6.
+ Carsten Block contributed configure-able rc scripts.
+ Olaf Kirch contributed a security fix for the run_as code.
+ Paul Wagland contributed various patches for bind9-compatability and other issues.
+ Roman Shterenzon contributed patches and lots of helpful hints for FreeBSD compatability.
+ Bernd Leibing has contributed spec file fixes.
+ Michael Wiedmann has contributed the pdnsd-ctl.8 man page.
+ Marko Stolle has contributed the contrib/pdnsd_update.pl script that makes pdnsd usable in a DHCP setup.
+ P.J. Bostley has contributed patches to get pdnsd working on alpha properly.
+ Christian Engstler contributed patches for SuSE compatability.
+ Bjoern Fischer contributed code to make pdnsd leave the case of names in the cache unchanged.
+ Marko Stolle contributed the contrib/pdnsd_update.pl script that makes pdnsd usable in a DHCP setup.
+ Andrew M. Bishop contributed the support for the label server option and the pdnsd-ctl interface for using it.
+ Frank Elsner contributed rc script fixes.
+ Andreas Steinmetz contributed the code for query_port_start and query_port_end options.
+ Mahesh T. Pai contributed the pdnsd.8 man page.
+ Nikola Kotur contributed the Slackware start-up script.
+ Kiyo Kelvin Lee contributed a patch for Cygwin support.
+ Rodney Brown contributed a patch for Darwin (Apple Mac OS X) support.
+ Jan-Marek Glogowski contributed a patch implementing the use_nss option. +

+

+ Special thanks to Bert Frederiks for letting me do a late-night debugging run on his machine to + spot obscure bugs! +

+

+ Thanks to the following persons for reporting bugs and being helpful:
+ David G. Andersen,
+ Dirk Armbrust,
+ Daniel Black,
+ Kevin A. Burton,
+ Juliusz Chroboczek,
+ Joachim Dorner,
+ Stefan Erhardt,
+ Stefan Förster,
+ Mike Hammer,
+ Jonathan Hudson,
+ Dan Jacobson,
+ Byrial Jensen,
+ Patrick Loschmidt,
+ James MacLean,
+ Fraser McCrossan,
+ Michael Müller,
+ Erich Reitz,
+ Brian Schroeder,
+ Milan P. Stanic,
+ Michael Steiner,
+ Norbert Steinl,
+ Markus Storm,
+ Michael Ströder,
+ Alan Swanson,
+ Eelco Vriezekolk. +

+ +

Links

+ Well, this is the obligatory link section. +
+
+ + + + + + + + +
+ + http://www.gnu.org
+ The GNU homepage +
+
+ + http://freecode.com
+ Freecode (formerly Freshmeat) - large free software index +
+
+ + http://www.freebsd.org
+ The FreeBSD project +
+
+ +
+
+
Thomas Moestl + and Paul A. Rombouts +
+
+

+ Last revised: 17 March 2012 by Paul A. Rombouts +

+ + diff --git a/jni/pdnsd/doc/html2confman.pl b/jni/pdnsd/doc/html2confman.pl new file mode 100644 index 00000000..abade119 --- /dev/null +++ b/jni/pdnsd/doc/html2confman.pl @@ -0,0 +1,161 @@ +#!/usr/bin/perl -w +# +# A Perl script for converting pdnsd html documentation to a man page. +# +# Written by Paul A. Rombouts +# +# This file Copyright 2004 Paul A. Rombouts +# It may be distributed under the GNU Public License, version 2, or +# any higher version. See section COPYING of the GNU Public license +# for conditions under which this file may be redistributed. +# + +use strict; +use POSIX qw(strftime); + + +while(<>) { + if(/[^<]*configuration file/i) { + last; + } +} + +exit unless defined($_); + +while(<>) { + if(/[^<]*layout/i) { + last; + } +} + +exit unless defined($_); + +(my $myname=$0) =~ s{.*/}{}; + +print <) { + if(/.*\bpdnsd-ctl\b/) { + last; + } + s{^\s*((?:<[^<>]+>)*?)[\d.]*\s*(.*)((?:<[^<>]+>)*?)(?:
)?\s*$}{.SS $1$2$3\n}i; + if(s{^\s*\s*}{.TP\n}i) {$taggedparagraph=1} + if(m{^\s*}i) {$taggedparagraph=0} + s{^\s*((?:<[^<>]+>)*?)(.*)((?:<[^<>]+>)*?)(?:
)?\s*$}{.B $1$2$3\n}i if $taggedparagraph; + s{^\s*((?:<[^<>]+>)*?or(?:<[^<>]+>)*?)(?:
)?\s*$}{$1\n.PD 0\n.TP\n.PD\n}i if $taggedparagraph; + if(s{^\s*
}{.DS L\n}i) {$displayed=1}
+    s{^\t}{        } if $displayed;
+    if(s{
\s*$}{\n.DE\n\n}i) {$displayed=0} + elsif(!$displayed) {s{^\s*}{}} + s{^\s*
  • }{.IP\n\\(bu }i; + s{
  • }{\n.IP\n\\(bu }i; + s{
      }{\n}i; + s{
    }{\n}i; + s{}{\\fB}ig; + s{}{\\fP}ig; + s{<(i|em)>}{\\fI}ig; + s{}{\\fP}ig; + unless(s{^\s*(<[^<>]+>)*(
    |

    )(<[^<>]+>)*\s*$}{\n}i) { + s{]*>(.*)

    }{\n$1\n}i; + s{^\s*
    }{.br\n}i; + s{
    \s*
    \s*$}{\n\n}i; + s{
    \s*$}{\n.br\n}i; + s{
    }{\n.br\n}i; + s{^\s*(<[^<>]+>)*\s*$}{}; + } + s{<[^<>]+>}{}g; + s{<}{<}ig; + s{>}{>}ig; + s{"}{"}ig; + s{ }{\\ }ig; + s{/var/cache/pdnsd\b}{\@cachedir\@}g; + s{(? +.UE +and was extensively revised by Paul A. Rombouts +.UR + +.UE +(for versions 1.1.8b1\\-par and later). +.PP +Several others have contributed to \\fBpdnsd\\fP; see files in the source or +\\fB/usr/share/doc/pdnsd/\\fP directory. +.PP +This man page was automatically generated from the html documentation for \\fBpdnsd\\fP, +using a customized Perl script written by Paul A. Rombouts. +ENDOFTRAILER + +if(defined($_)) { + while(<>) { + if(/last\s+revised/i) { + s{^\s*}{}; + s{<[^<>]+>}{}g; + s{<}{<}ig; + s{>}{>}ig; + s{"}{"}ig; + s{ }{\\ }ig; + print ".PP\n"; + print; + last; + } + } +} +exit; diff --git a/jni/pdnsd/doc/pdnsd-ctl.8 b/jni/pdnsd/doc/pdnsd-ctl.8 new file mode 100644 index 00000000..73459f3b --- /dev/null +++ b/jni/pdnsd/doc/pdnsd-ctl.8 @@ -0,0 +1,198 @@ +.\" This manpage has been automatically generated by docbook2man-spec +.\" from a DocBook document. docbook2man-spec can be found at: +.\" +.\" Please send any bug reports, improvements, comments, patches, +.\" etc. to Steve Cheng . +.\" This manpage has been edited manually by Paul A. Rombouts. +.TH "PDNSD\-CTL" "8" "Sep 2008" "pdnsd 1.2.9b-par" "" +.SH NAME +\fBpdnsd\-ctl\fP \- controls pdnsd +.SH SYNOPSIS +.sp +\fBpdnsd\-ctl\fP [\fB\-c\fP \fIcachedir\fP] [\fB\-q\fP] \fIcommand\fP [\fIarguments\fP] +.SH "DESCRIPTION" +.PP +\fBpdnsd\-ctl\fP controls \fBpdnsd\fP, a proxy dns server with permanent caching. +Note that the status control socket must be enabled (by specifying an option on +the pdnsd command line or in the configuration file) before you can use +\fBpdnsd\-ctl\fP. +.PP +.TP +\fB\-c\fP \fIcachedir\fP +Set the cache directory to \fIcachedir\fP (must match pdnsd setting). +This is only necessary if the directory differs from the default specified +at compile time. +.TP +\fB\-q\fP +Be quiet unless output is specified by the command or something goes wrong. +.SH "COMMANDS" +.TP +\fBhelp\fP\ \ \ [no arguments] + +Print a command summary. +.TP +\fBversion\fP\ [no arguments] + +Print version and license info. +.TP +\fBstatus\fP\ [no arguments] + +Print a description of pdnsd's cache status, thread status and configuration. +Also shows which remote name servers are assumed to be available. +.TP +\fBserver\fP\ (\fIindex\fP|\fIlabel\fP) (\fBup\fP|\fBdown\fP|\fBretest\fP) [\fIdns1\fP[,\fIdns2\fP[,...]]] + +Set the status of the servers with the given index or label to up or down, or +force a retest. The index is assigned in the order of definition in pdnsd.conf +starting with 0. Use the status command to view the indexes. You can specify all +instead of an index to perform the action for all servers registered with pdnsd. +.IP +An optional third argument can be given consisting of a list of IP addresses +separated by commas or white-space characters. This list will replace the +addresses of name servers used by pdnsd for the given server section. This +feature is useful for run-time configuration of pdnsd with dynamic DNS data in +scripts called by ppp or DHCP clients. The last argument may also be an empty +string, which causes existing IP addresses to be removed and the corresponding +server section to become inactive. +.TP +\fBrecord\fP\ \fIname\fP (\fBdelete\fP|\fBinvalidate\fP) + +Delete or invalidate the records of the given domain name if it is in the cache. +Invalidation means that the records are marked as timed out, and will be +reloaded if possible. For local records (i.e., records that were given in the +config file using a rr section, records read from a hosts-style file and records +added using pdnsd-ctl), invalidation has no effect. Deletion will work, though. +.TP +\fBsource\fP\ \fIfn\fP \fIowner\fP [\fIttl\fP] [(\fBon\fP|\fBoff\fP)] [\fBnoauth\fP] + +Load a hosts-style file. Works like using the pdnsd source configuration section. +Owner and ttl are used as in the source section. ttl has a default +of 900 (it does not need to be specified). The next to last argument corresponds +to the serve_aliases option, and is off by default. +\fBnoauth\fP is used to make the domains non-authoritative +(this is similar to setting authrec=off in the config file, +please consult the +.BR pdnsd.conf (5) +man page for what that means). +fn is the name of the file, which must be readable by pdnsd. +.TP +\fBadd\fP\ \ \ \ \fBa\fP \fIaddr\fP \fIname\fP [\fIttl\fP] [\fBnoauth\fP] +.TP +\fBadd\fP\ \ \ \ \fBaaaa\fP \fIaddr\fP \fIname\fP [\fIttl\fP] [\fBnoauth\fP] +.TP +\fBadd\fP\ \ \ \ \fBptr\fP \fIhost\fP \fIname\fP [\fIttl\fP] [\fBnoauth\fP] +.TP +\fBadd\fP\ \ \ \ \fBcname\fP \fIhost\fP \fIname\fP [\fIttl\fP] [\fBnoauth\fP] +.TP +\fBadd\fP\ \ \ \ \fBmx\fP \fIhost\fP \fIname\fP \fIpref\fP [\fIttl\fP] [\fBnoauth\fP] + +Add a record of the given type to the pdnsd cache, replacing existing +records for the same name and type. The 2nd argument corresponds +to the value of the option in the rr section that is named like +the first argument. The addr argument may be a list of IP addresses, +separated by commas or white space. +The ttl is optional, the default is 900 seconds. +\fBnoauth\fP is used to make the domains non-authoritative +(this is similar to setting authrec=off in the config file, +please consult the +.BR pdnsd.conf (5) +man page for what that means). +If you want no other record than the newly added in the cache, do +\fBpdnsd\-ctl\fP\ \fBrecord\fP\ \fIname\fP\ \fBdelete\fP +before adding records. +.TP +\fBneg\fP\ \ \ \ \fIname\fP [\fItype\fP] [\fIttl\fP] + +Add a negatively cached record to pdnsd's cache, replacing existing +records for the same name and type. If no type is given, the whole +domain is cached negatively. For negatively cached records, errors are +immediately returned on a query, without querying other servers first. +The ttl is optional, the default is 900 seconds. +.TP +\fBconfig\fP\ \fIfilename\fP + +Reload pdnsd's configuration file. +.br +The config file must be owned by the uid that pdnsd had when it was started, +and be readable by pdnsd's run_as uid. +If no file name is specified, the config file used at start-up is reloaded. +Note that some configuration changes, like the port or IP address pdnsd listens on, +cannot be made this way and you will receive an error message. +In these cases, you will have to restart pdnsd instead. +.TP +\fBinclude\fP\ \fIfilename\fP + +Parse an include file. +.br +The include file may contain the same +type of sections as a config file, expect for global and server +sections, which are not allowed. This command can be used to add data +to the cache without reconfiguring pdnsd. +.TP +\fBeval\fP\ \ \ \fIstring\fP + +Parse a string as if part of an include file. +.br +The string should hold one or more complete configuration sections, +but no global and server sections, which are not allowed. +If multiple strings are given, they will be joined using newline chars +and parsed together. +.TP +\fBempty\-cache\fP\ [[+|-]\fIname\fP ...] + +Delete all entries in the cache matching include/exclude rules. +.br +If no arguments are provided, the cache is completely emptied, +freeing all existing entries. +Note that this also removes local records, as defined by the config file. +To restore local records, run "pdnsd-ctl\ config" immediately afterwards. +.br +If one or more arguments are provided, these are interpreted as +include/exclude names. If an argument starts with a '+' the name is to +be included. If an argument starts with a '-' it is to be excluded. +If an argument does not begin with '+' or '-', a '+' is assumed. +If the domain name of a cache entry ends in one of the names in the +list, the first match will determine what happens. If the matching name +is to be included, the cache entry is deleted, otherwise it remains. +If there are no matches, the default action is not to delete. +.TP +\fBdump\fP\ \ \ [\fIname\fP] + +Print information stored in the cache about \fIname\fP. +If \fIname\fP begins with a dot and is not the root domain, information +about the names in the cache ending in \fIname\fP (including \fIname\fP without +the leading dot) will be printed. +If \fIname\fP is not specified, information about all the names in the cache +will be printed. +.TP +\fBlist\-rrtypes\fP [no arguments] + +List available rr types for the neg command. Note that those are only +used for the neg command, not for add! +.SH "BUGS" +.PP +If you pipe the output of \fBdump\fP command through an application that +reads only part of the output and then blocks (such as more or less), +pdnsd threads trying to add new entries to the cache will be suspended +until the pipe is closed. +It is preferable to capture the output in a file in such a case. +.br +Report any remaining bugs to the authors. +.SH "AUTHORS" +.PP +Thomas Moestl +.UR + +.UE +.br +Paul A. Rombouts +.UR + +.UE +(for versions 1.1.8b1\-par and later) +.PP +Last revised: 04 Sep 2008 by Paul A. Rombouts. +.SH "SEE ALSO" +.PP +.BR pdnsd (8), +.BR pdnsd.conf (5) diff --git a/jni/pdnsd/doc/pdnsd.8.in b/jni/pdnsd/doc/pdnsd.8.in new file mode 100644 index 00000000..ba4330af --- /dev/null +++ b/jni/pdnsd/doc/pdnsd.8.in @@ -0,0 +1,326 @@ +.TH PDNSD 8 "Jul 2007" "pdnsd @fullversion@" "System Administration Commands" + +.SH NAME +\fBpdnsd\fP \- dns proxy daemon + +.SH SYNOPSIS + +\fBpdnsd\fP [\-h] [\-V] [\-s] [\-d] [\-g] [\-t] [\-p \fIfile\fR] [\-v\fIn\fR] [\-m\fIxx\fR] [\-c \fIfile\fR] [\-4] [\-6] [\-a] +.PP +This man page is an extract of the documentation of \fBpdnsd\fP. +For complete, current documentation, refer to the HTML (or plain text) +documentation (which you can find in the \fBdoc/\fP subdirectory of the +source or in a standard documentation directory, typically +\fB/usr/share/doc/pdnsd/\fP if you are using a binary package). + +.SH DESCRIPTION +.PP +\fBpdnsd\fP is a IPv6 capable proxy domain name server (DNS) which +saves the contents of its DNS cache to the disk on exit. + +.SH OPTIONS + +.RS +.TP +.B \-4 +enables IPv4 support. IPv6 support is automatically +disabled (should it be available). On by default. +.TP +.B \-6 +enables IPv6 support. IPv4 support is automatically +disabled (should it be available). Off by default. +.TP +.B \-a +With this option, pdnsd will try to detect automatically if +the system supports IPv6, and fall back to IPv4 otherwise. +.TP +.BR \-V " or " \-\-version +Print version information and exit. +.TP +\fB\-c\fP \fIFILE\fP or \fB\-\-config\-file=\fP\fIFILE\fP +specifies that configuration is to be read from \fIFILE\fP. +Default is \fB@sysconfdir@/pdnsd.conf\fP. +.TP +.BR \-d " or " \-\-daemon +Start \fBpdnsd\fP in daemon mode (as a background process). +.TP +.BR \-g " or " \-\-debug +Print some debug messages on the console or to the file +\fBpdnsd.debug\fP in your cache directory (in daemon mode). +.TP +.BR \-h " or " \-\-help +Print an option summary and exit. +.TP +\fB\-i\fP \fIPREFIX\fP or \fB\-\-ipv4_6_prefix=\fP\fIPREFIX\fP +specifies the prefix pdnsd uses (when running in IPv6 mode) to map IPv4 +addresses in the configuration file to IPv6 addresses. Must be a valid IPv6 +address. Default is ::ffff:0.0.0.0 +.TP +.B \-p \fIFILE\fP +writes the pid the server runs as to the specified filename. Works +only in daemon mode. +.TP +.B \-\-pdnsd\-user +Print the user \fBpdnsd\fP will run as and exit. +.TP +.BR \-s " or " \-\-status +enables the status control socket. Either this option should be passed +to the command line or \fBstatus_ctl=on;\fP should be specified in the +config file if you want to use +.BR pdnsd\-ctl (8) +to control \fBpdnsd\fP at runtime. +.TP +.BR \-t " or " \-\-tcp +enables the TCP server thread. \fBpdnsd\fP will then serve TCP and UDP +queries. +.TP +.BI \-v n +sets the verbosity of \fBpdnsd\fP. \fIn\fP is a numeric argument +between 0 (normal operation) to 3 (many messages for debugging). +.TP +.BI \-m xx +sets the query method \fBpdnsd\fP +uses. Possible values for \fIxx\fP are: +.IP +.B uo +\- pdnsd will use UDP only. This is the fastest method, and should +be supported by all name servers on the Internet. + +.IP +.B to +\- pdnsd will use TCP only. TCP queries usually take more time than +UDP queries, but are more secure against certain attacks, where an +attacker tries to guess your query id and to send forged answers. TCP +queries are not supported by some name servers. + +.IP +.B tu +\- pdnsd will try to use TCP, and will fall back to UDP if its +connection is refused or times out. + +.IP +.B ut +\- pdnsd will try to use UDP, and will repeat the query using TCP +if the UDP reply was truncated (i.e. the tc bit is set). +This is the behaviour recommended by the DNS standards. + +.PP +Additionally, "no" can be prepended to the \-\-status, \-\-daemon, \-\-debug +and \-\-tcp options (e.g. \-\-notcp) to reverse their effect. +.RE + +.SH USAGE +.PP +\fBpdnsd\fP is usually run from a startup script. For \fBpdnsd\fP to +work, You need to:- + +.IP +1. Tell your system to use \fBpdnsd\fP as the primary DNS server by +modifying \fB/etc/resolv.conf\fP. + +.IP +2. Tell \fBpdnsd\fP to use an authentic source for DNS records, by +including the IP addresses of one or more DNS servers, usually your +ISP's DNS servers, in \fB@sysconfdir@/pdnsd.conf\fP. +.PP +For this, put the following line in your \fB/etc/resolv.conf\fP +.PP +.RS +nameserver 127.0.0.X +.RE +.PP +where X can be any number. (I use 3). Comment out all other +entries. You should put the same value in the server_ip= line in +\fBglobal\fP section of \fB@sysconfdir@/pdnsd.conf\fP. +.br +If you want to use \fBpdnsd\fP as the DNS server for a small local network, +you should use the IP address or name of the interface connected to +this network instead of 127.0.0.X. +.RE + +.PP +To tell \fBpdnsd\fP where to get DNS information from, add the +following lines in \fB@sysconfdir@/pdnsd.conf\fP:- + +.PP +.RS +server { +.br + label= "myisp"; + ip=123.456.789.001,123.456.789.002; + proxy_only=on; + timeout=10; +.br +} +.RE +.PP +Note the opening and closing braces. Add more such \fBserver\fP +sections for each set of DNS servers you want \fBpdnsd\fP to query. +Of course the configuration options shown here are just examples. +More examples can be found in \fB@sysconfdir@/pdnsd.conf.sample\fP +or the pdnsd.conf in the documentation directory. +See the +.BR pdnsd.conf (5) +man page for all the possible options and their exact meaning. +.PP +If you use a dial up connection, remember that ppp scripts usually +replace \fB/etc/resolv.conf\fP when connection with the ISP is +established. You need to configure ppp (or whatever you use to +establish a connection) so that \fB/etc/resolv.conf\fP is not replaced +every time a connection is established. Read the documentation for the +scripts run when your network comes up. +.PP +If you use pppconfig, specify `none' in the `nameservers' option in +the `advanced' tab. If you use multiple ISPs, you should do this for +each connection/account. +.PP +If you use multiple ISPs, you should tell \fBpdnsd\fP which DNS servers +have become available by calling \fBpdnsd\-ctl\fP, the \fBpdnsd\fP +control utility, in a script (e.g. \fB/etc/ppp/ip\-up\fP when you use pppd) +that is run when the connection is established. +If the addresses of the DNS servers are obtained through some type of +dynamic configuration protocol (e.g. pppd with the usepeerdns +option or a DHCP client), you can pass the DNS server addresses as an extra +argument to \fBpdnsd\-ctl\fP to configure \fBpdnsd\fP at run time. +See the +.BR pdnsd\-ctl (8) +man page for details. + +.SH FILES + +\fB@sysconfdir@/pdnsd.conf\fP is the pdnsd configuration file. +The file format and configuration options are described in the +.BR pdnsd.conf (5) +man page. You can find examples of almost all options in +\fB@sysconfdir@/pdnsd.conf.sample\fP. +.PP +\fB@cachedir@/pdnsd.cache\fP +.PP +\fB@cachedir@/pdnsd.status\fP is the status control socket, which must be +enabled before you can use \fBpdnsd\-ctl\fP. +.PP +\fB/etc/init.d/pdnsd\fP (the name and location of the start-up script +may be different depending on your distribution.) +.PP +\fB/etc/resolv.conf\fP +.PP +\fB/etc/defaults/pdnsd\fP contains additional parameters or options +which may be passed to pdnsd at boot time. This saves the hassle of +fiddling with initscripts (not available on all distributions). + +.SH BUGS +.PP +The verbosity option +.BI -v n +presently does not seem to have much effect on the amount of debug output. +.br +Report any remaining bugs to the authors. + +.SH CONFORMING TO +.PP +\fBpdnsd\fP should comply with RFCs 1034 and 1035. As of version +1.0.0, RFC compliance has been improved and pdnsd is now believed (or +hoped?) to be fully RFC compatible. It completely follows RFC 2181 +(except for one minor issue in the FreeBSD port, see the +documentation). +.PP +It does \fINOT\fP support the following features, of which most are +marked optional, experimental or obsolete in these RFCs: + + +.IP +\(bu Inverse queries +.IP +\(bu Status queries +.IP +\(bu Completion queries +.IP +\(bu Namespaces other than IN (Internet) +.IP +\(bu AXFR and IXFR queries (whole zone transfers); since pdnsd does not maintain zones, that should not violate the standard + +.PP +The following record types, that are extensions to the original DNS +standard, are supported if given as options at compile time. (if you +do not need them, you do not need to compile support for them into +pdnsd and save cache and executable space): + +.IP +\(bu RP (responsible person, RFC 1183) +.IP +\(bu AFSDB (AFS database location, RFC 1183) +.IP +\(bu X25 (X25 address, RFC 1183) +.IP +\(bu ISDN (ISDN number/address, RFC 1183) +.IP +\(bu RT (route through, RFC 1183) +.IP +\(bu NSAP (Network Service Access Protocol address , RFC 1348) +.IP +\(bu PX (X.400/RFC822 mapping information, RFC 1995) +.IP +\(bu GPOS (geographic position, deprecated) +.IP +\(bu AAAA (IPv6 address, RFC 1886) +.IP +\(bu LOC (location, RFC 1876) +.IP +\(bu EID (Nimrod EID) +.IP +\(bu NIMLOC (Nimrod locator) +.IP +\(bu SRV (service record, RFC 2782) +.IP +\(bu ATMA (ATM address) +.IP +\(bu NAPTR (URI mapping, RFC 2168) +.IP +\(bu KX (key exchange, RFC 2230) + +.SH SEE ALSO +.PP +.BR pdnsd\-ctl (8), +.BR pdnsd.conf (5), +.BR pppconfig (8), +.BR resolv.conf (5) +.PP +More documentation is available in the \fBdoc/\fP subdirectory of the source, +or in \fB/usr/share/doc/pdnsd/\fP if you are using a binary package. + +.SH AUTHORS + +\fBpdnsd\fP was originally written by Thomas Moestl, +.UR +, +.UE +and was extensively revised by Paul A. Rombouts +.UR + +.UE +(for versions 1.1.8b1\-par and later). +.PP +Several others have contributed to \fBpdnsd\fP; see files in the +source or \fB/usr/share/doc/pdnsd/\fP directory. +.PP +This man page was written by Mahesh T. Pai +.UR + +.UE +using the documents in \fB/usr/share/docs/pdnsd/\fP directory for Debian, +but can be used on other distributions too. +.PP +Last revised: 22 Jul 2007 by Paul A. Rombouts. + +.SH COPYRIGHT + +.PP +This man page is a part of the pdnsd package, and may be distributed +in original or modified form under terms of the GNU General Public +License, as published by the Free Software Foundation; either version +3, or (at your option) any later version. + +.PP +You can find a copy of the GNU GPL in the file \fBCOPYING\fP in the source +or the \fB/usr/share/common\-licenses/\fP directory if you are using a +Debian system. diff --git a/jni/pdnsd/doc/pdnsd.conf.5.in b/jni/pdnsd/doc/pdnsd.conf.5.in new file mode 100644 index 00000000..801b5350 --- /dev/null +++ b/jni/pdnsd/doc/pdnsd.conf.5.in @@ -0,0 +1,1328 @@ +.\" Generated automatically from the html documentation by html2confman.pl +.\" +.\" Manpage for pdnsd.conf (pdnsd configuration file) +.\" +.\" Copyright (C) 2000, 2001 Thomas Moestl +.\" Copyright (C) 2003, 2004, 2005, 2006, 2007 Paul A. Rombouts +.\" +.\" This manual is a part of the pdnsd package, and may be distributed in +.\" original or modified form under terms of the GNU General Public +.\" License, as published by the Free Software Foundation; either version +.\" 3, or (at your option) any later version. +.\" You can find a copy of the GNU GPL in the file COPYING in the source +.\" or documentation directory. +.\" +.TH PDNSD.CONF 5 "Apr 2012" "pdnsd @fullversion@" +.SH NAME +pdnsd.conf \- The configuration file for pdnsd +.hw config +.SH DESCRIPTION +.PP +This manual page describes the layout of the +.BR pdnsd (8) +configuration file and the available configuration options. +The default location of the file is @sysconfdir@/pdnsd.conf. This may be changed +with the \fB-c\fP command line option. +An example pdnsd.conf comes with the pdnsd distribution in the documentation directory +or in @sysconfdir@/pdnsd.conf.sample. +.SH "FILE FORMAT" +.PP +The configuration file is divided into sections. Each section is prefixed with +the section name and opening curlies ({) and closed with closing curlies (}). +In each section, configuration options can be given in the form + +\fIoption_name\fP=\fIoption_value\fP; + +Option value may be a string literal, a number, a time specification or a constant. +In previous versions of pdnsd strings had to be enclosed +in quotes ("), but since version 1.1.10 this is no longer necessary, unless +a string contains a special character such as whitespace, a token that normally starts +a comment, or one of ",;{}\". +Since version 1.2.9 a backslash (\) inside a string is interpreted as an escape character, +so it is possible to include special characters in strings (both quoted or unquoted) +by preceding them with a backslash. Some escape sequences are in interpreted as in the C +programming language, e.g. \t becomes a tab, +\n becomes a new-line control char. +.br +A time specification consists a sequence of digits followed by a one-letter suffix. +The following suffixes are recognized: +s (seconds), m (minutes), h (hours), +d (days) and w (weeks). +If the suffix is missing, seconds are assumed. +If several time specifications are concatenated, their values are added together; +e.g. 2h30m is interpreted as 2*60*60 + 30*60 = 9000 seconds. +.br +Some options take more than one value; in this case, the values are separated with commas. +.br +If you may supply one of a set of possible values to an option, this is noted +in the documentation as +(option1|option2|option3|...) +.br +The constants true|false and yes|no +are accepted as synonyms for the constants on|off. +.br +Comments may be enclosed in /* and */, nested comments are possible. If the +# sign or two slashes (//) appear in the configuration file, everything from +these signs to the end of the current line is regarded as a comment and ignored. +.br +There are examples for nearly all options in the sample config file. + +.SS global Section +The global section specifies parameters that affect the overall behaviour of the +server. If you specify multiple global sections, the settings of those later in +the file will overwrite the earlier given values. +.br +These are the possible options: + +.TP +.B perm_cache=(\fInumber\fP|off); +Switch the disk cache off or supply a maximum cache size in kB. If the disk +cache is switched off, 8 bytes will still be written to disk. +The memory cache is always 10kB larger than the file cache. +This value is 2048 (2 MB) by default. +.TP +.B cache_dir=\fIstring\fP; +Set the directory you want to keep the cache in. +The default is "@cachedir@" +(unless pdnsd was compiled with a different default). +.TP +.B server_port=\fInumber\fP; +Set the server port. This is especially useful when you want to start the +server and are not root. Note that you may also not specify uptest=ping in +the server section as non-root. +.br +The default port is 53, the RFC-standard one. Note that you should only use +non-standard ports when you only need clients on your machine to communicate +with the server; others will probably fail if the try to contact the server +on the basis of an NS record, since the A record that supplies the address for +(among others) name servers does not have a port number specification. +.TP +.B server_ip=\fIstring\fP; +or +.PD 0 +.TP +.PD +.B interface=\fIstring\fP; +Set the IP address pdnsd listens on for requests. This can be useful +when the host has several interfaces and you want pdnsd not to listen on +all interfaces. For example, it is possible to bind pdnsd to listen on +127.0.0.2 to allow pdnsd to be a forwarder for BIND. +The default setting for this option is server_ip=any, which means that +pdnsd will listen on all of your local interfaces. +Presently you can only specify one address here; if you want pdnsd to listen on multiple +interfaces but not all you will have to specify server_ip=any +and use firewall rules to restrict access. +.br +The IP address used to need quotation marks around it, but since version 1.1.10 +this is no longer necessary. +.br +If pdnsd has been compiled with both IPv4 and IPv6 support, and you want to +specify an IPv6 address here, then unless pdnsd was compiled to start up in IPv6 mode +by default, you will need to use the \-6 command-line option or +set run_ipv4=off first (see below) in order to ensure that the +IPv6 address is parsed correctly. +.br +If pdnsd is running in IPv6 mode and you specify an IPv4 address here, +it will automatically be mapped to an IPv6 address. +.br +\fINew in version 1.2:\fP You may also give the name of an interface +such as "lo" or "eth0" here, instead of an IP address +(this has been tested on Linux, and may or may not work on other platforms). +pdnsd will not bind to the interface name, but will look up the address of the +interface at start-up and listen on that address. If the address of the interface +changes while pdnsd is running, pdnsd will not notice that. You will need to +restart pdnsd in that case. +.TP +.B outgoing_ip=\fIstring\fP; +or +.PD 0 +.TP +.PD +.B outside_interface=\fIstring\fP; +\fINew in version 1.2.9:\fP +Set the IP address of the interface used by pdnsd for outgoing queries. +This can be useful when the host has several interfaces and you want pdnsd +to send outgoing queries via only one of them. +For example, if pdnsd is running on a host with one interface with IP address +192.168.1.1 connected to the local network, and another with IP address 123.xxx.yyy.zzz +connected to the internet, you may specify server_ip=192.168.1.1 +and outgoing_ip=123.xxx.yyy.zzz to enforce that pdnsd only responds +to queries received from the local network, and only sends outgoing queries via +the interface connected to the internet. +.br +The default setting for this option is any, which means that +the kernel is free to decide which interface to use. +Like with the server_ip option, you may also give the name of an +interface here, instead of an IP address. +.TP +.B linkdown_kluge=(on|off); +This option enables a kluge that some people might need: when all servers are +marked down, with this option set the cache is not even used when a query is +received, and a DNS error is returned in any case. The only exception from this +is that local records (as specified in rr and source +sections are still served normally. +In general, you probably want to get cached entries even when the network is down, +so this defaults to off. +.TP +.B max_ttl=\fItimespec\fP; +This option sets the maximum time a record is held in cache. All dns +resource records have a time to live field that says for what period of time the +record may be cached before it needs to be requeried. If this is more than the +value given with max_ttl, this time to live value is set to max_ttl. +This is done to prevent records from being cached an inappropriate long period of time, because +that is almost never a good thing to do. Default is 604800s (one week). +.TP +.B min_ttl=\fItimespec\fP; +This option sets the minimum time a record is held in cache. All dns +resource records have a time to live field that says for what period of time the +record may be cached before it needs to be requeried. If this is less than the +value given with min_ttl, this time to live value is set to min_ttl. +Default is 120 seconds. +.TP +.B neg_ttl=\fItimespec\fP; +This option sets the time that negatively cached records will remain valid in the +cache if no time to live can be determined. This is always the case when whole +domains are being cached negatively, and additionally when record types are cached +negatively for a domain for which no SOA record is known to pdnsd. If a SOA is present, +the ttl of the SOA is taken. +.TP +.B neg_rrs_pol=(on|off|auth|default); +This sets the RR set policy for negative caching; this tells pdnsd under which circumstances +it should cache a record type negatively for a certain domain. off will +turn the negative caching of record types off, on will always add a negative +cache entry when a name server did not return a record type we asked it for, and auth +will only add such entries if the answer came from an authoritative name server for that +domain. +.br +\fINew in version 1.2.8:\fP The default setting will add a negatively cached record +if either the answer was authoritive or the answer indicated the name server had "recursion available" +while the query explicitly requested such recursion. +.br +The preset is "default" (used to be auth). +.TP +.B neg_domain_pol=(on|off|auth); +This is analogue to neg_rrs_pol for whole domain negative caching. It should be safe +to set this on, because I have not seen a caching server that will falsely claim that a +domain does not exist. +.br +The default is auth. +.TP +.B run_as=\fIstring\fP; +This option allows you to let pdnsd change its user and group id after operations that needed +privileges have been done. This helps minimize security risks and is therefore recommended. The +supplied string gives a user name whose user id and primary group id are taken. +.br +A little more details: after reading the config file, becoming a daemon (if specified) and starting +the server status thread, the main thread changes its gid and uid, as do all newly created threads +thereafter. By taking another uid and gid, those threads run with the privileges of the +specified user. +Under Linux and FreeBSD, the server status thread runs with the original privileges only when the strict_setuid option +is set to off (see below, on by default), because these may be needed +for exec uptests. The manager thread also retains its original privileges in this case. +You should take care that the user you specify has write permissions on your cache file and +status pipe (if you need a status pipe). You should look out for error messages like "permission denied" +and "operation not permitted" to discover permission problems. +.br +.TP +.B strict_setuid=(on|off); +When used together with the run_as option, this option lets you specify that all threads of the +program will run with the privileges of the run_as user. This provides higher security than +the normal run_as +option, but is not always possible. See the run_as option for further discussion. +.br +This option is on by default. +.br +Note that this option has no effect on Non-Linux systems. +.TP +.B paranoid=(on|off); +Normally, pdnsd queries all servers in recursive mode (i.e. instructs servers to query other servers themselves +if possible, +and to give back answers for domains that may not be in its authority), and accepts additional records with information +for servers that are not in the authority of the queried server. This opens the possibility of so-called cache poisoning: +a malicious attacker might set up a dns server that, when queried, returns forged additional records. This way, he might +replace trusted servers with his own ones by making your dns server return bad IP addresses. This option protects +you from cache poisoning by rejecting additional records +that do not describe domains in the queried servers authority space and not doing recursive queries any more. +An exception +to this rule are the servers you specify in your config file, which are trusted. +.br +The penalty is a possible performance decrease, in particular, more queries might be necessary for the same +operation. +.br +You should also notice that there may be other similar security problems, which are essentially problems of +the DNS, i.e. +any "traditional" server has them (the DNS security extensions solve these problems, but are not widely +supported). +One of this vulnerabilities is that an attacker may bombard you with forged answers in hopes that one may match a +query +you have done. If you have done such a query, one in 65536 forged packets will be succesful (i.e. an average packet +count of 32768 is needed for that attack). pdnsd can use TCP for queries, +which has a slightly higher overhead, but is much less vulnerable to such attacks on sane operating systems. Also, pdnsd +chooses random query ids, so that an attacker cannot take a shortcut. If the attacker is able to listen to your network +traffic, this attack is relatively easy, though. +.br +This vulnerability is not pdnsd's fault, and is possible using any conventional +name server (pdnsd is perhaps a little more secured against this type of attacks if you make it use TCP). +.br +The paranoid option is off by default. +.br +.TP +.B ignore_cd=(on|off); +\fINew in version 1.2.8:\fP This option lets you specify that the CD bit of a DNS query will be ignored. +Otherwise pdnsd will reply FORMERR to clients that set this bit in a query. +It is safe to enable this option, as the CD bit refers to 'Checking Disabled' +which means that the client will accept non-authenticated data. +.br +This option is on by default. Turn it off if you want the old behaviour (before version 1.2.8). +.TP +.B scheme_file=\fIstring\fP; +In addition to normal uptests, you may specify that some servers shall only be queried when a certain +pcmcia-cs scheme is active (only under linux). For that, pdnsd needs to know where the file resides that +holds the pcmcia scheme information. Normally, this is either /var/lib/pcmcia/scheme or +/var/state/pcmcia/scheme. +.TP +.B status_ctl=(on|off); +This has the same effect as the \-s command line option: the status control is enabled when +on is specified. +.br +\fIAdded by Paul Rombouts\fP: Note that pdnsd\-ctl allows run-time configuration of pdnsd, +even the IP addesses of the name servers can be changed. If you're not using pdnsd\-ctl and +you want maximum security, you should not enable this option. It is disabled by default. +.TP +.B daemon=(on|off); +This has the same effect as the \-d command line option: the daemon mode is enabled when +on is specified. +.br +Default is off. +.TP +.B tcp_server=(on|off); +tcp_server=on has the same effect as the \-t or \-\-tcp +command-line option: it enables TCP serving. +Similarly, tcp_server=off is like the \-\-notcp command-line option. +.br +Default is on. +.TP +.B pid_file=\fIstring\fP; +This has the same effect as the \-p command line option: you can specify a file that pdnsd +will write its pid into when it starts in daemon mode. +.TP +.B verbosity=\fInumber\fP; +This has the same effect as the \-v command line option: you can set the verbosity of pdnsd's +messages with it. The argument is a number between 0 (few messages) to 3 (most messages). +.TP +.B query_method=(tcp_only|udp_only|tcp_udp|udp_tcp); +This has the same effect as the \-m command line option. +Read the documentation for the command line option on this. +tcp_only corresponds to the to, udp_only to the uo, +tcp_udp to the tu and udp_tcp to the ut +argument of the command line option. +.br +If you use query_method=tcp_udp, it is recommended that you also set the global timeout option to at least twice the longest server timeout. +.TP +.B run_ipv4=(on|off); +This has the same effect as the \-4 or \-6 command line option: +if on is specified, IPv4 support is enabled, and IPv6 support is disabled (if available). +If off is specified, IPv4 will be disabled and IPv6 will be enabled. +For this option to be meaningful, pdnsd needs to be compiled with support for the protocol you choose. +If pdnsd was compiled with both IPv4 and IPv6 support, and you want to include IPv6 addresses +in the configuration file, you will probably need to specify run_ipv4=off first to +ensure that the IPv6 addresses are parsed correctly. +.TP +.B debug=(on|off); +This has the same effect as the \-g command line option: the debugging messages are enabled when +on is specified. +.TP +.B ctl_perms=\fInumber\fP; +This option allows you to set the file permissions that the pdnsd status control socket will have. These +are the same as file permissions. The owner of the file will be the run_as user, or, if none is specified, +the user who started pdnsd. If you want to specify the permissions in octal (as usual), don't forget +the leading zero (0600 instead of 600!). To use the status control, write access is needed. The default +is 0600 (only the owner may read or write). +.br +Please note that the socket is kept in the cache directory, and that the cache directory permissions +might also need to be adjusted. Please ensure that the cache directory is not writeable for untrusted +users. +.TP +.B proc_limit=\fInumber\fP; +With this option, you can set a limit on the pdnsd threads that will be active simultaneously. If +this number is exceeded, queries are queued and may be delayed some time. +See also the procq_limit option. +.br +The default for this option is 40. +.TP +.B procq_limit=\fInumber\fP; +When the query thread limit proc_limit is exceeded, connection attempts to pdnsd will be queued. +With this option, you can set the maximum queue length. +If this length is also exceeded, the incoming queries will be dropped. +That means that tcp connections will be closed and udp queries will just be dropped, which +will probably cause the querying resolver to wait for an answer until it times out. +.br +See also the proc_limit option. A maximum of proc_limit+procq_limit +query threads will exist at any one time (plus 3 to 6 threads that will always +be present depending on your configuration). +.br +The default for this option is 60. +.TP +.B tcp_qtimeout=\fItimespec\fP; +This option sets a timeout for tcp queries. If no full query has been received on a tcp connection +after that time has passed, the connection will be closed. The default is set using the +\-\-with\-tcp\-qtimeout option to configure. +.TP +.B par_queries=\fInumber\fP; +This option used to set the maximum number of remote servers that would be queried simultaneously, +for every query that pdnsd receives. +.br +Since version 1.1.11, the meaning of this option has changed slightly. +It is now the increment with which the number of parallel queries is +increased when the previous set of servers has timed out. +For example, if we have a list \fIserver1, server2, server3,\fP etc. of available servers +and par_queries=2, then pdnsd will first send queries to \fIserver1\fP and \fIserver2\fP, +and listen for responses from these servers. +.br +If these servers do not send a reply within their timeout period, pdnsd will send additional +queries to \fIserver3\fP and \fIserver4\fP, and listen for responses from +\fIserver1, server2, server3\fP and \fIserver4\fP, and so on until a useful reply is +received or the list is exhausted. +.br +In the worst case there will be pending queries to all the servers in the list of available servers. +We may be using more system resources this way (but only if the first servers in the list +are slow or unresponsive), but the advantage is that we have a greater chance of catching a reply. +After all, if we wait longer anyway, why not for more servers. +.br +See also the explanation of the global timeout option below. +.br +1 or 2 are good values for this option. +The default is set at compile time using the \-\-with\-par\-queries option to configure. +.TP +.B timeout=\fItimespec\fP; +This is the global timeout parameter for dns queries. +This specifies the minimum period of time pdnsd will wait after sending the +first query to a remote server before giving up without having +received a reply. The timeout options in the configuration file are +now only minimum timeout intervals. Setting the global timeout option +makes it possible to specify quite short timeout intervals in the +server sections (see below). This will have the effect that pdnsd will start +querying additional servers fairly quickly if the first servers are +slow to respond (but will still continue to listen for responses from +the first ones). This may allow pdnsd to get an answer more quickly in +certain situations. +.br +If you use query_method=tcp_udp it is recommended that +you make the global timeout at least twice as large as the largest +server timeout, otherwise pdnsd may not have time to try a UDP query +if a TCP connection times out. +.br +Default value is 0. +.TP +.B randomize_recs=(on|off); +If this option is turned on, pdnsd will randomly reorder the cached records of one type +when creating an answer. This supports round-robin DNS schemes and increases fail +safety for hosts with multiple IP addresses, so this is usually a good idea. +.br +On by default. +.TP +.B query_port_start=(\fInumber\fP|none); +If a number is given, this defines the start of the port range used for queries of pdnsd. The +value given must be >= 1024. The purpose of this option is to aid certain firewall +configurations that are based on the source port. Please keep in mind that another application +may bind a port in that range, so a stateful firewall using target port and/or process uid may +be more effective. In case a query start port is given pdnsd uses this port as the first port of a +specified port range (see query_port_end) used for queries. +pdnsd will try to randomly select a free port from this range as local port for the query. +.br +To ensure that there are enough ports for pdnsd to use, the range between query_port_start and +query_port_end should be adjusted to at least (par_queries * proc_limit). +A larger range is highly recommended for security reasons, and also because other applications may +allocate ports in that range. If possible, this range should be kept out of the space +that other applications usually use. +.br +The default for this option is 1024. Together with the default value of query_port_end, +this makes it the hardest for an attacker to guess the source port used by the pdnsd resolver. +If you specify none here, pdnsd will let the kernel choose the source port, but +this may leave pdnsd more vulnerable to an attack. +.TP +.B query_port_end=\fInumber\fP; +Used if query_port_start is not none. Defines the last port of the range started by query_port_start +used for querys by pdnsd. The default is 65535, which is also the maximum legal value for this option. +For details see the description of query_port_start. +.TP +.B delegation_only=\fIstring\fP; +\fIAdded by Paul Rombouts\fP: This option specifies a "delegation-only" zone. +This means that if pdnsd receives a query for a name that is in a +subdomain of a "delegation-only" zone but the remote name server +returns an answer with an authority section lacking any NS RRs for +subdomains of that zone, pdnsd will answer NXDOMAIN (unknown domain). +This feature can be used for undoing the undesired effects of DNS +"wildcards". Several "delegation-only" zones may be specified together. +If you specify root servers in a server section it is +important that you set root_server=on in such a section. +.br +Example: + +delegation_only="com","net"; + +This feature is off by default. It is recommended that you only use +this feature if you actually need it, because there is a risk that +some legitimate names will be blocked, especially if the remote +name servers queried by pdnsd return answers with empty authority +sections. +.TP +.B ipv4_6_prefix=\fIstring\fP; +This option has the same effect as the \-i command-line option. +When pdnsd runs in IPv6 mode, this option specifies the prefix pdnsd uses to convert IPv4 addresses in +the configuration file (or addresses specified with pdnsd\-ctl) +to IPv6-mapped addresses. +The string must be a valid IPv6 address. Only the first 96 bits are used. +Note that this only effects the parsing of IPv4 addresses listed after this option. +.br +The default is "::ffff.0.0.0.0". +.TP +.B use_nss=(on|off); +If this option is turned on, pdnsd will call initgroups() to set up the group access list, +whenever pdnsd changes its user and group id (see run_as option). +There is a possible snag, though, if initgroups() uses NSS (Name Service Switch) and +NSS in turn uses DNS. In such a case you may experience lengthy timeouts and stalls. +By setting use_nss=off, you can disable the initgroups() call +(only possible in versions 1.2.5 and later). +.br +This option was contributed by Jan-Marek Glogowski. +.br +On by default. +.TP +.B udpbufsize=\fInumber\fP; +\fINew in version 1.2.9:\fP +This option sets the upper limit on the size of UDP DNS messages. The default is 1024. +.br +See also the edns_query server option below. + +.SS server Section +Each server section specifies a set of name servers that pdnsd should try to get +resource records or authoritative name server information from. The servers are +queried in the order of their appearance (or parallel to a limited extend). +If one fails, the next one is taken and so on. +.br +You probably want to specify the dns server in your LAN, the caching dns servers +of your internet provider or even a list of root servers in one or more server sections. +.br +The supported options in this section are: + +.TP +.B label=\fIstring\fP; +Specify a label for the server section. This can be used to refer to this section +when using pdnsd\-ctl, the pdnsd control utility. +.br +You can give several server sections the same label, but if you want to change the addresses +of a server section (see \fBip\fP option below) during run-time with +"pdnsd\-ctl\ server\ \fIlabel\fP\ up\ \fIdns1\fP,\fIdns2\fP,...", +the label must be unique. +.TP +.B ip=\fIstring\fP; +Give the IP (the address, \fInot\fP the host name) of the server. +.br +Multiple IP addresses can be given per server section. +This can be done by entering multiple lines of the form ip=\fIstring\fP; +or a single line like this: + +ip=\fIstring\fP,\fIstring\fP,\fIstring\fP; + +IP addresses do not have to be specified in the configuration file. +A server section without IP addresses will remain inactive until it is assigned +one or more addresses with pdnsd\-ctl, +the pdnsd control utility. +.br +If pdnsd has been compiled with both IPv4 and IPv6 support, any IPv6 addresses you specify +here will be skipped with a warning message, unless pdnsd is running in IPv6 mode. +Thus, unless pdnsd was compiled to startup in IPv6 mode by default, you need to use the +command-line option \-6 or set run_ipv4=off +first (see global section) in order to ensure +that IPv6 addresses are parsed correctly. +.br +If pdnsd is running in IPv6 mode and you specify an IPv4 address here, +it will automatically be mapped to an IPv6 address. +.TP +.B file=\fIstring\fP; +\fINew in version 1.2:\fP This option allows you to give the name of a resolv.conf-style file. +Of the lines beginning with the nameserver keyword, the second field will be parsed as an +IP address, as if it were specified with the ip= option. The remaining lines will be ignored. +If the contents of the file changes while pdnsd is running, you can make pdnsd aware of the changes through the +use of pdnsd\-ctl, the pdnsd control utility. +This is usually most conveniently done by placing the command "pdnsd\-ctl\ config" in a script +that is automatically run whenever the DNS configuration changes. +.br +For example, suppose you have a ppp client that writes the DNS configuration for your ISP to the file +/etc/ppp/resolv.conf and runs the script /etc/ppp/ip-up when a new +connection is established. One way of ensuring that pdnsd is automatically reconfigured is to +add a server section in the config file with file=/etc/ppp/resolv.conf and to +add the command "pdnsd\-ctl\ config" to /etc/ppp/ip-up. +.TP +.B port=\fInumber\fP; +Give the port the remote name server listens on. Default is 53 (the official +dns port) +.TP +.B uptest=(ping|none|if|dev|diald|exec|query); +Determine the method to check whether the server is available. Currently +defined methods are: +.IP +\(bu \fBping\fP: Send an ICMP_ECHO request to the server. If it doesn't respond +within the timeout, it is regarded to be unavailable until the next probe. +.IP +\(bu \fBnone\fP: The availability status is not changed, only the time stamp is updated. +.IP +\(bu \fBif\fP: Check whether the interface (specified in the interface= option) is +existent, up and running. This currently works for all "ordinary" +network interfaces, interfaces that disappear when down (e.g. ppp?), +and additionally for Linux isdn interfaces (as of kernel 2.2). Note that +you need a /dev/isdninfo device file (major#45, minor#255), or the +isdn uptest will always fail. +.IP +\(bu \fBdev\fP and \fBdiald\fP: Perform an if uptest, and, if that +was succesful, additionally check whether a program is running that +has locked a given (modem-) device. The needed parameters are an interface (specified as for the if +uptest, e.g. "ppp0") and a device relative to /dev (e.g. +"modem" for /dev/modem specified using the device= option. +pdnsd will then look for a pid file for the given interface in /var/lock (e.g. +/var/run/ppp0.pid) and for a lockfile for the given device (e.g. /var/lock/LCK..modem), +and then test whether the locking process is the process that created the pid file and this process is still +alive. If this is the case, the normal if uptest is executed for the given interface. +.br +The dev option is for pppd dial-on-demand, diald is the same for diald users. +.IP +\(bu \fBexec\fP: Executes a given command in the /bin/sh shell +(as /bin/sh \-c ) +and evaluates the result (the return code of the last command) in the shell's way of handling return codes, +i.e. 0 indicates success, all other indicate failure. The shell's process name will be +uptest_sh. The command is given with the uptest_cmd option (see below). +For secuity issues, also see that entry. +.IP +\(bu \fBquery\fP: \fINew in version 1.2:\fP +This works like the ping test, except it sends an (empty) DNS query to the remote server. +If the server sends a well-formed response back within the timeout period (except SERVFAIL), +it will be regarded as available. +This test is useful if a remote server does not respond to ICMP_ECHO requests at all, +which unfortunately is quite common these days. +It can also happen that a remote server is online but ignores empty DNS queries. +Then you will need the set the query_test_name option (see below). +In many cases this test will be a more reliable indicator of availability +than the ones mentioned before. + +The default value is \fBnone\fP. + +\fBNOTE\fP: If you use on-demand dialing, use none, if, +dev, diald or exec, +since ping or query will send packets +in the specified interval and the interface will thus frequently dial! +.TP +.B ping_timeout=\fInumber\fP; +Sets the timeout for the ping test in tenths of seconds +(this unit is used for legacy reasons; actually the current implementation is +only accurate to a second). +.br +The default is 600 (one minute). +.TP +.B ping_ip=\fIstring\fP; +The IP address for the ping test. The default is the IP of the name server. +.TP +.B query_test_name=\fIstring\fP; +\fINew in version 1.2.9:\fP +Sets the name to be queried when using uptest=query availability test. +If the string is the unquoted constant none, +an empty query is used (this the default), otherwise a query of type A will be +sent for the domain name specified here. It is not necessary for the domain name +to exist or have a record of type A in order for the uptest to succeed. +.br +If the the remote server ignores empty queries, you will probably want to set +query_test_name="." (the root domain). +.TP +.B uptest_cmd=\fIstring\fP,\fIstring\fP; +or +.PD 0 +.TP +.PD +.B uptest_cmd=\fIstring\fP; +Sets the command for the uptest=exec function to the first string. +If the second string is given, it specifies a user with whose user +id and primary group id the command is executed. +.br +This is especially useful if you are executing the server as root, +but do not want the uptest to be performed with root privileges. +In fact, you should never execute the uptest as root if you can help +it. +.br +If the server is running setuid or setgid, the privileges thus gained +are attempted to be dropped even before changing identity to the +specified user to prevent setuid/gid security holes (otherwise, any +user might execute commands as root if you setuid the executable). +.br +\fBNote that this is not always possible, and that pdnsd should never +be installed as setuid or setgid.\fP +The command is executed using /bin/sh, so you should be able to use +shell builtin commands. +.TP +.B interval=(\fItimespec\fP|onquery|ontimeout); +Sets the interval for the server up-test. The default is 900 seconds; +however, a test is forced when a query times out and the timestamp is reset then. +.br +If you specify onquery instead of a timeout, the interface will be +tested before every query. This is to prevent automatically dialing +interfaces (diald/pppd or ippp) to dial on dns queries. It is intended to be +used in connection with an interface-testing uptest ;\-) +.br +Note that using uptest=exec, you might run into performance problems +on slow machines when you use that option. +DON'T use onquery with uptest=ping or +uptest=query, as it may cause delays if the server does not answer +(btw, it doesn't make sense anyway). +Note also that using onquery is no guarantee that the interface +will not be used. When another (reachable) dns server tells pdnsd +to query a third dns server for data, pdnsd will do that and has +no means of checking whether this will dial up the interface or not. +This however should be a rare situation. +.br +\fINew in version 1.2.3:\fP +A third possibility is to specify interval=ontimeout. +In this case the server is not tested at startup/reconfiguration, nor at regular intervals, +but only after a DNS query to a server times out. Certain types of network problems +such as a refused connection will also cause the server to be considered unavailable. +However, once a server is declared dead it is never considered again unless it is revived using a +pdnsd\-ctl config or server command. +The idea behind this option is to minimize uptests by assuming all +servers are available until there is reason to believe otherwise. +.TP +.B interface=\fIstring\fP; +The network interface (or network device, e.g. "eth0") for the uptest=if option. +Must be specified if uptest=if is given. +.TP +.B device=\fIstring\fP; +The (modem-) device that is used for the dev uptest. If you use this for a dial-on-demand +ppp uptest (together with uptest=dev), you need to enter the device you are using for your +pppd here, e.g. modem for /dev/modem. +.br +Must be specified if uptest=dev is given. +.TP +.B timeout=\fItimespec\fP; +Set the timeout for the dns query. The default is 120 seconds. You probably want to set this lower. +.br +Timeouts specified in the configuration file are only treated as the +minimum period of time to wait for a reply. A queries to a remote +server are not canceled until a useful reply has been received, or all +the other queries have timed out or failed. +.br +If you have also set the global timeout option, you may consider setting a fairly small value here. +See the explanation of the timeout option in the global +section for what that means. +.TP +.B purge_cache=(on|off); +In every fetched dns record, there is a cache timeout given, which +specifies how long the fetched data may be cached until it needs to be +reloaded. If purge_cache is set to off, the stale records are not purged +(unless the cache size would be exceeded, in this case the oldest records are purged). +Instead, they are still served if they cannot succesfully be +updated (e.g. because all servers are down). +.br +Default is off. +.TP +.B caching=(on|off); +Specifies if caching shall be performed for this server at all. Default is +on. +.TP +.B lean_query=(on|off); +Specifies whether to use the "lean" query mode. In this mode, only the +information actually queried from pdnsd is resolved and cached. This has +the advantage that usually less cache space is used and the query is +usually faster. In 90% of the cases, only address (A) records are needed +anyway. If switched off, pdnsd will always cache all data about a host +it can find and will specifically ask for all available records +(well, at least it is a good approximation for what it really does ;\-) +This will of course increase the answer packet sizes. +.br +Some buggy name servers may not deliver CNAME records when not asked for +all records. I do not know if such servers are around, but if you have +trouble resolving certain host names, try turning this option off. +.br +A last note: If you use multiple pdnsd's that access each other, turning +this option on is probably a big win. +.br +This on by default. +.TP +.B edns_query=(on|off); +\fINew in version 1.2.9:\fP +Specifies whether to use EDNS (Extension mechanisms for DNS) for outgoing queries. +Currently this is only useful for allowing UDP message sizes larger than 512 bytes. +Note that setting this option on can give problems in combination with some legacy +systems or software, including, embarrassingly enough, previous versions of pdnsd. +.br +The default is off, but if your network can handle UDP payloads +significantly larger than 512 bytes, the recommended value is on. +.br +Note that this option only effects outgoing queries. If pdnsd receives a query using +EDNS, it will reply using EDNS regardless of the value of this option. + +See also the udpbufsize option above. +.TP +.B scheme=\fIstring\fP; +You can specify a pcmcia-cs scheme that is used in addition to the uptests. If you specify +a scheme here, the server this section is for will only be queries if the given scheme +is active. Shell wildcards (* and ?) are allowed in the string under their special +meanings. You need to use the scheme_file option on the global +section to make this option work. +.TP +.B preset=(on|off); +This allows you to specify the initial state of a server before any uptest is performed. +on specifies that the server is regarded available. The default is on. +This is especially useful when you set uptest=none; and want to change +the status of a server only via pdnsd\-ctl. +.TP +.B proxy_only=(on|off); +When this option is set to on, answers given by the servers are always accepted, and no +other servers (as, for example, specified in the NS records of the query domain) are +queried. If you do not turn this option on, pdnsd will do such queries in some cases +(in particular when processing ANY queries). +.br +This option is useful when you do not want pdnsd to make connections to outside servers +for some reasons (e.g. when a firewall is blocking such queries). +.br +I recommend that you turn on lean_query when using this option. +.br +Default is off. +.TP +.B root_server=(on|off|discover); +Set this option to on if the servers specified in a section are root servers. +A root server will typically only give the name servers for the top-level domain in its reply. +Setting root_server=on will cause pdnsd to try to use cached information about +top-level domains to reduce to number of queries to root servers, making the resolving of +new names more efficient. +You can get a list of available root servers by running the command +"dig\ .\ ns". +.br +This option is also necessary if you use the delegation_only option. +.br +\fINew in version 1.2.8:\fP This option may also be set to "discover". +This will cause pdnsd to query the servers provided with the ip= option +to obtain the full list of root servers. The root-server addresses will replace the addresses +specified with the ip= option. +This will only be done once on startup, or after a "pdnsd\-ctl\ config" command. +In this case the name servers specified with the ip= option don't have to be +root servers, they just have to know the names and addresses of the root servers. +After root-server discovery pdnsd will behave just as if root_server=on +had been specified. +.br +Default is off. +.TP +.B randomize_servers=(on|off); +\fINew in version 1.2.6:\fP Set this option to on to give each name server +in this section an equal chance of being queried. If this option is off, the name servers +are always queried starting with the first one specified. Even with this option on, the +query order is not truly random. Only the first server is selected randomly; the following +ones are queried in consecutive order, wrapping around to the beginning of the list when +the end is reached. Note that this option only effects the order within a section. The +servers in the first (active) section are always queried before those in the second one, +etc. +.br + The default is off, but if you are resolving from root servers setting this +option on is highly recommended. If root_server=on this option also effects +the query order of the name servers for the top-level domains. +.TP +.B reject=\fIstring\fP; +\fINew in version 1.2.6:\fP This option can be used to make pdnsd reject replies that +contain certain IP addresses. You can specify a single IP address, which will be matched +exactly, or a range of addresses using an address/mask pair. +The mask can be specified as a simple integer, indicating the number of initial 1 bits in +the mask, or in the usual IP address notation. IP addresses may be either IPv4 or IPv6 +(provided there is sufficient support in the C libraries and support for AAAA records was +not disabled). +When addresses in the reject list are compared with those in a reply, only the bits +corresponding to those set in the netmask are significant, the rest are ignored. +.br +Multiple addresses or address/mask pairs may be specified; this can be done by entering +multiple lines of the form reject=\fIstring\fP; +or a single line like this: + +reject=\fIstring\fP,\fIstring\fP,\fIstring\fP; + +How pdnsd reacts when an address in the reply matches one in the reject list, +depends on the reject_policy option, see below. +.TP +.B reject_policy=(fail|negate); +\fINew in version 1.2.6:\fP +This option determines what pdnsd does when an address in the reply from a name server +matches the reject list (see above). If this option is set to +fail, pdnsd will try another server, or, if there no more servers to try, +return the answer SERVFAIL. If this option is set to negate, pdnsd will +immediately return the answer NXDOMAIN (unknown domain) without querying additional +servers. The fail setting is useful if you don't always trust the servers in +this section, but do trust the servers in the following section. The negate +setting can be used to completely censor certain IP addresses. In this case you should put +the same reject list in every server section, and also set the +reject_recursively option (see below) to true. +.br +The default is fail. +.TP +.B reject_recursively=(on|off); +\fINew in version 1.2.6:\fP Normally pdnsd checks for addresses in the +reject list (see above) only when the reply comes directly from a name server +listed in the configuration file. With this option set to on, pdnsd will +also do this check for name servers that where obtained from NS records in the authority +section of a previous reply (which was incomplete and non-authoritative). +.br +Default is off. +.TP +.B policy=(included|excluded|simple_only|fqdn_only); +pdnsd supports inclusion/exclusion lists for server sections: with include= +and exclude= (see below) you can specify domain names for which this server +will be used or will not be used. The first match counts (i.e., the first include or +exclude rule in a server section that matches a domain name is applied, and the +search for other rules is terminated). If no rule matched a given domain name, +the policy= option determines whether this server is used for the +lookup for that domain name; when included is given, the server will +be asked, and when excluded is given, it will not. +If simple_only is given the server will be used if the name to lookup +is a simple (single-label) domain name, on the other hand if fqdn_only +is given the server will be used only for names consisting of two or more labels +(i.e. the name has at least one dot in-between). +.br +If no server is available for a queried domain, pdnsd will return an error message +to the client that usually will stop the client's attempts to resolve a specific +domain from this server (the libc resolver will e.g. return an error to the application that +tried to resolve the domain if no other servers are available in the resolv.conf). +This may be of use sometimes. +.br +\fINote\fP: the simple_only and fqdn_only constants +were added by Paul Rombouts. +They are useful for controlling which name servers (if any) will be used by +pdnsd for resolving simple (single-label) host names. +fqdn_only used to stand for "fully qualified domain name only", but this is +actually a misnomer. The names in queries received by pdnsd are always considered to be +fully qualified. If you do not exactly understand what the options simple_only and +fqdn_only are good for, you are probably better off not using them. +.br +The default for this option is included. +.TP +.B include=\fIstring\fP; +This option adds an entry to the exclusion/inclusion list. If a domain matches +the name given as string, the server is queried if this was the first matching rule +(see also the entry for policy). +.br +If the given name starts with a dot, the whole subdomain +of the given name including the one of that name is matched, e.g. ".foo.bar." +will match the domain names a.foo.bar., a.b.c.foo.bar. and foo.bar. +.br +If it does not start in a dot, only exactly the given name (ignoring the case, of course) +will be matched (hint: if you want to include all subdomains, but not the domain of the given +name itself, place an exact-match exclude rule before the include rule, e.g: +exclude="foo.bar."; include=".foo.bar."; +.br +Previous versions of pdnsd +required that names given with this and the next option ended in a dot, but since +version 1.1.8b1-par8, pdnsd automatically adds a dot at the end if it +is missing. +.br +pdnsd now also accepts a more compact notation for adding several "include" entries in +one line, e.g.: + +include=".foo",".bar",".my.dom"; + +.TP +.B exclude=\fIstring\fP; +This option adds an entry to the exclusion/inclusion list. If a domain matches +the name given as string, the server is not queried if this was the first matching rule +(see also the entry for policy). +.br +If the given name starts with a dot, the whole subdomain +of the given name including the one of that name is matched, e.g. ".foo.bar." +will match the domain names a.foo.bar., a.b.c.foo.bar. and foo.bar. +.br +If it does not start in a dot, only exactly the given name (ignoring the case, of course) +will be matched (hint: if you want to exclude all subdomains, but not the domain of the given +name itself, place an exact-match include rule before the exclude rule, e.g: +include="foo.bar."; exclude=".foo.bar."; +.br +pdnsd now also accepts a more compact notation for adding several "exclude" entries in +one line, e.g.: + +exclude=".foo",".bar",".my.dom"; + + +.SS rr Section +Every rr section specifies a dns resource record that is stored locally. It +allows you to specify own dns records that are served by pdnsd in a limited way. +Only A, PTR, CNAME, MX, NS and SOA records are implemented. +.br +This option is intended to allow you to define RRs for 1.0.0.127.in-addr.arpa. +and localhost. (and perhaps even one or two hosts) without having to start an +extra named if your cached name servers do not serve those records. +It is \fBNOT\fP intended and not capable to work as a full-featured name server. + +.TP +.B name=\fIstring\fP; +Specifies the name of the resource records, i.e. the domain name of +the resource the record describes. This option must be specified +before any a, ptr, cname, +mx, ns or soa records. +Names are interpreted as absolute domain names +(i.e. pdnsd assumes they end in the root domain). +For this and all following arguments that take domain names, you need to +specify domain names in dotted notation (example venera.isi.edu.). +.br +Previous versions of pdnsd +required that domain names given in the configuration file ended in a +dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a +dot at the end if it is missing. +.br +\fINew in version 1.2:\fP It is also possible to specify a name starting +with the label *. Such a name is called a wildcard. The * in a wildcard +can match one or more labels in a queried name, but only whole labels. +Any other * characters in a wildcard, apart from the leading one, +will only match a literal *. +.br +For example, *.mydomain will match a.mydomain or www.a.mydomain, but not +mydomain. *.a*.mydomain will match www.a*.mydomain, but not www.ab.mydomain. +*a.mydomain will only match itself. +.br +Before you can specify an rr section with name=*.mydomain +you must define some records for mydomain, typically NS and/or SOA records. +Example: +.DS L + + rr { + name = mydomain; + ns = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + rr { + name = *.mydomain; + a = 192.168.1.10; + } +.DE + +In this example, www.mydomain and ftp.mydomain will resolve to the numeric +address 192.168.1.10 (unless you add rr sections explicitly +specifying different addresses for www.mydomain or ftp.mydomain). +If you want mydomain also to resolve to a numeric address, +add an A record to the first rr section. +.TP +.B ttl=\fItimespec\fP; +Specifies the ttl (time to live) for all resource records in this section after this entry. +This may be redefined. The default is 86400 seconds (=1 day). +.TP +.B authrec=(on|off); +If this is turned on, pdnsd will create authoritative local records for this rr section. +This means that pdnsd flags the domain record so that records of this domain that are not +present in the cache are treated as non-existent, i.e. no other servers are queried for +that record type, and an response containing none of those records is returned. This is +most time what people want: if you add an A record for a host, and it has no AAAA record +(thus no IPv6 address), you normally don't want other name servers to be queried for it. +.br +This is on by default. +.br +Please note that this only has an effect if it precedes the name option! +.TP +.B reverse=(on|off); +\fINew in version 1.2:\fP If you want a locally defined name to resolve to a numeric address +and vice versa, you can achieve this by setting reverse=on before defining the A record +(see below). The alternative is to define a separate PTR record, but you will +probably find this option much more convenient. +.br +The default is off. +.TP +.B a=\fIstring\fP; +Defines an A (host address) record. The argument is an IPv4 address in dotted notation. +pdnsd will serve this address for the host name given in the name option. +.br +Provided there is sufficient support in the C libraries and support for AAAA records was not +disabled, the argument string may also be an IPv6 address, in which case an AAAA record +will be defined. +.br +This option be may used multiple times within an rr section, causing +multiple addresses to be defined for the name. However, if you put the different addresses +in different rr sections for the same name, the definition in the last +rr section will cancel the definitions in the previous ones. +.TP +.B ptr=\fIstring\fP; +Defines a PTR (domain name pointer) record. The argument is a host name in +dotted notation (see name). The ptr record is for resolving adresses into names. For example, if +you want the adress 127.0.0.1 to resolve into localhost, and localhost into 127.0.0.1, you need something +like the following sections: +.br +.DS L + + rr { + name = localhost; + a = 127.0.0.1; + owner = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + rr { + name = 1.0.0.127.in-addr.arpa; + ptr = localhost; + owner = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } +.DE + +The second section is for reverse resolving and uses the ptr option. +Note that you can get the same effect by specifying only the first rr section +with reverse=on. +.br +There is something special about the name in the second section: +when a resolver wants to get a host name from an internet address, +it composes an address that is built of the IP address in reverse byte order +(1.0.0.127 instead of 127.0.0.1) where each byte of the adress written +as number constitutes a sub-domain under the domain in-addr.arpa. +.br +So, if you want to compose an adress for reverse resolving, take your ip in dotted notation (e.g. 1.2.3.4), +reverse the byte order (4.3.2.1) and append in-addr.arpa. (4.3.2.1.in-addr.arpa.) +Then, define an rr section giving this address as name and the domain name corresponding to +that ip in the ptr option. +.TP +.B cname=\fIstring\fP; +Defines a CNAME (canonical name) record. +The argument should be a fully-qualified host name in dotted notation (see name). +A CNAME is the DNS equivalent of an alias or symbolic link. +.br +A useful application for CNAMEs is giving short, easy to remember nicknames to hosts with complicated names. +For example, you might want the name "news" to refer to your ISP's news server "nntp2.myisp.com". +Instead of adding an A record for "news" with the same address as "nntp2.myisp.com", you could +put in a CNAME pointing to "nntp2.myisp.com", so that if the IP address of the news server changes, +there is no need to update the record for "news". +.br +To implement this with pdnsd, you could add the following section to your configuration file: +.br +.DS L + + rr { + name = news; + cname = nntp2.myisp.com; + owner = localhost; + } +.DE + +.TP +.B mx=\fIstring\fP,\fInumber\fP; +Defines an MX (mail exchange) record. The string is the host name of the mail server in dotted notation (see name). +The number specifies the preference level. +.br +When you send mail to someone, your mail typically goes from your E-mail client to an SMTP server. +The SMTP server then checks for the MX record of the domain in the E-mail address. +For example, with joe@example.com, it would look for the MX record for example.com and find +that the name of mail server for that domain is, say, mail.example.com. +The SMTP server then gets the A record for mail.example.com, and connects to the mail server. +.br +If there are multiple MX records, the SMTP server will pick one based on the preference level +(starting with the lowest preference number, working its way up). +.br +Don't define MX records with pdnsd unless you know what you're doing. +.TP +.B owner=\fIstring\fP; +or +.PD 0 +.TP +.PD +.B ns=\fIstring\fP; +Defines an NS (name server) record. Specifies the name of the host which should be authoritative for the records +you defined in the rr section. This is typically the host pdnsd runs on. +.br +\fINote:\fP In previous versions of pdnsd this option had to be specified before +any a, ptr, cname, mx or soa entries. +In version 1.2, the restrictions on this option are same as the options just mentioned, +and it must listed after the name= option. +This can be a pain if you want to use an old config file which specifies owner= +before name= (sorry about that). +Apart from greater consistency, the advantage is that you can now specify as many NS records as you like (including zero). +.TP +.B soa=\fIstring\fP,\fIstring\fP,\fInumber\fP,\fItimespec\fP,\fItimespec\fP,\fItimespec\fP,\fItimespec\fP; +This defines a soa (start of authority) record. The first string is the +domain name of the server and should be equal to the name you specified as +owner. +.br +The second string specifies the email address of the maintainer of the name +server. It is also specified as a domain name, so you will have to replace the +@ sign in the name with a dot (.) to get the name you have to specify here. +The next parameter (the first number) is the serial number of the record. You +should increment this number if you change the record. +.br +The 4th parameter is the refresh timeout. It specifies after what amount +of time a caching server should attempt to refresh the cached record. +.br +The 5th parameter specifies a time after which a caching server should attempt +to refresh the record after a refresh failure. +.br +The 6th parameter defines the timeout after which a cached record expires if it +has not been refreshed. +.br +The 7th parameter is the ttl that is specified in every rr and should be the +same as given with the ttl option (if you do not specify a ttl, use the default 86400). +.TP +.B txt=\fIstring\fP,...,\fIstring\fP; +\fINew in version 1.2.9:\fP +Defines an TXT record. You can specify one or more strings here. + +.SS neg Section +Every neg section specifies a dns resource record or a dns domain that should be +cached negatively locally. Queries for negatively cached records are always answered +immediatley with an error or an empty answer without querying other hosts as long +as the record is valid. The records defined with neg sections remain +valid until they are explicitely invalidated or deleted by the user using +pdnsd\-ctl. +.br +This is useful if a certain application asks periodically for nonexisting hosts or +RR types and you do not want a query to go out every time the cached record has +timed out. Example: Netscape Communicator will ask for the servers news and mail +on startup if unconfigured. If you do not have a dns search list for your network, +you can inhibit outgoing queries for these by specifying +.br +.DS L + + neg { + name = news; + types = domain; + } + neg { + name = mail; + types = domain; + } +.DE + +in your config file. If you have a search list, you have to repeat that for any +entry in your search list in addition to the entries given above! +.br +In versions 1.1.11 and later, if you negate whole domains this way, all subdomains +will be negated as well. Thus if you specify +.br +neg {name=example.com; types=domain;} in the +config file, this will also negate www.example.com, xxx.adserver.example.com, etc. + +.TP +.B name=\fIstring\fP; +Specifies the name of the domain for which negative cache entries are created. +This option must be specified before the types option. +Names are interpreted as absolute domain names (i.e. pdnsd +assumes they end in the root domain). +You need to specify domain names in dotted notation (example venera.isi.edu.). +.br +Previous versions of pdnsd +required that domain names given in the configuration file ended in a +dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a +dot at the end if it is missing. +.TP +.B ttl=\fItimespec\fP; +Specifies the ttl (time to live) for all resource records in this section after this entry. +This may be redefined. The default is 86400 seconds (=1 day). +.TP +.B types=(domain|\fIrr_type\fP[,\fIrr_type\fP[,\fIrr_type\fP[,...]]]); +Specifies what is to be cached negatively: domain will cache the whole +domain negatively; alternatively, you can specify a comma-separated list of RR types +which are to be cached negatively. You may specify multiple types options, but +domain and the RR types are mutually exclusive. +.br +The RR types are specified using their official names from the RFC's in capitals, +e.g. A, CNAME, NS, PTR, MX, +AAAA, ... +.br +The command pdnsd\-ctl\ list\-rrtypes will give you a complete list +of those types. pdnsd\-ctl is built along with pdnsd +and will be installed in the same directory as the pdnsd binary during make install. + +.SS source Section +Every source section allows you to let pdnsd read the records from a file in an +/etc/hosts-like format. pdnsd will generate records to resolve the entries +address from its host name and vice versa for every entry in the file. This is +normally easier than defining an rr for every of your addresses, since localhost +and your other FQDNs are normally given in /etc/hosts. +.br +The accepted format is as follows: The #\-sign initiates a comment, the rest of +the line from the first occurence of this character on is ignored. Empty lines +are tolerated. +.br +The first entry on a line (predeceded by an arbitrary number of tabs and spaces) +is the IP in dotted notation, the second entry on one line (separated by the +first by an arbitrary number of tabs and spaces) is the FQDN (fully qualified +domain name) for that ip. The rest of the line is ignored by default (in the original +/etc/hosts, it may contain information not needed by pdnsd). + +.TP +.B owner=\fIstring\fP; +Specifies the name of the host pdnsd runs on and that are specified in dns +answers (specifically, nameserver records). +Must be specified before any file entries. +.br +Names are interpreted as absolute domain names (i.e. pdnsd +assumes they end in the root domain). +You need to specify domain names in dotted notation (example venera.isi.edu.). +.br +Previous versions of pdnsd +required that domain names given in the configuration file ended in a +dot, but since version 1.1.8b1-par8, pdnsd automatically assumes a +dot at the end if it is missing. +.TP +.B ttl=\fItimespec\fP; +Specifies the ttl (time to live) for all resource records in this section after +this entry. This may be redefined. The default is 86400 seconds (=1 day). +.TP +.B file=\fIstring\fP; +The string specifies a file name. For every file entry in a source section, +pdnsd will try to load the given file as described above. Failure is indicated +only when the file cannot be opened, malformed entries will be ignored. +.TP +.B serve_aliases=(on|off); +If this is turned on pdnsd will serve the aliases given in a hosts-style file. +These are the third entry in a line of a hosts-style file, which usually give a "short name" for the host. +This may be used to support broken clients without a proper domain-search option. +If no aliases are given in a line of the file, pdnsd behaves as without this option for this line. +.br +This feature was suggested by Bert Frederiks. +.br +It is off by default. +.TP +.B authrec=(on|off); +If this is turned on, pdnsd will create authoritative local records with the data from the hosts file. +Please see the description of the option of the same name in the rr section for a closer description of +what this means. Please note that this only has an effect for files sourced with file options +subsequent to this option. +.br +This is on by default. + +.SS include Section +A configuration file may include other configuration files. +However, only the top-level configuration file may contain global +and server sections, +thus include files are effectively limited to sections that add local definitions to the cache. +.br +Include sections currently only have one type of option, which may be given multiple times within a single section. + +.TP +.B file=\fIstring\fP; +The string specifies a file name. For every file option in an include section, +pdnsd will parse the given file as described above. The file may contain include sections itself, +but as a precaution pdnsd checks that a certain maximum depth is not exceeded to guard against +the possibility of infinite recursion. + +.SH "VERSION" +.PP +This man page is correct for version @fullversion@ of pdnsd. +.SH "SEE ALSO" +.PP +.BR pdnsd (8), +.BR pdnsd\-ctl (8) +.PP +More documentation is available in the \fBdoc/\fP subdirectory of the source, +or in \fB/usr/share/doc/pdnsd/\fP if you are using a binary package. + +.SH AUTHORS + +\fBpdnsd\fP was originally written by Thomas Moestl +.UR + +.UE +and was extensively revised by Paul A. Rombouts +.UR + +.UE +(for versions 1.1.8b1\-par and later). +.PP +Several others have contributed to \fBpdnsd\fP; see files in the source or +\fB/usr/share/doc/pdnsd/\fP directory. +.PP +This man page was automatically generated from the html documentation for \fBpdnsd\fP, +using a customized Perl script written by Paul A. Rombouts. +.PP +Last revised: 19 April 2012 by Paul A. Rombouts diff --git a/jni/pdnsd/doc/pdnsd.conf.in b/jni/pdnsd/doc/pdnsd.conf.in new file mode 100644 index 00000000..e348eb02 --- /dev/null +++ b/jni/pdnsd/doc/pdnsd.conf.in @@ -0,0 +1,143 @@ +// Sample pdnsd configuration file. Must be customized to obtain a working pdnsd setup! +// Read the pdnsd.conf(5) manpage for an explanation of the options. +// Add or remove '#' in front of options you want to disable or enable, respectively. +// Remove '/*' and '*/' to enable complete sections. + +global { + perm_cache=1024; + cache_dir="@cachedir@"; +# pid_file = /var/run/pdnsd.pid; + run_as="@def_id@"; + server_ip = 127.0.0.1; # Use eth0 here if you want to allow other + # machines on your network to query pdnsd. + status_ctl = on; +# paranoid=on; # This option reduces the chance of cache poisoning + # but may make pdnsd less efficient, unfortunately. + query_method=udp_tcp; + min_ttl=15m; # Retain cached entries at least 15 minutes. + max_ttl=1w; # One week. + timeout=10; # Global timeout option (10 seconds). + neg_domain_pol=on; + udpbufsize=1024; # Upper limit on the size of UDP messages. +} + +# The following section is most appropriate if you have a fixed connection to +# the Internet and an ISP which provides good DNS servers. +server { + label= "myisp"; + ip = 192.168.0.1; # Put your ISP's DNS-server address(es) here. +# proxy_only=on; # Do not query any name servers beside your ISP's. + # This may be necessary if you are behind some + # kind of firewall and cannot receive replies + # from outside name servers. + timeout=4; # Server timeout; this may be much shorter + # that the global timeout option. + uptest=if; # Test if the network interface is active. + interface=eth0; # The name of the interface to check. + interval=10m; # Check every 10 minutes. + purge_cache=off; # Keep stale cache entries in case the ISP's + # DNS servers go offline. + edns_query=yes; # Use EDNS for outgoing queries to allow UDP messages + # larger than 512 bytes. May cause trouble with some + # legacy systems. +# exclude=.thepiratebay.org, # If your ISP censors certain names, you may +# .thepiratebay.se, # want to exclude them here, and provide an +# .piratebay.org, # alternative server section below that will +# .piratebay.se; # successfully resolve the names. +} + +/* +# The following section is more appropriate for dial-up connections. +# Read about how to use pdnsd-ctl for dynamic configuration in the documentation. +server { + label= "dialup"; + file = "/etc/ppp/resolv.conf"; # Preferably do not use /etc/resolv.conf + proxy_only=on; + timeout=4; + uptest=if; + interface = ppp0; + interval=10; # Check the interface every 10 seconds. + purge_cache=off; + preset=off; +} +*/ + +/* +# The servers provided by OpenDNS are fast, but they do not reply with +# NXDOMAIN for non-existant domains, instead they supply you with an +# address of one of their search engines. They also lie about the addresses of +# of the search engines of google, microsoft and yahoo. +# If you do not like this behaviour the "reject" option may be useful. +server { + label = "opendns"; + ip = 208.67.222.222, 208.67.220.220; + reject = 208.69.32.0/24, # You may need to add additional address ranges + 208.69.34.0/24, # here if the addresses of their search engines + 208.67.219.0/24; # change. + reject_policy = fail; # If you do not provide any alternative server + # sections, like the following root-server + # example, "negate" may be more appropriate here. + timeout = 4; + uptest = ping; # Test availability using ICMP echo requests. + ping_timeout = 100; # ping test will time out after 10 seconds. + interval = 15m; # Test every 15 minutes. + preset = off; +} +*/ + +/* +# This section is meant for resolving from root servers. +server { + label = "root-servers"; + root_server = discover; # Query the name servers listed below + # to obtain a full list of root servers. + randomize_servers = on; # Give every root server an equal chance + # of being queried. + ip = 198.41.0.4, # This list will be expanded to the full + 192.228.79.201; # list on start up. + timeout = 5; + uptest = query; # Test availability using empty DNS queries. +# query_test_name = .; # To be used if remote servers ignore empty queries. + interval = 30m; # Test every half hour. + ping_timeout = 300; # Test should time out after 30 seconds. + purge_cache = off; +# edns_query = yes; # Use EDNS for outgoing queries to allow UDP messages + # larger than 512 bytes. May cause trouble with some + # legacy systems. + exclude = .localdomain; + policy = included; + preset = off; +} +*/ + +source { + owner=localhost; +# serve_aliases=on; + file="/etc/hosts"; +} + +/* +include {file="/etc/pdnsd.include";} # Read additional definitions from /etc/pdnsd.include. +*/ + +rr { + name=localhost; + reverse=on; + a=127.0.0.1; + owner=localhost; + soa=localhost,root.localhost,42,86400,900,86400,86400; +} + +/* +neg { + name=doubleclick.net; + types=domain; # This will also block xxx.doubleclick.net, etc. +} +*/ + +/* +neg { + name=bad.server.com; # Badly behaved server you don't want to connect to. + types=A,AAAA; +} +*/ diff --git a/jni/pdnsd/doc/txt/doc_makefile b/jni/pdnsd/doc/txt/doc_makefile new file mode 100644 index 00000000..57aa7c11 --- /dev/null +++ b/jni/pdnsd/doc/txt/doc_makefile @@ -0,0 +1,21 @@ +# Makefile for converting pdnsd html documentation to text files. +# This file was based on a Makefile originally written by Thomas Moestl +# and adapted by Paul Rombouts. + + +HTML2TXT=w3m -dump -cols 80 -T text/html + +doc: intro.txt manual.txt faq.txt +.PHONY: doc clean + +intro.txt: ../html/index.html + sed -e 's///-->/g' ../html/index.html | $(HTML2TXT) | sed -e 's/[[:blank:]]\+$$//' > intro.txt + +manual.txt: ../html/doc.html + sed -e 's///-->/g' ../html/doc.html | $(HTML2TXT) | sed -e 's/[[:blank:]]\+$$//' > manual.txt + +faq.txt: ../html/faq.html + sed -e 's///-->/g' ../html/faq.html | $(HTML2TXT) | sed -e 's/[[:blank:]]\+$$//' > faq.txt + +clean: + @rm -fv intro.txt manual.txt faq.txt diff --git a/jni/pdnsd/doc/txt/faq.txt b/jni/pdnsd/doc/txt/faq.txt new file mode 100644 index 00000000..02631610 --- /dev/null +++ b/jni/pdnsd/doc/txt/faq.txt @@ -0,0 +1,227 @@ +The pdnsd FAQ + +Q: There are complete and well-tested name servers around, such as the BIND. + These do also perform caching. Why should I use pdnsd? + + pdnsd does not aim to be a complete name server implementation, such as the + BIND. It is optimized for caching, and you can only specify a small subset + of all dns record types pdnsd knows in your local "zone" definitions. This + of course reduces the code size drastically, and such the memory footprint. + There are some features especially interesting for dialin networks, + ordinary (non-server) internet hosts and computers that are often not + connected to to their network, e.g. notebooks (I originally wrote this + program for use with my notebook). These features are: +A: + * permanent disk cache (useful for frequent power-offs/reboots) + * usually smaller memory footprint (depends on cache size) (see next + question) + * offline-detection prevents hangs (e.g. the typical hang on startup of + some Netscape Navigator versions if not dialled in) + * better control about timeouts (also to prevent hangs) + * better control over the cache + * better run-time control + +------------------------------------------------------------------------------- + + When I look at the process size with ps, top, gtop, or a similar tool, I +Q: see some processes with a total size well above 3.5 MB. This is much more + than e.g. BIND named (about 1.4 MB). Why? + + Really, it is not. pdnsd uses multithreading, not multiprocessing. That + means that the processes share most of their process space. In the + LinuxThreads library or NPTL (Native Posix Thread Libary), which are used + by pdnsd on Linux, in fact the total process address space is shared +A: (although the processes have different stacks, these are in one process + address space). You may check this by looking at the at the process sizes + of the pdnsd threads: all should be the same. The effective size that pdnsd + occupies is thus the size of any of the processes, not the sum of those. + So, pdnsd with empty cache occupies about 800 kB, and the maximum size + should be about the cache size plus this size (in fact, ca 5-10% more). + +------------------------------------------------------------------------------- + +Q: What do I need the status control (option -s) for? + + It enables you to do some things you might or might not need. With it, you + can: + + * query pdnsd's settings at runtime to debug configuration files and see + which servers are regarded to be available +A: * mark servers as available or unavailable, or force a status retest - + very handy if you want to control which servers pdnsd queries, e.g for + muliple dial-up accounts + * delete, invalidate or add DNS records - useful e.g. when you want to + build records for dynamically assigned IP addresses or domain names + * reload pdnsd's configuration file without restarting pdnsd + * print information about the contents of pdnsd's cache. + +------------------------------------------------------------------------------- + +Q: What do I need local records (rr- and source-sections in the config file) + for? + + Some resolver programs, e.g. nslookup, want to look up the name of the + server they are using before doing anything else. This option is for + defining a PTR record for your IP such that those programs get an answer + even if the name server you are caching is not available or does not offer + these records. By extension, you may also define A and SOA records. This + allows you to build very small zones without having to use a "big" name + server. It is NOT intended to replace such a complete server in anything + but VERY small networks. Alternatively, you may start a named on another + host or on the same host on another port and cache it with pdnsd in + addition to other (more distant) name servers. +A: The source section allows you to let pdnsd read in your /etc/hosts file on + startup and serve its contents. This file is used by your local resolver + before it even tries the name servers and usually contains fully-qualified + domain names (FQDNs) for all of the internet addresses your host has. If + you source this file, you usually won't need any additional rr sections. + Sourcing it also allows other hosts (eg. in your local network) to access + the names defined in your hosts file. You can of course just add other + hosts in your local network to the servers hosts file, thus making them + known to your server's resolver and pdnsd (if you sourced that file). + If you don't know what this answer was all about, you should just take the + source section in the sample config file that comes with pdnsd, copy it + into your config file and forget about it. + +------------------------------------------------------------------------------- + + When compiling, I get an error message like +Q: Please define __BYTE_ORDER to be __LITTLE_ENDIAN or __BIG_ENDIAN + What's up? + + Normally, this macros should be defined in your C library's header files. + There are two different methods, most C libraries support both (and pdnsd + honors both): either __BYTE_ORDER is set to __LITTLE_ENDIAN or + __BIG_ENDIAN, or __LITTLE_ENDIAN or __BIG_ENDIAN are directly defined as + macros. + Linux glibc, for example, does set those macros correctly. Never mind. You + just have to know whether your machine is little-endian or big-endian, this + means wheter your machine saves the least significant byte of a word or + double-word first in memory (little-endian) or the most significant first +A: (big-endian). All intel x86 and Alpha machines are little-endian, for + example, while SPARC and PowerPC architectures are big-endian. If your + machine is little-endian, add the following line to your config.h: + #define __BYTE_ORDER __LITTLE_ENDIAN + Likewise, if your machines byte order is big-endian: + #define __BYTE_ORDER __BIG_ENDIAN + Pathological byte orders like pdp-endian are not yet supported really; + However, for the place the endianess is needed, __LITTLE_ENDIAN should do + (it deals only with 16 bits; for all other occurances, ntoh[sl]/hton[sl] is + used). + +------------------------------------------------------------------------------- + + At startup, I get a warning saying: +Q: Uptest command [...] will implicitly be executed as root + What does that mean? + + This warning only occurs if you use the uptest=exec option in your + configuration. It means that the uptest command is run as root because + pdnsd is running as root, and this was not explicitely specified. The idea + is that it may introduce security holes (in the programs being run) when +A: they run as root, and so they shouldn't do that if possible. You can + specify the user that shall run the command by appending its name + comma-separated as string to the uptest_cmd line: + uptest_cmd="",""; + If it is correctly running as root, just append the user string "root" to + the command and the warning will not occur again. + +------------------------------------------------------------------------------- + +Q: I cannot run my uptest_cmd command as root (it says permission denied), + although the pdnsd executable is setuid root. Why? + + pdnsd will drop privileges gained through setuid/setgid before executing + the uptest commands (you shouldn't set the pdnsd executable setuid/setgid +A: anyway). The reason is clear: if you install the pdnsd executable as setuid + root and this wouln't be done, any user could execute shellcode with root + privileges using that option! + +------------------------------------------------------------------------------- + + At startup, I get an error saying: +Q: Bad config file permissions: the file must be only writeable by the user + Why is that? + + pdnsd has an option (uptest=exec) that allows the execution of arbitrary + shell code (for testing whether an interface is up). This must be of course + secured against unauthorized use. One of these protection is the one that + produces the error message: if you routinely run pdnsd, e.g. at system + startup, and your config file is editable for others, someone could change +A: it and insert shell code that is executed in the next pdnsd run -- with + your user privileges! To prevent this, pdnsd will exit if the config file + is writeable by others than the owner. To get rid of this message, just do + chmod go-w + on your config file (for the default file: chmod go-w /etc/pdnsd.conf). You + should also check that the ownership is set correct. + +------------------------------------------------------------------------------- + +Q: serve_aliases does not seem to work. + + Some resolvers (e.g. of the glibc 2.1) seem sometimes not to look up + unmodified names, but the names with an entry of the search path already +A: appended. Since pdnsd will serve short names with this option anyway, you + can delete the search an domain options from your /etc/resolv.conf. This is + reported to work in some cases. + +------------------------------------------------------------------------------- + +Q: Some queries for domains that have many records (e.g. www.gmx.de) fail + mysteriously. + + pdnsd versions prior to 1.1.0 had the tcp server thread disabled by + default. Most resolvers repeat their query using tcp when they receive a +A: truncated answer (the answer is truncated when it exceeds a length of 512 + bytes). You need to recompile pdnsd with the option --enable-tcp-server to + fix this. + +------------------------------------------------------------------------------- + + I am behind some kind of firewall. In the configuration file I have only +Q: listed addresses of name servers on the local (ISP's) network, but pdnsd is + slow and DNS queries frequently time out. + + In some cases pdnsd will not consider the answer of the local name server + authoritative enough, and will try to get answers from the name servers + listed in the authority section of the reply message. If pdnsd is behind a + firewall that blocks the UDP reply packets from remote name servers, pdnsd + will wait in vain for a reply. One solution is to set proxy_only=on in the +A: servers sections of the configuration file. This will prevent pdnsd from + querying name servers that are not listed in the configuration file. + Another solution that can be tried is specifying query_method=tcp_only in + the global section of the configuration file, because a firewall that + blocks UDP packets from outside might still allow outgoing TCP connections + to port 53. + +------------------------------------------------------------------------------- + +Q: Is pdnsd vulnerable to DNS cache poisoning as described in CERT + vulnerability note VU#800113? + + Short answer: Yes. + Somewhat longer answer: The problem is not so much that pdnsd's + implementation is flawed but rather that the DNS protocol currently being + used is fundamentally flawed from a security viewpoint. As long as a more + secure protocol is not in place, all that the developers of pdnsd can do is + to try to tweak the current implementation to make it as difficult as + possible for an attacker to succeed. + From version 1.2.7 onwards, the default for the query_port_start option is +A: 1024, which means that the pdnsd resolver will randomly select source ports + in the range 1024-65535. (In previous versions the default was to let the + kernel select the source ports, which will often result in a more or less + predictable sequence of ports.) It also helps to use a good quality source + of random numbers. On platforms where this is supported, it is preferable + to configure with --with-random-device=/dev/urandom. There is still more + that can be done to make pdnsd less vulnerable, but this remains (as of + this writing) a work in progress. + Please note that pdnsd was designed for small (private) networks, and that + it is generally not recommended to let untrusted users access pdnsd. + +------------------------------------------------------------------------------- + +Thomas Moestl and Paul Rombouts + + +Last revised: 18 August 2008 by Paul Rombouts + diff --git a/jni/pdnsd/doc/txt/intro.txt b/jni/pdnsd/doc/txt/intro.txt new file mode 100644 index 00000000..db1c89e3 --- /dev/null +++ b/jni/pdnsd/doc/txt/intro.txt @@ -0,0 +1,305 @@ +------------------------------------------------------------------------------- + +About pdnsd + +pdnsd is a proxy DNS server with permanent caching (the cache contents are +written to hard disk on exit) that is designed to cope with unreachable or down +DNS servers (for example in dial-in networking). +Since version 1.1.0, pdnsd supports negative caching. + +It is licensed under the GNU General Public License (GPL). This, in short, +means that the sources are distributed togehter with the program, and that you +are free to modify the sources and redistribute them as long as you also +license them under the GPL. You do not need to pay anything for pdnsd. It also +means that there is ABSOLUTELY NO WARRANTY for pdnsd or any part of it. For +details, please read the GPL. + +pdnsd can be used with applications that do DNS lookups, e.g. on startup, and +can't be configured to change that behaviour, to prevent the often minute-long +hangs (or even crashes) that result from stalled DNS queries. Some Netscape +Navigator versions for Unix, for example, expose this behaviour. + +pdnsd is configurable via a file and supports run-time configuration using the +program pdnsd-ctl that comes with pdnsd. This allows you to set the status +flags of servers that pdnsd knows (to influence which servers pdnsd will +query), and the addition, deletion and invalidation of DNS records in pdnsd's +cache. +Parallel name server queries are supported. This is a technique that allows +querying several servers at the same time so that very slow or unavailable +servers will not block the answer for one timeout interval. +Since version 1.0.0, pdnsd has full IPv6 support. + +There is also a limited support for local zone records, intended for defining +1.0.0.127.in-addr.arpa. and localhost. , since some clients request that +information and it must be served even if the cached servers are not available +or do not serve these records. pdnsd may also read your /etc/hosts file (this +file is normally used by your local resolver and usually contains information +for localhost as well as for your machines FQDN) and serve its contents. + +pdnsd was started on Linux, and has since been ported to FreeBSD (and Cygwin +and Darwin). 90% of the source code should be easily portable to POSIX- and +BSD-compatible systems, provided that those systems support the POSIX threads +(pthreads). The rest might need OS-specific rewrites. + +Currently, pdnsd is only compileable by gcc. This should be easy to fix, but I +just do not have documentation for other compilers. If you are not able or do +not want to use gcc, I would recommend you just try to do the minor changes. + +pdnsd must be started as root in some cases (raw sockets are needed for icmp +echoes for the option uptest=ping, and the default port is 53, this must be > +1024 to allow non-root execution). However, pdnsd can be configured to change +it's user and group id to those of a non-privileged user after opening the +sockets needed for this. + +The server should support the full standard DNS queries following the rfcs 1034 +and 1035. As of version 1.0.0, the rfc compliance has been improved again, and +pdnsd is now believed (or hoped?) to be fully rfc-compatible. It completely +follows rfc 2181 (except for one minor issue in the FreeBSD port, see the +documentation). It does not support the following features, of which most are +marked optional, experimental or obsolete in these rfcs: + + * Inverse queries + * Status queries + * Completion queries + * Namespaces other than IN (Internet) + * AXFR and IXFR queries (whole zone transfers); since pdnsd does not maintain + zones, that should not violate the standard + +The following record types, that are extensions to the original DNS standard, +are supported for caching since version 1.2.9 (if you do not need most of them, +you can disable runtime support for the unneeded ones before compiling pdnsd +and save a little cache and executable space, see the source file src/ +rr_types.in): + + * RP (responsible person, RFC 1183) + * AFSDB (AFS database location, RFC 1183) + * X25 (X25 address, RFC 1183) + * ISDN (ISDN number/address, RFC 1183) + * RT (route through, RFC 1183) + * NSAP (Network Service Access Protocol address , RFC 1348) + * PX (X.400/RFC822 mapping information, RFC 1995) + * GPOS (geographic position, deprecated) + * AAAA (IPv6 address, RFC 1886) + * LOC (location, RFC 1876) + * EID (Nimrod EID) + * NIMLOC (Nimrod locator) + * SRV (service record, RFC 2782) + * ATMA (ATM address) + * NAPTR (URI mapping, RFC 2168) + * KX (key exchange, RFC 2230) + * CERT (Certificate record, RFC 4398) + * DS (Delegation Signer, RFC 4034) + * RRSIG (Resource Record Signature, RFC 4034) + * NSEC (Next Secure, RFC 4034) + * DNSKEY (record containing the public key for a zone, RFC 4034) + * NSEC3 (Next Secure version 3, RFC 5155) + * NSEC3PARAM (NSEC3 parameters, RFC 5155) + +Note: This list is incomplete. For the complete list see the source file src/ +rr_types.in. + +There are FreeBSD and OpenBSD ports available for pdnsd (ports/net/pdnsd for +both). Thanks go to Roman Shterenzon for the FreeBSD port Sebastian Stark for +the OpenBSD one! Thanks to Kiyo Kelvin Lee now also runs on the Cygwin +platform! Thanks goes to Rodney Brown for extending portability to the Darwin +(Apple Mac OS X) platform! + +If you have questions left, you should take a look into the FAQ. +Bugfixes, patches and compatability fixes for other OSs are very welcome! + +Features in detail + +This section describes some of pdnsds features in detail. Most of the options +are set in the config file. For more information on the configuration file, see +the documenation page. + + +Uptests + +pdnsd provides several methods to test whether a remote DNS server should be +regarded as available (so that pdnsd can query it), in addition to the obvious +"none" test (the server is always regarded as available, or availability is set +on or off using the pdnsd-ctl utility). These tests are: + + * ping: a given adress is ping'ed in a given interval. If it there is no + response or the host is unreachable, the server is seen to be not available + (for those who don't know: pinging is sending a certain Internet packet + type to a host to which any standard-conformant host is required to reply). + * if: a given network interface is tested whether it is existent, up and + running. If it is not, the server is regarded to be not available. This is + especially useful for ppp and similar interfaces. A special case test for + Linux isdn (ippp*) interfaces is integrated, so that the uptests should + also work for these. + * dev: this is a variant of the if uptest for use with Linux dial-on-demand + ppp interfaces. In addition to performing an if-style interface uptest, it + also tests whether a specified program (e.g. pppd) owns a lock to a given + (modem-) device. + * exec: a given shell command line is executed and the exit status of the + whole command line (which is normally the exit status of the last command) + is evaluated. If it is not zero, the server is regarded to be not + available. This is a very flexible testing method with which it should be + able to perform virtually any needed test. + * query: New in version 1.2: This works like the ping test, except it sends + an (empty) DNS query to the remote server. If the server sends a + well-formed response back within the timeout period (except SERVFAIL), it + will be regarded as available. This test is useful if a remote server does + not respond to ICMP_ECHO requests at all, which unfortunately is quite + common these days. In many cases this test will be a more reliable + indicator of availability than the ones mentioned above. + + +Local Records ("Zones") + +As mentioned above, there are only very basic local record types (ie the record +types that you may use in record declarations in your local configuration for +records that pdnsd shall serve in addion to the cached ones). They are +organized roughly in zones but have not complete zone declarations, so I +generally do not use the term "zone" for them, but rather "local records". +These are the local record types pdnsd can understand: + + * SOA (information about the name server) + * A (domain-name-to-address mapping) + * PTR (pointer, used normally for address-to-domain-name mapping) + * NS (name server, generated automatically by pdnsd for any local record set) + * CNAME (canonical host name) + * MX (mail exchange for the domain) + * TXT (arbitrary text strings, often used for Sender Policy Framework) + +You can specify these records in the configuration file. +You may "source" a file in a format like that used in the /etc/hosts file, that +means that pdnsd reads this file, extracts addresses and domain names from it +and automatically generates A records for name to address mapping, PTR records +for address to name mapping and NS records (name server specifiation) for each +entry in the file. +Records can also be changed dynamically at run time. +A script contributed by Marko Stolle makes pdnsd usable in a DHCP setup using +this feature. + +System requirements + +As mentioned, pdnsd currently runs under Linux, FreeBSD and Cygwin. Other BSD +flavours may or may not work (feedback is very welcome!). The system and +software requirements under Linux are: + + * Kernel version >2.2.0 + * glibc version >2.0.1 (aka libc6) with LinuxThreads (normally included) or + NPTL (Native Posix Thread Library, recommended). + Due to a bug, pdnsd 0.9.8 does not run with glibc2.1.1. This behaviour was + fixed in pdnsd 0.9.9. + * For IPv6: glibc>=2.1 + +The system requirements under FreeBSD are: + + * FreeBSD versions >=2.6 (prior ones may or may not work) + * For IPv6: FreeBSD >=4.0 is recommended (no idea if it runs on prior + versions) + +The common software requirements for all supported systems are: + + * GCC, preferably egcs-2.* or 3.* (other compilers are currently not + supported; the needed patch for another compiler should not be difficult, + however) + * GNU or BSD make + * the standard commands install, grep, sed, awk, touch and which (along with + the REALLY standard ones mv, cp, ln, rm, pwd, test, echo, cat, mkdir, + chown, chmod, tar). In any standard Unix installation, this should be no + problem. + * for hacking and building own packages, you might also need gzip, bzip2, + perl and rpmbuild + + +Download + +If you want to download pdnsd, please visit the download page. + +Authors + +pdnsd was originally written by Thomas Moestl, but is no longer maintained by +him. Paul A. Rombouts has revised large portions of the code and has added a +number of new features. See README.par and the ChangeLog in the source +directory (or /usr/share/doc/pdnsd- if you have installed a binary +package) for more details. If you have questions about the recent +modifications, you can find the email address of the current maintainer at the +end of README.par. + +Daniel Smolik has contributed RedHat RPMs (the most recent RPMs are available +here). +Torben Janssen contributed start scripts for Red Hat Linux. +Soenke J. Peters contributed patches and suggestions for Red Hat compatability. +Wolfgang Ocker has contributed the code and documentation for the server_ip +option. +Markus Mohr contributed a Debian rc script. +Nikita V. Youschenko contributed extensions to the "if" uptest. +Lyonel Vincent extended the serve_aliases option to support an arbitrary number +of aliases. +Sourav K. Mandal wrote the autoconf scripts and contributed many fixes and +suggestions. +Stephan Boettcher contributed the SCHEME= option. +Ron Yorston contributed the uptest for Linux ppp dial-on-demand devices. +Alexandre Nunes fixed some bugs in the autoconf files. +Sverker Wiberg contributed fixes for IPv6. +Carsten Block contributed configure-able rc scripts. +Olaf Kirch contributed a security fix for the run_as code. +Paul Wagland contributed various patches for bind9-compatability and other +issues. +Roman Shterenzon contributed patches and lots of helpful hints for FreeBSD +compatability. +Bernd Leibing has contributed spec file fixes. +Michael Wiedmann has contributed the pdnsd-ctl.8 man page. +Marko Stolle has contributed the contrib/pdnsd_update.pl script that makes +pdnsd usable in a DHCP setup. +P.J. Bostley has contributed patches to get pdnsd working on alpha properly. +Christian Engstler contributed patches for SuSE compatability. +Bjoern Fischer contributed code to make pdnsd leave the case of names in the +cache unchanged. +Marko Stolle contributed the contrib/pdnsd_update.pl script that makes pdnsd +usable in a DHCP setup. +Andrew M. Bishop contributed the support for the label server option and the +pdnsd-ctl interface for using it. +Frank Elsner contributed rc script fixes. +Andreas Steinmetz contributed the code for query_port_start and query_port_end +options. +Mahesh T. Pai contributed the pdnsd.8 man page. +Nikola Kotur contributed the Slackware start-up script. +Kiyo Kelvin Lee contributed a patch for Cygwin support. +Rodney Brown contributed a patch for Darwin (Apple Mac OS X) support. +Jan-Marek Glogowski contributed a patch implementing the use_nss option. + +Special thanks to Bert Frederiks for letting me do a late-night debugging run +on his machine to spot obscure bugs! + +Thanks to the following persons for reporting bugs and being helpful: +David G. Andersen, +Dirk Armbrust, +Daniel Black, +Kevin A. Burton, +Juliusz Chroboczek, +Joachim Dorner, +Stefan Erhardt, +Stefan F?rster, +Mike Hammer, +Jonathan Hudson, +Dan Jacobson, +Byrial Jensen, +Patrick Loschmidt, +James MacLean, +Fraser McCrossan, +Michael M?ller, +Erich Reitz, +Brian Schroeder, +Milan P. Stanic, +Michael Steiner, +Norbert Steinl, +Markus Storm, +Michael Str?der, +Alan Swanson, +Eelco Vriezekolk. + + +------------------------------------------------------------------------------- + +Thomas Moestl and Paul A. Rombouts + + +Last revised: 17 March 2012 by Paul A. Rombouts + diff --git a/jni/pdnsd/doc/txt/manual.txt b/jni/pdnsd/doc/txt/manual.txt new file mode 100644 index 00000000..c7e3e9d2 --- /dev/null +++ b/jni/pdnsd/doc/txt/manual.txt @@ -0,0 +1,2017 @@ + pdnsd Documentation + +This is the "official" pdnsd documentation and reference written by Thomas +Moestl with revisions by Paul A. Rombouts. +This manual is a part of the pdnsd package, and may be distributed in original +or modified form under terms of the GNU General Public License, as published by +the Free Software Foundation; either version 3, or (at your option) any later +version. +You can find a copy of the GNU GPL in the file COPYING in the source or +documentation directory. +This manual is up-to-date for version 1.2.9b. For older documentation, please +refer to the doc directory of the respective pdnsd package. +If you want a quicker introduction to pdnsd, you can try some of the HOWTOs +available on the web. For Apple Mac users, Brian Wells has published a good +HOWTO at http://web.mac.com/brianwells/main/pdnsd.html. + +0. Installation + +0.1 Installing binary RPM's + +To install a binary RPM, just do + +rpm -i pdnsd-.rpm + +This should install pretty much everything automatically. The only thing left +for you to do is adapt your configuration file (stored in /etc/pdnsd.conf) +according to your needs (see below). In the Red Hat and SuSE RPMs, a start +script is also installed; read the section 0.4, Start at Boot Time about that. + +0.2 Building RPM's + +It is possible to build a binary RPM from a source package using the command + +rpmbuild --rebuild pdnsd-.src.rpm + +or alternatively from a tarball using the command + +rpmbuild -tb pdnsd-.tar.gz + +You can do this as root, but it is safer to build a binary package first as a +normal user, and then, when all has gone well, install the resulting binary +package as root as in the previous section. How to build an RPM package without +being root is described at http://www.ibm.com/developerworks/linux/library/ +l-rpm1/. + +Several pdnsd-specific options are available when building RPM packages: + +--with isdn Has the same effect as --enable-isdn (see below). + +--without poll Has the same effect as --disable-poll (see below). + +--without nptl Has the same effect as --with-thread-lib=linuxthreads ( + see below). + +--with ipv6 Has the same effect as --enable-ipv6 (see below). + +--without tcpqueries Has the same effect as --disable-tcp-queries (see below + ). + +--without debug Has the same effect as --with-debug=0 (see below). + +--define "distro < Has the same effect as --with-distribution= ( +distro>" see below). + +--define "run_as_user Has the same effect as --with-default-id= (see +" below). + For RPMs the default is "pdnsd". + + If the user defined by the previous option does not +--define "run_as_uid < exist when the RPM is installed, the pre-install script +uid>" will try to create a new user with numerical id . + The default is to let the system choose the numerical + id at install time. + +--define "cachedir < Has the same effect as --with-cachedir= (see below +dir>" ). + +You can also configure which compiler flags will be used by setting the +environment variable CFLAGS. Using a bash shell, you can do that on the command +line like this: CFLAGS="-O1 -Wall" rpmbuild ... +This is useful if you prefer a different level of optimization, for instance. + +0.3 Installing from pure sources (tar archives or git repositories) + +0.3.1 Setting up the source code tree + +Source code is available in the form of snapshots (tarballs) or a git +repository with the very latest development code and a (nearly) complete +history of all the revisions. Cloning a git repository is useful if you need a +recent fix or feature that is not yet contained in a main release or you want +to participate in pdnsd development. Otherwise you will probably find the +tarballs more convenient because they are much more compact. + +0.3.1.1 Unpacking a tar archive + +The pdsnsd snapshot releases come in the form of a gzip'ed tar archive. To +decompress it (using a modern tar) do + +tar -xzf pdnsd-.tar.gz + +If your tar doesn't do this, use: + +gzip -dc pdnsd-.tar.gz | tar -xf - + +0.3.1.2 Cloning a git repository + +To clone a git repository you need to install, if not already installed, the +git version control system, which is available as a package in most modern +Linux distributions. Then run the command: + +git clone git://gitorious.org/pdnsd/pdnsd.git pdnsd + +In rare cases, if you are behind some kind of firewall, the special git +protocol can't be used and you will need to fall back to the http protocol. See +the gitorious.org website or git documentation for more information. + +0.3.2 Configuring the source + +Change into the pdnsd source directory and run configure. It takes the +following command line options (if you do not specify an option, defaults will +be used): + + Specify the prefix directory. The pdnsd files are + installed in subdirectories of the prefix, the +--prefix=dir pdnsd and pdnsd-ctl executables are for example + installed in the sbin subdirectory of the prefix. + The default for this is /usr/local; you might want + to set this to /usr (using --prefix=/usr). + + Specify the config directory. pdnsd expects its + pdnsd.conf file to reside there if the -c option is +--sysconfdir=dir not given at startup. The default for this is the + etc subdirectory of your prefix, e.g. /usr/local/ + etc if you did not specify a prefix. To set this + e.g. to /etc, use --sysconfdir=/etc. + +--with-distribution= Specify target distribution (default=Generic; +distro others: RedHat, SuSE, Debian) + See below for the effect of these settings. + + Change compilation target platform (default: + autodetect; others: Linux, BSD, Cygwin). + autodetect will attempt to detect whether you are +--with-target=platform using Linux, *BSD or Cygwin and should normally be + sufficient. If this does not work, try specifying + your system manually (for the Darwin platform + (Apple Mac OS X) specify BSD here). + + Default directory for pdnsd cache (default=/var/ +--with-cachedir=dir cache/pdnsd) + This setting can be changed via config file + settings when pdnsd has been built. + + Number of hash buckets to use (default=1024). The + default should be sufficient for most purposes, but + if you want to store a large number of names in the +--with-hash-buckets=num cache, cache lookups may be faster if the number of + hash buckets is comparable to the number of names + stored in the cache. The number actually used is + the smallest power of two greater or equal to the + number specified here. + + Enable ISDN support + This option will work only on Linux and may cause +--enable-isdn problems with 2.0.x or old 2.2.x kernels. You will + need it for a proper if uptest under Linux for ISDN + ppp devices. + +--disable-ipv4 Disable IPv4 networking support (default=enabled) + + Enable IPv6 networking support. +--enable-ipv6 If your OS does support IPv6 properly, you should + be able to serve also IPv4 queries using this. + Normally, this is disabled and you won't need it. + +--disable-ipv4-startup Disable IPv4 on pdnsd startup by default (default= + enabled) + + Enable IPV6 on pdnsd startup by default (default= + IPv4). These options are only defaults, you can +--enable-ipv6-startup specify on the command line or in the config files + which IP version will really be used. Normally, you + won't need to change these. + +--disable-udp-queries Disable UDP as query method. You shouldn't need to + change this. + + Disable TCP as query method. This only effects the + querying of name servers by pdnsd, not the ability + of pdnsd to answer TCP queries from clients. TCP + queries are slower than UDP queries, but can be +--disable-tcp-queries more secure against certain types of attacks and + are able to handle large answers. For normal use + this can be disabled. (Note that the default has + changed: TCP-query support is now compiled in by + default, but it still depends on the run-time + options whether it is actually used.) + + Specify the query method (default=udponly, others: + tcponly, tcpudp, udptcp). If you have enabled both + UDP and TCP queries, this lets you control which + query method pdnsd will use by default. tcpudp will + try TCP first and fall back to UDP if TCP is not +--with-query-method=qm supported by the server; udptcp will try UDP first + and, if the answer was truncated, will repeat the + query using TCP. udponly and tcponly should be + clear. Note that this only effects the compiled-in + default; the query method can still be changed + using command-line options or options in the + configuration file. + + Disable the TCP server. In this case pdnsd will not +--disable-tcp-server be able to respond to TCP queries from clients. + This may cause problems with very large answers. + + Disable the UDP source address discovery. + You need this only if you have trouble with +--disable-src-addr-disc messages saying "could not discover udp source + address". + For the Cygwin target, this option is disabled by + default. + +--disable-poll Disable poll(2) and use select(2) (default=enabled) + You will normally not need this. + + Since version 1.2.9 this option is obsolete and + ignored. It is now possible to configure for each +--disable-new-rrs RR type separately whether it is cacheable by pdnsd + by editing the file src/rr_types.in. The comments + in this file explain how to do this. + + Enforce strict RFC 2181 compliance. + This will cause pdnsd to reject DNS answers with +--enable-strict-rfc2181 incorrect timestamp settings (multiple RRs of the + same type and for the same domain with different + TTLs). Normally not needed. + + This option is obsolete. Since version 1.2, pdnsd +--enable-underscores places no restrictions on the types of characters + in domain names (there are still a few restrictions + for locally defined names, though). + + Specify random device; default: C Library random() + PRNG + pdnsd uses (pseudo-) random numbers as query IDs + for security reasons (this makes forging DNS + answers more difficult). This option controls where + pdnsd gets these from. The default is the C library + random() function, which is relatively weak. You + can specify a device like /dev/urandom here if you +--with-random-device= like; pdnsd will read random numbers from it +device 16-bit-wise. /dev/urandom is present under Linux + and most BSD derivates. You should not use /dev/ + random - it is more secure, but may block and delay + pdnsd's answers for a long time. + You can specify arc4random to use the BSD + arc4random() library function (default for FreeBSD + target), which is considered safe. + You can also specify random as device to use the C + Library random() function (described above). + + Specify default user for pdnsd (default=nobody). + This is the user that will be entered for the +--with-default-id=user run_as option in the config file (see below) that + will be installed during make install. You can + change this any time in your config file. + + Specify debugging level. Normally you can safely + switch debugging off by setting the level to 0. + This will increase speed (although only marginally) + and save space in the executable (only about 12kB). + However, more significant may be the savings in + stack space, especially if pdnsd is put under heavy + load and there are many simultaneous running + threads. + Presently the only defined debug levels are in the + range 0 - 9. Setting the level to 9 enables hex +--with-debug=level dumps of the queries and replies pdnsd receives and + should normally not be needed. Debug output will + only be generated if you turn on special switches; + it might be useful for debugging your config files, + so I recommend using the default (1). However, if + you use pdnsd under heavy load, a better strategy + may be to compile one version of pdnsd without + debug support (configured with --with-debug=0) for + production use, and one version with with debug + support (e.g. --with-debug=9) for diagnostic + purposes. + +--with-verbosity=level Specify default message verbosity. The default + should be ok. + + Enable RCS IDs in executables (default=disabled). +--enable-rcsids For personal use, there is no need to do this. If + you build rpm's, it might have advantages. + + Enable subsequent tcp queries. The DNS protocol + standard requires that servers must be capable of + answering multiple subsequent queries that are sent + over the same tcp connection, and that the server + may only close the connection by himself after a + certain timeout. This feature is rarely used, but +--enable-tcp-subseq may make denial-of-service attacks easier, as it + allows for an attacker to hold a connection open a + long time (although the attacker's IP is most + likely revealed then). For full standard + compliance, you should use this option. If you do + not use --enable-tcp-server, is option is not + honored. + + Specify default tcp query timeout after which the + connection is closed if no full query has been +--with-tcp-qtimeout=secs received. The default is 30s. You can also change + this option at run time using the tcp_qtimeout + config file option. If you do not use + --enable-tcp-server, is option is not honored. + + Specify the default number of queries that can be + executed in parallel. You can also change this +--with-par-queries=num option at run time using the par_queries config + file option. See the description of that option for + an explanation of what it really does. + The default for this option is 2. + + New in version 1.2.9b: Specify the maximum number + of IP addresses that can be used per nameserver + obtained from NS records (when resolving names + recursively). Just one IP address per nameserver is + sufficient in the vast majority of cases (and this +--with-max-nameserver-ips was the strategy used by pdnsd in previous +=num versions), but in rare cases this will cause + unnecessary resolve failures if the address chosen + for each nameserver happens to be unreachable while + the other addresses would lead to successful + resolution. + The default for this option is 3. + + Added by Paul Rombouts: Use this option if you + experience problems with signal handling under + Linux. The usual symptom is that pdnsd fails to + save the cache to disk, and /var/cache/pdnsd/ + pdnsd.cache remains empty. If you experience this + kind of trouble, try reconfiguring with different + values for the --with-thread-lib option. The + allowable values are linuxthreads (or lt for + short), linuxthreads2 (or lt2 for short), and nptl. + By default the configure script tries to detect +--with-thread-lib=lib automatically whether linuxthreads or nptl is more + appropriate for your system, but the method used is + not foolproof. Look for the line: checking if this + is an NPTL-based system... + If the automatic test mistakenly indentifies the + thread library on your system as NPTL based, you + should reconfigure with --with-thread-lib=lt and + recompile. If the result of the automatic test is + "no" or if --with-thread-lib=lt does not have the + desired effect, try again using --with-thread-lib= + lt2 . + +Normally, you will need only --prefix, --sysconfdir and --with-distribution. If +you specify your distribution using --with-distribution, this has the following +effects: + + * An rc script is copied in the appropriate localtion, which enables pdnsd to + start at machine boot time (see 0.4) + * Distribution-specific portions might be included in the generated + pdnsd.spec file (only important if you want to build rpm archives + yourself). + +If you choose Generic, no rc script is installed, and a generic spec file is +generated. +Further instructions are in the INSTALL document in the pdnsd source directory. +./configure --help will give you a list of all supported command line options. + +Note added by Paul Rombouts: Some people may want change the compiler +optimization flag. I use the -O2 flag, but it might be safer to use a lower +level of optimization or no optimization at all. In that case prefix the +configure command with the desired compiler flags like this (assuming you're +using a bash shell): + +CFLAGS="-O1 -Wall" ./configure ... + + +0.3.3 Building & installing + +Type make in the source directory. Should work by now. +To install, type make install or do the installation by hand (see 0.3.4). +make install will do the following ($prefix is the prefix directory; see +above): + + 1. copies pdnsd to $(prefix)/sbin/ + 2. copies pdnsd-ctl to $(prefix)/sbin/ + 3. copies docs/pdnsd.conf.sample (a sample configuration) to the pdnsd config + directory. + 4. creates your cache directory if it is not there. After installation, you + should check the file permissions and create or edit /etc/pdnsd.conf to fit + your needs (see below). If you use the run_as option, please make sure that + your cache directory is owned by the user you specified with this option! + +You must be root for this installation! +Security notes: never make the pdnsd cache directory writeable for untrusted +users, or you will get several security holes: the users might modify the cache +contents, or plant dangerous links. +If you use a pidfile, you should be aware that you introduce security problems +if you place the pidfile in a directory in a NFS filesystem that is writeable +for untrusted users. Generally, the pidfile directory (typically /var/run) +should not be writeable for untrusted users. + +0.3.4 Manual installation + +For a manual installation, you need to do the following steps: + + 1. Copy pdnsd and pdnsd-ctl from your build directory to an appropriate + location (e.g. /usr/sbin). + 2. Copy docs/pdnsd.conf into the directory you want it to reside (/etc by + default, and change it according to your needs (see below). + 3. Create your caching directory; default is /var/cache/pdnsd (you may change + this in your pdnsd.conf); Permissions should be at max rwxr-xr-x (if you + want to protect your cache and status socket, make it rwx------). + +Thats it! + +0.4 Start at boot time + +In the src/rc folder of the pdnsd distribution are start scripts for pdnsd +designed for different Linux distros. There are scripts for SuSE, Redhat, +Debian, Arch Linux and Slackware now. +The start scripts are automatically installed during RPM install, and also +during make install if you specified your distro. +For Slackware Linux there is a start-up script contributed by Nikola Kotur, but +presently it must be installed manually. See src/rc/README and src/rc/Slackware +/rc.pdnsd for details. + +0.4.1 SuSE Linux startup + +rc/SuSE/pdnsd is a start script for SuSE Linux. It was tested for 6.? but +should run on some versions below. You can do make install as root in the rc/ +SuSE directory to install it, or you can install manually: + +manual installation + +For manual installation, copy rc/SuSE/pdnsd into /sbin/init.d/, go to /sbin/ +init.d/rc2.d/ and create there the following two symlinks: +S11pdnsd to ../pdnsd (do ln -s ../pdnsd S11pdnsd in that dir) +K34pdnsd to ../pdnsd (do ln -s ../pdnsd K34pdnsd in that dir) +The numbers dictate the order different services are started and might need to +be modified. Then edit your /etc/rc.config file and add the line START_PDNSD= +yes to start pdnsd at boot time. + +If you used the make install command, START_PDNSD=yes has been appended to your +/etc/rc.config file, causing pdnsd to be started at boot time. If you don't +want that, change the yes into no. + +This start script was created from /sbin/init.d/skeleton by me, so the most is +copyrighted by SuSE. They put it under the GPL, however, so the license stated +in COPYING also applies to this script. There is NO WARRANTY OF ANY KIND on +these scripts. This is no official SuSE script, and SuSE naturally does NO +support for it. + +0.4.2 Red Hat Linux startup + +rc/Redhat/pdnsd is a start script for Red Hat Linux. It was contibuted by +Torben Janssen. +This was tested for 6.1 but should run on 5.0+. You can do make install as root +in the rc/Redhat directory to install it, or you can install manually: + +manual installation + +For manual installation, copy rc/Redhat/pdnsd into /etc/rc.d/init.d/ +Then go to /etc/rc.d/rc3.d and create there the following symlink: +S78pdnsd -> ../init.d/pdnsd (do ln -f -s ../init.d/pdnsd S78pdnsd in that dir) +Then go to /etc/rc.d/rc0.d and create there the following symlink: +K78pdnsd -> ../init.d/pdnsd (do ln -f -s ../init.d/pdnsd K78pdnsd in that dir) +Then go to /etc/rc.d/rc6.d and create there the following symlink: +K78pdnsd -> ../init.d/pdnsd (do ln -f -s ../init.d/pdnsd K78pdnsd in that dir) + +This script is also covered by license stated in COPYING. Again, there is NO +WARRANTY OF ANY KIND on these scripts. This is no offical Redhat script, and +Redhat naturally does NO support for it + +0.5 Notes for FreeBSD users + +The special handling of ISDN ppp devices is only supported on Linux. It is not +needed in FreeBSD, the normal device handling also works fine with isdn4bsd +devices. +When compiled for FreeBSD, pdnsd as a small RFC compatability issue: RFC2181 +demands answers on dns querys to be sent with the same source address the query +packet went to. In seldom cases, this will not be the case, because the kernel +selects the source address depending on the interface that was used for sending +the answer. +Setting the source address currently does not work for IPv4. I have written a +kernel patch that will provide an easy way to program this. We'll see if or +when it gets commited. + + + +1 Invocation + +When invoking pdnsd, you can specify various options at the command line. +Command line options always override config file options. The various --noX +options are present to override config file options. + +pdnsd --help (or -h) gives you an overview of the pdnsd command line options. + +pdnsd --version (or -V for short) prints licence and version information. + +To start pdnsd as background daemon, specifiy --daemon (or -d for short) on the +command line. Diagnostic and error messages after the actual daemon start will +be printed to the syslog instead of the console. --nodaemon will disable this. + +When starting pdnsd as a daemon, the -p option may be helpful: It writes the +pid of the server process to the file of the name given as argument to this +option. +Example: pdnsd -d -p /var/run/pdnsd.pid + +If you want to specify a configuration file other than /etc/pdnsd.conf, specify +-c or --config-file on the command line, followed by a filename. + +If pdnsd was compiled with debugging support, you may specify -g or --debug on +the command line. This will cause extra diagnostic messages to be printed. When +pdnsd runs in daemon mode, the messages will be written to the pdnsd.debug file +in your cache directory. --nodebug disables debugging. + +pdnsd -vn sets the verbosity level of pdnsd. n is normally a digit from 0 to 3, +where 0 means normal operation, while 3 will most verbose. Level 9 can be used +in combination with the --debug option for very extensive debug information. +Note: The current implementation mostly ignores the verbosity level, so you may +not notice much difference between the various levels. + +The option -s or --status enables the status control socket. This is a named +socket in the cache directory called pdnsd.status. This socket allows run-time +configuration of pdnsd using the utility pdnsd-ctl. See below for more details +about pdnsd-ctl. --nostatus disables status control. See also the configuration +option status_ctl in the global section. + +The option --notcp disables the seldom needed TCP server thread, which may save +you some resources. -t or --tcp will enable it. See also the tcp_server +configuration option. + +Using the -m option, you can select the method pdnsd uses to query other name +servers. Following methods are supported (see also the query_method +configuration option): +-muo: pdnsd will use UDP only. This is the fastest method, and should be +supported by all name servers on the Internet. +-mto: pdnsd will use TCP only. TCP queries usually take longer time than UDP +queries, but are more secure against certain attacks, where an attacker tries +to guess your query id and to send forged answers. TCP queries are not +supported by some name servers. +-mtu: pdnsd will try to use TCP, and will fall back to UDP if its connection is +refused or times out. +-mut: New in version 1.2.5: pdnsd will try to use UDP, and will repeat the +query using TCP if the UDP reply was truncated (i.e. the tc bit is set). This +is the behaviour recommended by the DNS standards. + +The -4 option switches to IPv4 mode, providing pdnsd was compiled with IPv4 +support. +The -6 option switches to IPv6 mode, providing pdnsd was compiled with IPv6 +support. +The -a option is only available when pdnsd was compiled with both IPv4 and IPv6 +support. With this option, pdnsd will try to detect automatically if a system +supports IPv6, and fall back to IPv4 otherwise. + +With -i prefix or --ipv4_6_prefix=prefix you can set the prefix pdnsd uses +(when running in IPv6 mode) to map IPv4 addresses in the configuration file to +IPv6 addresses. There is also a corresponding option for the config file, see +below. Must be a valid IPv6 address. The default is ::ffff:0.0.0.0 + +2 The configuration file + +This section describes the layout of the configuration file and the available +configuration options. The default location of the file is /etc/pdnsd.conf. +This may be changed with the -c command line option. An example pdnsd.conf +comes with the pdnsd distribution in the docs directory and will be installed +to /etc/ by make install. + +2.1 Layout + +The configuration file is divided into sections. Each section is prefixed with +the section name and opening curlies ({) and closed with closing curlies (}). +In each section, configuration options can be given in the form +option_name=option_value; +Option value may be a string literal, a number, a time specification or a +constant. In previous versions of pdnsd strings had to be enclosed in quotes +("), but since version 1.1.10 this is no longer necessary, unless a string +contains a special character such as whitespace, a token that normally starts a +comment, or one of ",;{}\". Since version 1.2.9 a backslash (\) inside a string +is interpreted as an escape character, so it is possible to include special +characters in strings (both quoted or unquoted) by preceding them with a +backslash. Some escape sequences are in interpreted as in the C programming +language, e.g. \t becomes a tab, \n becomes a new-line control char. +A time specification consists a sequence of digits followed by a one-letter +suffix. The following suffixes are recognized: s (seconds), m (minutes), h +(hours), d (days) and w (weeks). If the suffix is missing, seconds are assumed. +If several time specifications are concatenated, their values are added +together; e.g. 2h30m is interpreted as 2*60*60 + 30*60 = 9000 seconds. +Some options take more than one value; in this case, the values are separated +with commas. +If you may supply one of a set of possible values to an option, this is noted +in the documentation as (option1|option2|option3|...) +The constants true|false and yes|no are accepted as synonyms for the constants +on|off. +Comments may be enclosed in /* and */, nested comments are possible. If the # +sign or two slashes (//) appear in the configuration file, everything from +these signs to the end of the current line is regarded as a comment and +ignored. +There are examples for nearly all options in the sample config file. + +2.1.1 global Section + +The global section specifies parameters that affect the overall behaviour of +the server. If you specify multiple global sections, the settings of those +later in the file will overwrite the earlier given values. +These are the possible options: + + +perm_cache=(number|off); +Switch the disk cache off or supply a maximum cache size in kB. If the disk +cache is switched off, 8 bytes will still be written to disk. The memory cache +is always 10kB larger than the file cache. This value is 2048 (2 MB) by +default. + +cache_dir=string; +Set the directory you want to keep the cache in. The default is "/var/cache/ +pdnsd" (unless pdnsd was compiled with a different default). + +server_port=number; +Set the server port. This is especially useful when you want to start the +server and are not root. Note that you may also not specify uptest=ping in the +server section as non-root. +The default port is 53, the RFC-standard one. Note that you should only use +non-standard ports when you only need clients on your machine to communicate +with the server; others will probably fail if the try to contact the server on +the basis of an NS record, since the A record that supplies the address for +(among others) name servers does not have a port number specification. + +server_ip=string; +or +interface=string; +Set the IP address pdnsd listens on for requests. This can be useful when the +host has several interfaces and you want pdnsd not to listen on all interfaces. +For example, it is possible to bind pdnsd to listen on 127.0.0.2 to allow pdnsd +to be a forwarder for BIND. The default setting for this option is server_ip= +any, which means that pdnsd will listen on all of your local interfaces. +Presently you can only specify one address here; if you want pdnsd to listen on +multiple interfaces but not all you will have to specify server_ip=any and use +firewall rules to restrict access. +The IP address used to need quotation marks around it, but since version 1.1.10 +this is no longer necessary. +If pdnsd has been compiled with both IPv4 and IPv6 support, and you want to +specify an IPv6 address here, then unless pdnsd was compiled to start up in +IPv6 mode by default, you will need to use the -6 command-line option or set +run_ipv4=off first (see below) in order to ensure that the IPv6 address is +parsed correctly. +If pdnsd is running in IPv6 mode and you specify an IPv4 address here, it will +automatically be mapped to an IPv6 address. +New in version 1.2: You may also give the name of an interface such as "lo" or +"eth0" here, instead of an IP address (this has been tested on Linux, and may +or may not work on other platforms). pdnsd will not bind to the interface name, +but will look up the address of the interface at start-up and listen on that +address. If the address of the interface changes while pdnsd is running, pdnsd +will not notice that. You will need to restart pdnsd in that case. + +outgoing_ip=string; +or +outside_interface=string; +New in version 1.2.9: Set the IP address of the interface used by pdnsd for +outgoing queries. This can be useful when the host has several interfaces and +you want pdnsd to send outgoing queries via only one of them. For example, if +pdnsd is running on a host with one interface with IP address 192.168.1.1 +connected to the local network, and another with IP address 123.xxx.yyy.zzz +connected to the internet, you may specify server_ip=192.168.1.1 and +outgoing_ip=123.xxx.yyy.zzz to enforce that pdnsd only responds to queries +received from the local network, and only sends outgoing queries via the +interface connected to the internet. +The default setting for this option is any, which means that the kernel is free +to decide which interface to use. Like with the server_ip option, you may also +give the name of an interface here, instead of an IP address. + +linkdown_kluge=(on|off); +This option enables a kluge that some people might need: when all servers are +marked down, with this option set the cache is not even used when a query is +received, and a DNS error is returned in any case. The only exception from this +is that local records (as specified in rr and source sections are still served +normally. In general, you probably want to get cached entries even when the +network is down, so this defaults to off. + +max_ttl=timespec; +This option sets the maximum time a record is held in cache. All dns resource +records have a time to live field that says for what period of time the record +may be cached before it needs to be requeried. If this is more than the value +given with max_ttl, this time to live value is set to max_ttl. This is done to +prevent records from being cached an inappropriate long period of time, because +that is almost never a good thing to do. Default is 604800s (one week). + +min_ttl=timespec; +This option sets the minimum time a record is held in cache. All dns resource +records have a time to live field that says for what period of time the record +may be cached before it needs to be requeried. If this is less than the value +given with min_ttl, this time to live value is set to min_ttl. Default is 120 +seconds. + +neg_ttl=timespec; +This option sets the time that negatively cached records will remain valid in +the cache if no time to live can be determined. This is always the case when +whole domains are being cached negatively, and additionally when record types +are cached negatively for a domain for which no SOA record is known to pdnsd. +If a SOA is present, the ttl of the SOA is taken. + +neg_rrs_pol=(on|off|auth|default); +This sets the RR set policy for negative caching; this tells pdnsd under which +circumstances it should cache a record type negatively for a certain domain. +off will turn the negative caching of record types off, on will always add a +negative cache entry when a name server did not return a record type we asked +it for, and auth will only add such entries if the answer came from an +authoritative name server for that domain. +New in version 1.2.8: The default setting will add a negatively cached record +if either the answer was authoritive or the answer indicated the name server +had "recursion available" while the query explicitly requested such recursion. +The preset is "default" (used to be auth). + +neg_domain_pol=(on|off|auth); +This is analogue to neg_rrs_pol for whole domain negative caching. It should be +safe to set this on, because I have not seen a caching server that will falsely +claim that a domain does not exist. +The default is auth. + +run_as=string; +This option allows you to let pdnsd change its user and group id after +operations that needed privileges have been done. This helps minimize security +risks and is therefore recommended. The supplied string gives a user name whose +user id and primary group id are taken. +A little more details: after reading the config file, becoming a daemon (if +specified) and starting the server status thread, the main thread changes its +gid and uid, as do all newly created threads thereafter. By taking another uid +and gid, those threads run with the privileges of the specified user. Under +Linux and FreeBSD, the server status thread runs with the original privileges +only when the strict_setuid option is set to off (see below, on by default), +because these may be needed for exec uptests. The manager thread also retains +its original privileges in this case. You should take care that the user you +specify has write permissions on your cache file and status pipe (if you need a +status pipe). You should look out for error messages like "permission denied" +and "operation not permitted" to discover permission problems. + +strict_setuid=(on|off); +When used together with the run_as option, this option lets you specify that +all threads of the program will run with the privileges of the run_as user. +This provides higher security than the normal run_as option, but is not always +possible. See the run_as option for further discussion. +This option is on by default. +Note that this option has no effect on Non-Linux systems. + +paranoid=(on|off); +Normally, pdnsd queries all servers in recursive mode (i.e. instructs servers +to query other servers themselves if possible, and to give back answers for +domains that may not be in its authority), and accepts additional records with +information for servers that are not in the authority of the queried server. +This opens the possibility of so-called cache poisoning: a malicious attacker +might set up a dns server that, when queried, returns forged additional +records. This way, he might replace trusted servers with his own ones by making +your dns server return bad IP addresses. This option protects you from cache +poisoning by rejecting additional records that do not describe domains in the +queried servers authority space and not doing recursive queries any more. An +exception to this rule are the servers you specify in your config file, which +are trusted. +The penalty is a possible performance decrease, in particular, more queries +might be necessary for the same operation. +You should also notice that there may be other similar security problems, which +are essentially problems of the DNS, i.e. any "traditional" server has them +(the DNS security extensions solve these problems, but are not widely +supported). One of this vulnerabilities is that an attacker may bombard you +with forged answers in hopes that one may match a query you have done. If you +have done such a query, one in 65536 forged packets will be succesful (i.e. an +average packet count of 32768 is needed for that attack). pdnsd can use TCP for +queries, which has a slightly higher overhead, but is much less vulnerable to +such attacks on sane operating systems. Also, pdnsd chooses random query ids, +so that an attacker cannot take a shortcut. If the attacker is able to listen +to your network traffic, this attack is relatively easy, though. +This vulnerability is not pdnsd's fault, and is possible using any conventional +name server (pdnsd is perhaps a little more secured against this type of +attacks if you make it use TCP). +The paranoid option is off by default. + +ignore_cd=(on|off); +New in version 1.2.8: This option lets you specify that the CD bit of a DNS +query will be ignored. Otherwise pdnsd will reply FORMERR to clients that set +this bit in a query. It is safe to enable this option, as the CD bit refers to +'Checking Disabled' which means that the client will accept non-authenticated +data. +This option is on by default. Turn it off if you want the old behaviour (before +version 1.2.8). + +scheme_file=string; +In addition to normal uptests, you may specify that some servers shall only be +queried when a certain pcmcia-cs scheme is active (only under linux). For that, +pdnsd needs to know where the file resides that holds the pcmcia scheme +information. Normally, this is either /var/lib/pcmcia/scheme or /var/state/ +pcmcia/scheme. + +status_ctl=(on|off); +This has the same effect as the -s command line option: the status control is +enabled when on is specified. +Added by Paul Rombouts: Note that pdnsd-ctl allows run-time configuration of +pdnsd, even the IP addesses of the name servers can be changed. If you're not +using pdnsd-ctl and you want maximum security, you should not enable this +option. It is disabled by default. + +daemon=(on|off); +This has the same effect as the -d command line option: the daemon mode is +enabled when on is specified. +Default is off. + +tcp_server=(on|off); +tcp_server=on has the same effect as the -t or --tcp command-line option: it +enables TCP serving. Similarly, tcp_server=off is like the --notcp command-line +option. +Default is on. + +pid_file=string; +This has the same effect as the -p command line option: you can specify a file +that pdnsd will write its pid into when it starts in daemon mode. + +verbosity=number; +This has the same effect as the -v command line option: you can set the +verbosity of pdnsd's messages with it. The argument is a number between 0 (few +messages) to 3 (most messages). + +query_method=(tcp_only|udp_only|tcp_udp|udp_tcp); +This has the same effect as the -m command line option. Read the documentation +for the command line option on this. tcp_only corresponds to the to, udp_only +to the uo, tcp_udp to the tu and udp_tcp to the ut argument of the command line +option. +If you use query_method=tcp_udp, it is recommended that you also set the global +timeout option to at least twice the longest server timeout. + +run_ipv4=(on|off); +This has the same effect as the -4 or -6 command line option: if on is +specified, IPv4 support is enabled, and IPv6 support is disabled (if +available). If off is specified, IPv4 will be disabled and IPv6 will be +enabled. For this option to be meaningful, pdnsd needs to be compiled with +support for the protocol you choose. If pdnsd was compiled with both IPv4 and +IPv6 support, and you want to include IPv6 addresses in the configuration file, +you will probably need to specify run_ipv4=off first to ensure that the IPv6 +addresses are parsed correctly. + +debug=(on|off); +This has the same effect as the -g command line option: the debugging messages +are enabled when on is specified. + +ctl_perms=number; +This option allows you to set the file permissions that the pdnsd status +control socket will have. These are the same as file permissions. The owner of +the file will be the run_as user, or, if none is specified, the user who +started pdnsd. If you want to specify the permissions in octal (as usual), +don't forget the leading zero (0600 instead of 600!). To use the status +control, write access is needed. The default is 0600 (only the owner may read +or write). +Please note that the socket is kept in the cache directory, and that the cache +directory permissions might also need to be adjusted. Please ensure that the +cache directory is not writeable for untrusted users. + +proc_limit=number; +With this option, you can set a limit on the pdnsd threads that will be active +simultaneously. If this number is exceeded, queries are queued and may be +delayed some time. See also the procq_limit option. +The default for this option is 40. + +procq_limit=number; +When the query thread limit proc_limit is exceeded, connection attempts to +pdnsd will be queued. With this option, you can set the maximum queue length. +If this length is also exceeded, the incoming queries will be dropped. That +means that tcp connections will be closed and udp queries will just be dropped, +which will probably cause the querying resolver to wait for an answer until it +times out. +See also the proc_limit option. A maximum of proc_limit+procq_limit query +threads will exist at any one time (plus 3 to 6 threads that will always be +present depending on your configuration). +The default for this option is 60. + +tcp_qtimeout=timespec; +This option sets a timeout for tcp queries. If no full query has been received +on a tcp connection after that time has passed, the connection will be closed. +The default is set using the --with-tcp-qtimeout option to configure. + +par_queries=number; +This option used to set the maximum number of remote servers that would be +queried simultaneously, for every query that pdnsd receives. +Since version 1.1.11, the meaning of this option has changed slightly. It is +now the increment with which the number of parallel queries is increased when +the previous set of servers has timed out. For example, if we have a list +server1, server2, server3, etc. of available servers and par_queries=2, then +pdnsd will first send queries to server1 and server2, and listen for responses +from these servers. +If these servers do not send a reply within their timeout period, pdnsd will +send additional queries to server3 and server4, and listen for responses from +server1, server2, server3 and server4, and so on until a useful reply is +received or the list is exhausted. +In the worst case there will be pending queries to all the servers in the list +of available servers. We may be using more system resources this way (but only +if the first servers in the list are slow or unresponsive), but the advantage +is that we have a greater chance of catching a reply. After all, if we wait +longer anyway, why not for more servers. +See also the explanation of the global timeout option below. +1 or 2 are good values for this option. The default is set at compile time +using the --with-par-queries option to configure. + +timeout=timespec; +This is the global timeout parameter for dns queries. This specifies the +minimum period of time pdnsd will wait after sending the first query to a +remote server before giving up without having received a reply. The timeout +options in the configuration file are now only minimum timeout intervals. +Setting the global timeout option makes it possible to specify quite short +timeout intervals in the server sections (see below). This will have the effect +that pdnsd will start querying additional servers fairly quickly if the first +servers are slow to respond (but will still continue to listen for responses +from the first ones). This may allow pdnsd to get an answer more quickly in +certain situations. +If you use query_method=tcp_udp it is recommended that you make the global +timeout at least twice as large as the largest server timeout, otherwise pdnsd +may not have time to try a UDP query if a TCP connection times out. +Default value is 0. + +randomize_recs=(on|off); +If this option is turned on, pdnsd will randomly reorder the cached records of +one type when creating an answer. This supports round-robin DNS schemes and +increases fail safety for hosts with multiple IP addresses, so this is usually +a good idea. +On by default. + +query_port_start=(number|none); +If a number is given, this defines the start of the port range used for queries +of pdnsd. The value given must be >= 1024. The purpose of this option is to aid +certain firewall configurations that are based on the source port. Please keep +in mind that another application may bind a port in that range, so a stateful +firewall using target port and/or process uid may be more effective. In case a +query start port is given pdnsd uses this port as the first port of a specified +port range (see query_port_end) used for queries. pdnsd will try to randomly +select a free port from this range as local port for the query. +To ensure that there are enough ports for pdnsd to use, the range between +query_port_start and query_port_end should be adjusted to at least (par_queries +* proc_limit). A larger range is highly recommended for security reasons, and +also because other applications may allocate ports in that range. If possible, +this range should be kept out of the space that other applications usually use. +The default for this option is 1024. Together with the default value of +query_port_end, this makes it the hardest for an attacker to guess the source +port used by the pdnsd resolver. If you specify none here, pdnsd will let the +kernel choose the source port, but this may leave pdnsd more vulnerable to an +attack. + +query_port_end=number; +Used if query_port_start is not none. Defines the last port of the range +started by query_port_start used for querys by pdnsd. The default is 65535, +which is also the maximum legal value for this option. For details see the +description of query_port_start. + +delegation_only=string; +Added by Paul Rombouts: This option specifies a "delegation-only" zone. This +means that if pdnsd receives a query for a name that is in a subdomain of a +"delegation-only" zone but the remote name server returns an answer with an +authority section lacking any NS RRs for subdomains of that zone, pdnsd will +answer NXDOMAIN (unknown domain). This feature can be used for undoing the +undesired effects of DNS "wildcards". Several "delegation-only" zones may be +specified together. If you specify root servers in a server section it is +important that you set root_server=on in such a section. +Example: + +delegation_only="com","net"; + +This feature is off by default. It is recommended that you only use this +feature if you actually need it, because there is a risk that some legitimate +names will be blocked, especially if the remote name servers queried by pdnsd +return answers with empty authority sections. + +ipv4_6_prefix=string; +This option has the same effect as the -i command-line option. When pdnsd runs +in IPv6 mode, this option specifies the prefix pdnsd uses to convert IPv4 +addresses in the configuration file (or addresses specified with pdnsd-ctl) to +IPv6-mapped addresses. The string must be a valid IPv6 address. Only the first +96 bits are used. Note that this only effects the parsing of IPv4 addresses +listed after this option. +The default is "::ffff.0.0.0.0". + +use_nss=(on|off); +If this option is turned on, pdnsd will call initgroups() to set up the group +access list, whenever pdnsd changes its user and group id (see run_as option). +There is a possible snag, though, if initgroups() uses NSS (Name Service +Switch) and NSS in turn uses DNS. In such a case you may experience lengthy +timeouts and stalls. By setting use_nss=off, you can disable the initgroups() +call (only possible in versions 1.2.5 and later). +This option was contributed by Jan-Marek Glogowski. +On by default. + +udpbufsize=number; +New in version 1.2.9: This option sets the upper limit on the size of UDP DNS +messages. The default is 1024. +See also the edns_query server option below. + + +2.1.2 server Section + +Each server section specifies a set of name servers that pdnsd should try to +get resource records or authoritative name server information from. The servers +are queried in the order of their appearance (or parallel to a limited extend). +If one fails, the next one is taken and so on. +You probably want to specify the dns server in your LAN, the caching dns +servers of your internet provider or even a list of root servers in one or more +server sections. +The supported options in this section are: + + +label=string; +Specify a label for the server section. This can be used to refer to this +section when using pdnsd-ctl, the pdnsd control utility. +You can give several server sections the same label, but if you want to change +the addresses of a server section (see ip option below) during run-time with +"pdnsd-ctl server label up dns1,dns2,...", the label must be unique. + +ip=string; +Give the IP (the address, not the host name) of the server. +Multiple IP addresses can be given per server section. This can be done by +entering multiple lines of the form ip=string; or a single line like this: + +ip=string,string,string; + +IP addresses do not have to be specified in the configuration file. A server +section without IP addresses will remain inactive until it is assigned one or +more addresses with pdnsd-ctl, the pdnsd control utility. +If pdnsd has been compiled with both IPv4 and IPv6 support, any IPv6 addresses +you specify here will be skipped with a warning message, unless pdnsd is +running in IPv6 mode. Thus, unless pdnsd was compiled to startup in IPv6 mode +by default, you need to use the command-line option -6 or set run_ipv4=off +first (see global section) in order to ensure that IPv6 addresses are parsed +correctly. +If pdnsd is running in IPv6 mode and you specify an IPv4 address here, it will +automatically be mapped to an IPv6 address. + +file=string; +New in version 1.2: This option allows you to give the name of a +resolv.conf-style file. Of the lines beginning with the nameserver keyword, the +second field will be parsed as an IP address, as if it were specified with the +ip= option. The remaining lines will be ignored. If the contents of the file +changes while pdnsd is running, you can make pdnsd aware of the changes through +the use of pdnsd-ctl, the pdnsd control utility. This is usually most +conveniently done by placing the command "pdnsd-ctl config" in a script that is +automatically run whenever the DNS configuration changes. +For example, suppose you have a ppp client that writes the DNS configuration +for your ISP to the file /etc/ppp/resolv.conf and runs the script /etc/ppp/ +ip-up when a new connection is established. One way of ensuring that pdnsd is +automatically reconfigured is to add a server section in the config file with +file=/etc/ppp/resolv.conf and to add the command "pdnsd-ctl config" to /etc/ppp +/ip-up. + +port=number; +Give the port the remote name server listens on. Default is 53 (the official +dns port) + +uptest=(ping|none|if|dev|diald|exec|query); +Determine the method to check whether the server is available. Currently +defined methods are: + + * ping: Send an ICMP_ECHO request to the server. If it doesn't respond within + the timeout, it is regarded to be unavailable until the next probe. + * none: The availability status is not changed, only the time stamp is + updated. + * if: Check whether the interface (specified in the interface= option) is + existent, up and running. This currently works for all "ordinary" network + interfaces, interfaces that disappear when down (e.g. ppp?), and + additionally for Linux isdn interfaces (as of kernel 2.2). Note that you + need a /dev/isdninfo device file (major#45, minor#255), or the isdn uptest + will always fail. + * dev and diald: Perform an if uptest, and, if that was succesful, + additionally check whether a program is running that has locked a given + (modem-) device. The needed parameters are an interface (specified as for + the if uptest, e.g. "ppp0") and a device relative to /dev (e.g. "modem" for + /dev/modem specified using the device= option. pdnsd will then look for a + pid file for the given interface in /var/lock (e.g. /var/run/ppp0.pid) and + for a lockfile for the given device (e.g. /var/lock/LCK..modem), and then + test whether the locking process is the process that created the pid file + and this process is still alive. If this is the case, the normal if uptest + is executed for the given interface. + The dev option is for pppd dial-on-demand, diald is the same for diald + users. + * exec: Executes a given command in the /bin/sh shell (as /bin/sh -c + ) and evaluates the result (the return code of the last command) + in the shell's way of handling return codes, i.e. 0 indicates success, all + other indicate failure. The shell's process name will be uptest_sh. The + command is given with the uptest_cmd option (see below). For secuity + issues, also see that entry. + * query: New in version 1.2: This works like the ping test, except it sends + an (empty) DNS query to the remote server. If the server sends a + well-formed response back within the timeout period (except SERVFAIL), it + will be regarded as available. This test is useful if a remote server does + not respond to ICMP_ECHO requests at all, which unfortunately is quite + common these days. It can also happen that a remote server is online but + ignores empty DNS queries. Then you will need the set the query_test_name + option (see below). In many cases this test will be a more reliable + indicator of availability than the ones mentioned before. + +The default value is none. + +NOTE: If you use on-demand dialing, use none, if, dev, diald or exec, since +ping or query will send packets in the specified interval and the interface +will thus frequently dial! + +ping_timeout=number; +Sets the timeout for the ping test in tenths of seconds (this unit is used for +legacy reasons; actually the current implementation is only accurate to a +second). +The default is 600 (one minute). + +ping_ip=string; +The IP address for the ping test. The default is the IP of the name server. + +query_test_name=string; +New in version 1.2.9: Sets the name to be queried when using uptest=query +availability test. If the string is the unquoted constant none, an empty query +is used (this the default), otherwise a query of type A will be sent for the +domain name specified here. It is not necessary for the domain name to exist or +have a record of type A in order for the uptest to succeed. +If the the remote server ignores empty queries, you will probably want to set +query_test_name="." (the root domain). + +uptest_cmd=string,string; +or +uptest_cmd=string; +Sets the command for the uptest=exec function to the first string. If the +second string is given, it specifies a user with whose user id and primary +group id the command is executed. +This is especially useful if you are executing the server as root, but do not +want the uptest to be performed with root privileges. In fact, you should never +execute the uptest as root if you can help it. +If the server is running setuid or setgid, the privileges thus gained are +attempted to be dropped even before changing identity to the specified user to +prevent setuid/gid security holes (otherwise, any user might execute commands +as root if you setuid the executable). +Note that this is not always possible, and that pdnsd should never be installed +as setuid or setgid. The command is executed using /bin/sh, so you should be +able to use shell builtin commands. + +interval=(timespec|onquery|ontimeout); +Sets the interval for the server up-test. The default is 900 seconds; however, +a test is forced when a query times out and the timestamp is reset then. +If you specify onquery instead of a timeout, the interface will be tested +before every query. This is to prevent automatically dialing interfaces (diald/ +pppd or ippp) to dial on dns queries. It is intended to be used in connection +with an interface-testing uptest ;-) +Note that using uptest=exec, you might run into performance problems on slow +machines when you use that option. DON'T use onquery with uptest=ping or uptest +=query, as it may cause delays if the server does not answer (btw, it doesn't +make sense anyway). Note also that using onquery is no guarantee that the +interface will not be used. When another (reachable) dns server tells pdnsd to +query a third dns server for data, pdnsd will do that and has no means of +checking whether this will dial up the interface or not. This however should be +a rare situation. +New in version 1.2.3: A third possibility is to specify interval=ontimeout. In +this case the server is not tested at startup/reconfiguration, nor at regular +intervals, but only after a DNS query to a server times out. Certain types of +network problems such as a refused connection will also cause the server to be +considered unavailable. However, once a server is declared dead it is never +considered again unless it is revived using a pdnsd-ctl config or server +command. The idea behind this option is to minimize uptests by assuming all +servers are available until there is reason to believe otherwise. + +interface=string; +The network interface (or network device, e.g. "eth0") for the uptest=if +option. Must be specified if uptest=if is given. + +device=string; +The (modem-) device that is used for the dev uptest. If you use this for a +dial-on-demand ppp uptest (together with uptest=dev), you need to enter the +device you are using for your pppd here, e.g. modem for /dev/modem. +Must be specified if uptest=dev is given. + +timeout=timespec; +Set the timeout for the dns query. The default is 120 seconds. You probably +want to set this lower. +Timeouts specified in the configuration file are only treated as the minimum +period of time to wait for a reply. A queries to a remote server are not +canceled until a useful reply has been received, or all the other queries have +timed out or failed. +If you have also set the global timeout option, you may consider setting a +fairly small value here. See the explanation of the timeout option in the +global section for what that means. + +purge_cache=(on|off); +In every fetched dns record, there is a cache timeout given, which specifies +how long the fetched data may be cached until it needs to be reloaded. If +purge_cache is set to off, the stale records are not purged (unless the cache +size would be exceeded, in this case the oldest records are purged). Instead, +they are still served if they cannot succesfully be updated (e.g. because all +servers are down). +Default is off. + +caching=(on|off); +Specifies if caching shall be performed for this server at all. Default is on. + +lean_query=(on|off); +Specifies whether to use the "lean" query mode. In this mode, only the +information actually queried from pdnsd is resolved and cached. This has the +advantage that usually less cache space is used and the query is usually +faster. In 90% of the cases, only address (A) records are needed anyway. If +switched off, pdnsd will always cache all data about a host it can find and +will specifically ask for all available records (well, at least it is a good +approximation for what it really does ;-) This will of course increase the +answer packet sizes. +Some buggy name servers may not deliver CNAME records when not asked for all +records. I do not know if such servers are around, but if you have trouble +resolving certain host names, try turning this option off. +A last note: If you use multiple pdnsd's that access each other, turning this +option on is probably a big win. +This on by default. + +edns_query=(on|off); +New in version 1.2.9: Specifies whether to use EDNS (Extension mechanisms for +DNS) for outgoing queries. Currently this is only useful for allowing UDP +message sizes larger than 512 bytes. Note that setting this option on can give +problems in combination with some legacy systems or software, including, +embarrassingly enough, previous versions of pdnsd. +The default is off, but if your network can handle UDP payloads significantly +larger than 512 bytes, the recommended value is on. +Note that this option only effects outgoing queries. If pdnsd receives a query +using EDNS, it will reply using EDNS regardless of the value of this option. +See also the udpbufsize option above. + +scheme=string; +You can specify a pcmcia-cs scheme that is used in addition to the uptests. If +you specify a scheme here, the server this section is for will only be queries +if the given scheme is active. Shell wildcards (* and ?) are allowed in the +string under their special meanings. You need to use the scheme_file option on +the global section to make this option work. + +preset=(on|off); +This allows you to specify the initial state of a server before any uptest is +performed. on specifies that the server is regarded available. The default is +on. This is especially useful when you set uptest=none; and want to change the +status of a server only via pdnsd-ctl. + +proxy_only=(on|off); +When this option is set to on, answers given by the servers are always +accepted, and no other servers (as, for example, specified in the NS records of +the query domain) are queried. If you do not turn this option on, pdnsd will do +such queries in some cases (in particular when processing ANY queries). +This option is useful when you do not want pdnsd to make connections to outside +servers for some reasons (e.g. when a firewall is blocking such queries). +I recommend that you turn on lean_query when using this option. +Default is off. + +root_server=(on|off|discover); +Set this option to on if the servers specified in a section are root servers. A +root server will typically only give the name servers for the top-level domain +in its reply. Setting root_server=on will cause pdnsd to try to use cached +information about top-level domains to reduce to number of queries to root +servers, making the resolving of new names more efficient. You can get a list +of available root servers by running the command "dig . ns". +This option is also necessary if you use the delegation_only option. +New in version 1.2.8: This option may also be set to "discover". This will +cause pdnsd to query the servers provided with the ip= option to obtain the +full list of root servers. The root-server addresses will replace the addresses +specified with the ip= option. This will only be done once on startup, or after +a "pdnsd-ctl config" command. In this case the name servers specified with the +ip= option don't have to be root servers, they just have to know the names and +addresses of the root servers. After root-server discovery pdnsd will behave +just as if root_server=on had been specified. +Default is off. + +randomize_servers=(on|off); +New in version 1.2.6: Set this option to on to give each name server in this +section an equal chance of being queried. If this option is off, the name +servers are always queried starting with the first one specified. Even with +this option on, the query order is not truly random. Only the first server is +selected randomly; the following ones are queried in consecutive order, +wrapping around to the beginning of the list when the end is reached. Note that +this option only effects the order within a section. The servers in the first +(active) section are always queried before those in the second one, etc. +The default is off, but if you are resolving from root servers setting this +option on is highly recommended. If root_server=on this option also effects the +query order of the name servers for the top-level domains. + +reject=string; +New in version 1.2.6: This option can be used to make pdnsd reject replies that +contain certain IP addresses. You can specify a single IP address, which will +be matched exactly, or a range of addresses using an address/mask pair. The +mask can be specified as a simple integer, indicating the number of initial 1 +bits in the mask, or in the usual IP address notation. IP addresses may be +either IPv4 or IPv6 (provided there is sufficient support in the C libraries +and support for AAAA records was not disabled). When addresses in the reject +list are compared with those in a reply, only the bits corresponding to those +set in the netmask are significant, the rest are ignored. +Multiple addresses or address/mask pairs may be specified; this can be done by +entering multiple lines of the form reject=string; or a single line like this: + +reject=string,string,string; + +How pdnsd reacts when an address in the reply matches one in the reject list, +depends on the reject_policy option, see below. + +reject_policy=(fail|negate); +New in version 1.2.6: This option determines what pdnsd does when an address in +the reply from a name server matches the reject list (see above). If this +option is set to fail, pdnsd will try another server, or, if there no more +servers to try, return the answer SERVFAIL. If this option is set to negate, +pdnsd will immediately return the answer NXDOMAIN (unknown domain) without +querying additional servers. The fail setting is useful if you don't always +trust the servers in this section, but do trust the servers in the following +section. The negate setting can be used to completely censor certain IP +addresses. In this case you should put the same reject list in every server +section, and also set the reject_recursively option (see below) to true. +The default is fail. + +reject_recursively=(on|off); +New in version 1.2.6: Normally pdnsd checks for addresses in the reject list +(see above) only when the reply comes directly from a name server listed in the +configuration file. With this option set to on, pdnsd will also do this check +for name servers that where obtained from NS records in the authority section +of a previous reply (which was incomplete and non-authoritative). +Default is off. + +policy=(included|excluded|simple_only|fqdn_only); +pdnsd supports inclusion/exclusion lists for server sections: with include= and +exclude= (see below) you can specify domain names for which this server will be +used or will not be used. The first match counts (i.e., the first include or +exclude rule in a server section that matches a domain name is applied, and the +search for other rules is terminated). If no rule matched a given domain name, +the policy= option determines whether this server is used for the lookup for +that domain name; when included is given, the server will be asked, and when +excluded is given, it will not. If simple_only is given the server will be used +if the name to lookup is a simple (single-label) domain name, on the other hand +if fqdn_only is given the server will be used only for names consisting of two +or more labels (i.e. the name has at least one dot in-between). +If no server is available for a queried domain, pdnsd will return an error +message to the client that usually will stop the client's attempts to resolve a +specific domain from this server (the libc resolver will e.g. return an error +to the application that tried to resolve the domain if no other servers are +available in the resolv.conf). This may be of use sometimes. +Note: the simple_only and fqdn_only constants were added by Paul Rombouts. They +are useful for controlling which name servers (if any) will be used by pdnsd +for resolving simple (single-label) host names. fqdn_only used to stand for +"fully qualified domain name only", but this is actually a misnomer. The names +in queries received by pdnsd are always considered to be fully qualified. If +you do not exactly understand what the options simple_only and fqdn_only are +good for, you are probably better off not using them. +The default for this option is included. + +include=string; +This option adds an entry to the exclusion/inclusion list. If a domain matches +the name given as string, the server is queried if this was the first matching +rule (see also the entry for policy). +If the given name starts with a dot, the whole subdomain of the given name +including the one of that name is matched, e.g. ".foo.bar." will match the +domain names a.foo.bar., a.b.c.foo.bar. and foo.bar. +If it does not start in a dot, only exactly the given name (ignoring the case, +of course) will be matched (hint: if you want to include all subdomains, but +not the domain of the given name itself, place an exact-match exclude rule +before the include rule, e.g: exclude="foo.bar."; include=".foo.bar."; +Previous versions of pdnsd required that names given with this and the next +option ended in a dot, but since version 1.1.8b1-par8, pdnsd automatically adds +a dot at the end if it is missing. +pdnsd now also accepts a more compact notation for adding several "include" +entries in one line, e.g.: + +include=".foo",".bar",".my.dom"; + +exclude=string; +This option adds an entry to the exclusion/inclusion list. If a domain matches +the name given as string, the server is not queried if this was the first +matching rule (see also the entry for policy). +If the given name starts with a dot, the whole subdomain of the given name +including the one of that name is matched, e.g. ".foo.bar." will match the +domain names a.foo.bar., a.b.c.foo.bar. and foo.bar. +If it does not start in a dot, only exactly the given name (ignoring the case, +of course) will be matched (hint: if you want to exclude all subdomains, but +not the domain of the given name itself, place an exact-match include rule +before the exclude rule, e.g: include="foo.bar."; exclude=".foo.bar."; +pdnsd now also accepts a more compact notation for adding several "exclude" +entries in one line, e.g.: + +exclude=".foo",".bar",".my.dom"; + + +2.1.3 rr Section + +Every rr section specifies a dns resource record that is stored locally. It +allows you to specify own dns records that are served by pdnsd in a limited +way. Only A, PTR, CNAME, MX, NS and SOA records are implemented. +This option is intended to allow you to define RRs for 1.0.0.127.in-addr.arpa. +and localhost. (and perhaps even one or two hosts) without having to start an +extra named if your cached name servers do not serve those records. It is NOT +intended and not capable to work as a full-featured name server. + + +name=string; +Specifies the name of the resource records, i.e. the domain name of the +resource the record describes. This option must be specified before any a, ptr, +cname, mx, ns or soa records. Names are interpreted as absolute domain names +(i.e. pdnsd assumes they end in the root domain). For this and all following +arguments that take domain names, you need to specify domain names in dotted +notation (example venera.isi.edu.). +Previous versions of pdnsd required that domain names given in the +configuration file ended in a dot, but since version 1.1.8b1-par8, pdnsd +automatically assumes a dot at the end if it is missing. +New in version 1.2: It is also possible to specify a name starting with the +label *. Such a name is called a wildcard. The * in a wildcard can match one or +more labels in a queried name, but only whole labels. Any other * characters in +a wildcard, apart from the leading one, will only match a literal *. +For example, *.mydomain will match a.mydomain or www.a.mydomain, but not +mydomain. *.a*.mydomain will match www.a*.mydomain, but not www.ab.mydomain. +*a.mydomain will only match itself. +Before you can specify an rr section with name=*.mydomain you must define some +records for mydomain, typically NS and/or SOA records. Example: + + rr { + name = mydomain; + ns = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + rr { + name = *.mydomain; + a = 192.168.1.10; + } + +In this example, www.mydomain and ftp.mydomain will resolve to the numeric +address 192.168.1.10 (unless you add rr sections explicitly specifying +different addresses for www.mydomain or ftp.mydomain). If you want mydomain +also to resolve to a numeric address, add an A record to the first rr section. + +ttl=timespec; +Specifies the ttl (time to live) for all resource records in this section after +this entry. This may be redefined. The default is 86400 seconds (=1 day). + +authrec=(on|off); +If this is turned on, pdnsd will create authoritative local records for this rr +section. This means that pdnsd flags the domain record so that records of this +domain that are not present in the cache are treated as non-existent, i.e. no +other servers are queried for that record type, and an response containing none +of those records is returned. This is most time what people want: if you add an +A record for a host, and it has no AAAA record (thus no IPv6 address), you +normally don't want other name servers to be queried for it. +This is on by default. +Please note that this only has an effect if it precedes the name option! + +reverse=(on|off); +New in version 1.2: If you want a locally defined name to resolve to a numeric +address and vice versa, you can achieve this by setting reverse=on before +defining the A record (see below). The alternative is to define a separate PTR +record, but you will probably find this option much more convenient. +The default is off. + +a=string; +Defines an A (host address) record. The argument is an IPv4 address in dotted +notation. pdnsd will serve this address for the host name given in the name +option. +Provided there is sufficient support in the C libraries and support for AAAA +records was not disabled, the argument string may also be an IPv6 address, in +which case an AAAA record will be defined. +This option be may used multiple times within an rr section, causing multiple +addresses to be defined for the name. However, if you put the different +addresses in different rr sections for the same name, the definition in the +last rr section will cancel the definitions in the previous ones. + +ptr=string; +Defines a PTR (domain name pointer) record. The argument is a host name in +dotted notation (see name). The ptr record is for resolving adresses into +names. For example, if you want the adress 127.0.0.1 to resolve into localhost, +and localhost into 127.0.0.1, you need something like the following sections: + + rr { + name = localhost; + a = 127.0.0.1; + owner = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + rr { + name = 1.0.0.127.in-addr.arpa; + ptr = localhost; + owner = localhost; + soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400; + } + +The second section is for reverse resolving and uses the ptr option. Note that +you can get the same effect by specifying only the first rr section with +reverse=on. +There is something special about the name in the second section: when a +resolver wants to get a host name from an internet address, it composes an +address that is built of the IP address in reverse byte order (1.0.0.127 +instead of 127.0.0.1) where each byte of the adress written as number +constitutes a sub-domain under the domain in-addr.arpa. +So, if you want to compose an adress for reverse resolving, take your ip in +dotted notation (e.g. 1.2.3.4), reverse the byte order (4.3.2.1) and append +in-addr.arpa. (4.3.2.1.in-addr.arpa.) Then, define an rr section giving this +address as name and the domain name corresponding to that ip in the ptr option. + +cname=string; +Defines a CNAME (canonical name) record. The argument should be a +fully-qualified host name in dotted notation (see name). A CNAME is the DNS +equivalent of an alias or symbolic link. +A useful application for CNAMEs is giving short, easy to remember nicknames to +hosts with complicated names. For example, you might want the name "news" to +refer to your ISP's news server "nntp2.myisp.com". Instead of adding an A +record for "news" with the same address as "nntp2.myisp.com", you could put in +a CNAME pointing to "nntp2.myisp.com", so that if the IP address of the news +server changes, there is no need to update the record for "news". +To implement this with pdnsd, you could add the following section to your +configuration file: + + rr { + name = news; + cname = nntp2.myisp.com; + owner = localhost; + } + +mx=string,number; +Defines an MX (mail exchange) record. The string is the host name of the mail +server in dotted notation (see name). The number specifies the preference +level. +When you send mail to someone, your mail typically goes from your E-mail client +to an SMTP server. The SMTP server then checks for the MX record of the domain +in the E-mail address. For example, with joe@example.com, it would look for the +MX record for example.com and find that the name of mail server for that domain +is, say, mail.example.com. The SMTP server then gets the A record for +mail.example.com, and connects to the mail server. +If there are multiple MX records, the SMTP server will pick one based on the +preference level (starting with the lowest preference number, working its way +up). +Don't define MX records with pdnsd unless you know what you're doing. + +owner=string; +or +ns=string; +Defines an NS (name server) record. Specifies the name of the host which should +be authoritative for the records you defined in the rr section. This is +typically the host pdnsd runs on. +Note: In previous versions of pdnsd this option had to be specified before any +a, ptr, cname, mx or soa entries. In version 1.2, the restrictions on this +option are same as the options just mentioned, and it must listed after the +name= option. This can be a pain if you want to use an old config file which +specifies owner= before name= (sorry about that). Apart from greater +consistency, the advantage is that you can now specify as many NS records as +you like (including zero). + +soa=string,string,number,timespec,timespec,timespec,timespec; +This defines a soa (start of authority) record. The first string is the domain +name of the server and should be equal to the name you specified as owner. +The second string specifies the email address of the maintainer of the name +server. It is also specified as a domain name, so you will have to replace the +@ sign in the name with a dot (.) to get the name you have to specify here. The +next parameter (the first number) is the serial number of the record. You +should increment this number if you change the record. +The 4th parameter is the refresh timeout. It specifies after what amount of +time a caching server should attempt to refresh the cached record. +The 5th parameter specifies a time after which a caching server should attempt +to refresh the record after a refresh failure. +The 6th parameter defines the timeout after which a cached record expires if it +has not been refreshed. +The 7th parameter is the ttl that is specified in every rr and should be the +same as given with the ttl option (if you do not specify a ttl, use the default +86400). + +txt=string,...,string; +New in version 1.2.9: Defines an TXT record. You can specify one or more +strings here. + + +2.1.4 neg Section + +Every neg section specifies a dns resource record or a dns domain that should +be cached negatively locally. Queries for negatively cached records are always +answered immediatley with an error or an empty answer without querying other +hosts as long as the record is valid. The records defined with neg sections +remain valid until they are explicitely invalidated or deleted by the user +using pdnsd-ctl. +This is useful if a certain application asks periodically for nonexisting hosts +or RR types and you do not want a query to go out every time the cached record +has timed out. Example: Netscape Communicator will ask for the servers news and +mail on startup if unconfigured. If you do not have a dns search list for your +network, you can inhibit outgoing queries for these by specifying + + neg { + name = news; + types = domain; + } + neg { + name = mail; + types = domain; + } + +in your config file. If you have a search list, you have to repeat that for any +entry in your search list in addition to the entries given above! +In versions 1.1.11 and later, if you negate whole domains this way, all +subdomains will be negated as well. Thus if you specify +neg {name=example.com; types=domain;} in the config file, this will also negate +www.example.com, xxx.adserver.example.com, etc. + + +name=string; +Specifies the name of the domain for which negative cache entries are created. +This option must be specified before the types option. Names are interpreted as +absolute domain names (i.e. pdnsd assumes they end in the root domain). You +need to specify domain names in dotted notation (example venera.isi.edu.). +Previous versions of pdnsd required that domain names given in the +configuration file ended in a dot, but since version 1.1.8b1-par8, pdnsd +automatically assumes a dot at the end if it is missing. + +ttl=timespec; +Specifies the ttl (time to live) for all resource records in this section after +this entry. This may be redefined. The default is 86400 seconds (=1 day). + +types=(domain|rr_type[,rr_type[,rr_type[,...]]]); +Specifies what is to be cached negatively: domain will cache the whole domain +negatively; alternatively, you can specify a comma-separated list of RR types +which are to be cached negatively. You may specify multiple types options, but +domain and the RR types are mutually exclusive. +The RR types are specified using their official names from the RFC's in +capitals, e.g. A, CNAME, NS, PTR, MX, AAAA, ... +The command pdnsd-ctl list-rrtypes will give you a complete list of those +types. pdnsd-ctl is built along with pdnsd and will be installed in the same +directory as the pdnsd binary during make install. + + +2.1.5 source Section + +Every source section allows you to let pdnsd read the records from a file in an +/etc/hosts-like format. pdnsd will generate records to resolve the entries +address from its host name and vice versa for every entry in the file. This is +normally easier than defining an rr for every of your addresses, since +localhost and your other FQDNs are normally given in /etc/hosts. +The accepted format is as follows: The #-sign initiates a comment, the rest of +the line from the first occurence of this character on is ignored. Empty lines +are tolerated. +The first entry on a line (predeceded by an arbitrary number of tabs and +spaces) is the IP in dotted notation, the second entry on one line (separated +by the first by an arbitrary number of tabs and spaces) is the FQDN (fully +qualified domain name) for that ip. The rest of the line is ignored by default +(in the original /etc/hosts, it may contain information not needed by pdnsd). + + +owner=string; +Specifies the name of the host pdnsd runs on and that are specified in dns +answers (specifically, nameserver records). Must be specified before any file +entries. +Names are interpreted as absolute domain names (i.e. pdnsd assumes they end in +the root domain). You need to specify domain names in dotted notation (example +venera.isi.edu.). +Previous versions of pdnsd required that domain names given in the +configuration file ended in a dot, but since version 1.1.8b1-par8, pdnsd +automatically assumes a dot at the end if it is missing. + +ttl=timespec; +Specifies the ttl (time to live) for all resource records in this section after +this entry. This may be redefined. The default is 86400 seconds (=1 day). + +file=string; +The string specifies a file name. For every file entry in a source section, +pdnsd will try to load the given file as described above. Failure is indicated +only when the file cannot be opened, malformed entries will be ignored. + +serve_aliases=(on|off); +If this is turned on pdnsd will serve the aliases given in a hosts-style file. +These are the third entry in a line of a hosts-style file, which usually give a +"short name" for the host. This may be used to support broken clients without a +proper domain-search option. If no aliases are given in a line of the file, +pdnsd behaves as without this option for this line. +This feature was suggested by Bert Frederiks. +It is off by default. + +authrec=(on|off); +If this is turned on, pdnsd will create authoritative local records with the +data from the hosts file. Please see the description of the option of the same +name in the rr section for a closer description of what this means. Please note +that this only has an effect for files sourced with file options subsequent to +this option. +This is on by default. + + +2.1.6 include Section + +A configuration file may include other configuration files. However, only the +top-level configuration file may contain global and server sections, thus +include files are effectively limited to sections that add local definitions to +the cache. +Include sections currently only have one type of option, which may be given +multiple times within a single section. + + +file=string; +The string specifies a file name. For every file option in an include section, +pdnsd will parse the given file as described above. The file may contain +include sections itself, but as a precaution pdnsd checks that a certain +maximum depth is not exceeded to guard against the possibility of infinite +recursion. + + +3 pdnsd-ctl + +pdnsd-ctl allows you to configure pdnsd at run time. To make this work, you +have to start pdnsd with the -s option (or use the status_ctl option in the +config file). You also should make sure that you have appropriate permissions +on the control socket (use the ctl_perms option to make this sure) and of your +pdnsd cache directory (pdnsd keeps its socket there). Please make sure the +pdnsd cache directory is not writeable for untrusted users! + +pdnsd-ctl accepts two command-line options starting with a dash. +-c may be used to specify the cache directory (and takes this as argument). The +default for this setting is the pdnsd default cache directory (specified at +compile time). The cache directory for pdnsd-ctl must be the same pdnsd uses! +-q can be used to make the output of pdnsd-ctl less verbose. + +The following table lists the commands that pdnsd-ctl supports. The command +must always be the first command-line option (not starting with a dash), the +arguments to the command must follow in the given order. +In the following table, keywords are in a normal font, while placeholders are +in italics. +Alternatives are specified like (alt1|alt2|alt3). Optional arguments are placed +between square brackets []. + +Command Arguments Description + +help Print a command summary. + +version Print version and license info. + +status Print a description of pdnsd's cache status, thread status + and configuration. Also shows which remote name servers + are assumed to be available. + +server (index|label) (up| Set the status of the server with the given index or label + down|retest) [dns1[, (where the given label matches the one given with the + dns2[,...]]] label option in the respective server section in the + config file) to up or down, or force a retest. The index + is assigned in the order of definition in pdnsd.conf + starting with 0. Use the status command to view the + indices and labels. You can specify all instead of an + index or label to perform the action for all servers + registered with pdnsd. Example: + pdnsd-ctl server 0 retest + An optional third argument consisting of a list of IP + addresses (separated by commas or white-space characters) + can be given. This list will replace the previous list of + addresses of name servers used by pdnsd in the specified + section of the config file. For example in the /etc/ppp/ + ip-up script called by pppd you could place the following + line: + pdnsd-ctl server isplabel up $DNS1,$DNS2 + If white space is used to separate addresses the list will + have to be quoted. Spurious commas and white-space + characters are ignored. The last argument may also be an + empty string, in which case the existing IP addresses are + removed and the corresponding server section becomes + inactive. + +record name (delete| Delete or invalidate the records of the given domain name + invalidate) if it is in the cache. Invalidation means that the records + are marked as timed out, and will be reloaded if possible + (if purge_cache is set to on, they will be deleted in any + case). + For local records (i.e., records that were given in the + config file using a rr section, records read from a + hosts-style file and records added using pdnsd-ctl), + invalidation has no effect. Deletion will work, though. + Example: + pdnsd-ctl record localhost. delete + +source fn owner [ttl] [(on Load a hosts-style file. Works like using the pdnsd source + |off)] [noauth] configuration section. owner and ttl are used as in the + source section. ttl has a default of 900 (it does not need + to be specified). The next to last argument corresponds to + the serve_aliases option, and is off by default (i.e. if + it is not specified). noauth is used to make the domains + non-authoritative - please see the description of the + authrec config file options for a description of what that + means. fn is the filename. The file must be readable by + pdnsd! Example: + pdnsd-ctl source /etc/hosts localhost. 900 off + +add a addr name [ttl] + [noauth] + Add a record of the given type to the pdnsd cache, + replacing existing records for the same name and type. The +add aaaa addr name [ttl 2nd argument corresponds to the value of the option in the + ] [noauth] rr section that is named like the first argument: a is a + record for hostname-to-address mapping, aaaa is the same + thing for IPv6 addresses, and ptr is for +add ptr host name [ttl] address-to-hostname mapping. See the documentation for the + [noauth] rr section for more details. In case of A and AAAA + records, the addr argument may be a list of IP addresses, + separated by commas or white space, causing multiple +add cname host name [ addresses to be defined for the same name. The ttl is + ttl] [noauth] optional, the default is 900 seconds. noauth is used to + make the domains non-authoritative - please see the + description of the authrec config file options for a +add mx host name pref description of what that means. If you want no other + [ttl] [noauth] record than the newly added in the cache, do + pdnsd-ctl record name delete before adding records. This + is also better when overwriting local records. Example: +add ns host name [ttl] pdnsd-ctl add a 127.0.0.1 localhost. 900 + [noauth] + + +neg name [type] [ttl] Add a negatively cached record to pdnsd's cache, replacing + existing records for the same name and type. If no type is + given, the whole domain is cached negatively. For + negatively cached records, errors are immediately returned + on a query, without querying other servers first. The ttl + is optional, the default is 900 seconds. + You can get a list of all types you can pass to this + command using pdnsd-ctl list-rrtypes. The type is treated + case-sensitive! Example: + pdnsd-ctl neg foo.bar A 900 + pdnsd-ctl neg foo.baz 900 + +config [filename] Reload pdnsd's configuration file. + The config file must be owned by the uid that pdnsd had + when it was started, and be readable by pdnsd's run_as + uid. If no file name is specified, the config file used at + start-up is reloaded. + Note that some configuration changes, like the port or IP + address pdnsd listens on, cannot be made this way and you + will receive an error message. In these cases, you will + have to restart pdnsd instead. + +include filename Parse the given file as an include file, see the + documentation on include sections for a description what + this file may contain. + This command is useful for adding definitions to the cache + without reconfiguring pdnsd. + +eval string Parse the given string as if it were part of pdnsd's + configuration file. The string should hold one or more + complete configuration sections. However, global and + server sections are not allowed, just as in include files. + If multiple strings are given, they will be joined using + newline chars and parsed together. + This command is useful for adding records interactively to + the cache that cannot be defined using the "pdnsd-ctl add" + command, (e.g. soa records). + +empty-cache [[+|-]name ...] If no arguments are provided, the cache will be completely + emptied, freeing all existing entries. Note that this also + removes local records, as defined by the config file. To + restore local records, run "pdnsd-ctl config" or + "pdnsd-ctl include filename" immediately afterwards. + The "pdnsd-ctl empty-cache" command now accepts additional + arguments; these are interpreted as include/exclude names. + If an argument starts with a '+' the name will be + included. If an argument starts with a '-' it will be + excluded. If an argument does not begin with '+' or '-', a + '+' is assumed. If the domain name of a cache entry ends + in one of the names in the list, the first match will + determine what happens. If the matching name is to be + included, the cache entry is deleted, otherwise not. If + there are no matches, the default action is not to delete. + Note that if you want to delete exactly one name and no + others, you should use "pdnsd-ctl record name delete", + this is also much more efficient. + Examples: + pdnsd-ctl empty-cache + This command will remove all cache entries. + + pdnsd-ctl empty-cache microsoft.com msft.net + This will remove all entries ending in microsoft.com or + msft.net. + + pdnsd-ctl empty-cache -localdomain -168.192.in-addr.arpa . + This will remove all entries except those ending in + localdomain or 168.192.in-addr.arpa. Note that '.' is the + root domain which matches any domain name. + +dump [name] Print information stored in the cache about name. If name + begins with a dot and is not the root domain, information + about the names in the cache ending in name (including + name without the leading dot) will be printed. If name is + not specified, information about all the names in the + cache will be printed. + For each RR record the time and date that this record has + been added to the cache will be printed in the form mm/dd + HH:MM:SS (locally defined records are printed without a + time stamp). After that the type of record is printed with + the data. For the more common types of RR records the data + will be printed in human readable form, the remaining ones + in a hexadecimal representation. + This command is mainly useful for diagnostic purposes. + Note that if you pipe the output of this command through + an application that reads only part of the output and then + blocks (such as more or less), pdnsd will not be able to + add new entries to the cache until the pipe is closed. It + is preferable to capture the output in a file in such a + case. + +list-rrtypes List available rr types for the neg command. Note that + those are only used for the neg command, not for add! + + + +4 contrib/ + +The contrib directory in the pdnsd distribution contains useful +user-contributed scripts. +So far, there are scripts contributed by Marko Stolle and Paul Rombouts that +make pdnsd usable in a DHCP setup. Please take a look into the README file in +the contrib directory for further information. + + +5 Problems... + +If you have problems with configuring or running pdnsd, be sure to read the FAQ +. If this does not help you, pdnsd crashes or you find bugs, please mail one of +the authors. +Note added by Paul A. Rombouts: Thomas Moestl no longer maintains the code. I +have revised the code and added new features. See README.par and the ChangeLog +in the source directory (or /usr/share/doc/pdnsd- if you have +installed a binary package) for more details. If you have questions about my +modifications, you can find my email address at the end of README.par. + + +6 Hacking + +Here comes some information you might find useful for hacking pdnsd. + +6.1 Source files + +Makefile.am, autoconf/automake/autoheader scripts. Makefile.am's are in +configure.in, most subdirectories. +acconfig.h + +pdnsd.spec.in A template from which configure generates a spec file for + building rpm's for various distributions. + +version Contains only the program version string. Needed for + several templates. + +src/rc/* rc (start-up) scripts for various linux distributions. + + The pdnsd cache subsystem(s) as defined in src/cache.h. +src/cache.c This is the "traditional" pdnsd system which keeps the + cache in memory and uses hash tables for accesses. Sourav + K. Mandal is working on a system using gdbm. + +src/pdnsd-ctl/* Contains the code for pdnsd-ctl, a program that allows you + to control pdnsd at run time. + + The lex/flex source file for the config file lexer. This is +src/conf-lex.l.in a template because there might be inserted "%option + yylineno" for proper flex support. (obsolete, superseded by + src/conf-parser.c) + + This is automatically generated by configure from +src/conf-lex.l conf-lex.l.in. It may be overwritten in any make, so never + modify this, but conf-lex.l.in instead! (obsolete, + superseded by src/conf-parser.c) + +src/conf-parse.y The yacc/bison source of the config file parser. (obsolete, + superseded by src/conf-parser.c) + +src/conf-parser.c, The config file parser written purely in C (versions +src/conf-parser.h, 1.1.10-par and later). +src/conf-keywords.h + +src/conff.c, src/ The configuration handler functions and their prototypes. +conff.h The parser is called from here. + +src/consts.h Some constants used by the parser, config file handler + functions and in the server status thread, among others. + + Define dns message structures, constants, and some common +src/dns.c, src/dns.h dns data handlers. dns.h contains gcc-specific code (in + praticular, "__attribute__((packed))"). + +src/dns_answer.c, Define functions that answer incoming dns queries. +src/dns_answer.h + +src/dns_query.c, src Define functions to manage outgoing dns queries. +/dns_query.h + +src/error.c, src/ Functions for error output to stderr or the syslog, and +error.h debug output to stderr or pdnsd.debug. + +src/hash.c, src/ Contains the code for storing and looking up cache entries +hash.h in the hash table. + +src/helpers.c, src/ Define miscellaneous helper functions. +helpers.h + +src/icmp.c, src/ Define a function for performing a ping test. This contains +icmp.h OS-specific code. + +src/main.c Contains main(), which holds the command line parser, + performs initialisations and signal handling. + + Contains the code for the executable make_hashconvtable, +src/ which is only run once, during build time, to generate the +make_hashconvtable.c file hashconvtable.h, used by src/hash.c (versions + 1.1.10-par and later). (obsolete since version 1.2) + + A perl script for generating src/rr_types.h, a C header +src/ file containing macro definitions and tables needed for +make_rr_types_h.pl handling the RR types known to pdnsd, from the text file + src/rr_types.in. + +src/rr_types.c, src/ These define tables and macros needed for handling the RR +rr_types.h, src/ types known to pdnsd. Since version 1.2.9, rr_types.h is an +rr_types.in automatically generated file, see make_rr_types_h.pl. + +src/netdev.c, src/ Define functions for network device handling. OS-specific. +netdev.h + +src/servers.c, src/ Define functions for the server status thread that performs +servers.h the periodical uptests. + +src/status.c, src/ Define functions for the status control thread. This is +status.h pdnsd's interface to pdnsd-ctl. + + +------------------------------------------------------------------------------- + +Copyright (C) 2000, 2001 Thomas Moestl +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2012 Paul A. Rombouts + +Last revised: 19 April 2012 by Paul A. Rombouts + diff --git a/jni/pdnsd/file-list.base.in b/jni/pdnsd/file-list.base.in new file mode 100644 index 00000000..409ba338 --- /dev/null +++ b/jni/pdnsd/file-list.base.in @@ -0,0 +1,5 @@ +%defattr(-,root,root) +%doc AUTHORS THANKS COPYING COPYING.BSD ChangeLog ChangeLog.old INSTALL NEWS README README.par README.par.old TODO +%config /etc/pdnsd.conf.sample +%attr(750, @def_id@, @def_id@) %dir @cachedir@ +%attr(640, @def_id@, @def_id@) %config @cachedir@/pdnsd.cache diff --git a/jni/pdnsd/install-sh b/jni/pdnsd/install-sh new file mode 100644 index 00000000..4d4a9519 --- /dev/null +++ b/jni/pdnsd/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# 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. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +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: +-c (ignored) +-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. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; 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 + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + 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 "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # 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 -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # 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 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $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 "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 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. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jni/pdnsd/missing b/jni/pdnsd/missing new file mode 100644 index 00000000..894e786e --- /dev/null +++ b/jni/pdnsd/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# 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 + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +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 + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jni/pdnsd/pdnsd.spec.in b/jni/pdnsd/pdnsd.spec.in new file mode 100644 index 00000000..6af6cdef --- /dev/null +++ b/jni/pdnsd/pdnsd.spec.in @@ -0,0 +1,244 @@ +# rpmbuild spec file for pdnsd. +# with modifications by Paul Rombouts. + +# Supported rpmbuild --define and --with options include: +# +# --with isdn Configure with --enable-isdn. +# +# --without poll Configure with --disable-poll +# +# --without nptl Configure with --with-thread-lib=linuxthreads. +# +# --with ipv6 Configure with --enable-ipv6. +# +# --without tcpqueries Configure with --disable-tcp-queries. +# +# --without debug Configure with --with-debug=0. +# +# --define "distro " Configure with --with-distribution=. +# +# --define "run_as_user " Configure with --with-default-id=. +# For RPMs the default is "@def_id@". +# +# --define "run_as_uid " If the user defined by the previous option does not exist +# when the RPM is installed, the pre-install script will try +# to create a new user with numerical id . +# +# --define "cachedir " Configure with --with-cachedir=. +# + +%{!?distro: %define distro @distribution@} + +# The default run_as ID to use +%{!?run_as_user: %define run_as_user @def_id@} +# By default, if a new run_as_user is to be created, we let +# useradd choose the numerical uid, unless run_as_uid is defined. +#define run_as_uid 96 +%{!?cachedir: %define cachedir @cachedir@} +%define conffile %{_sysconfdir}/pdnsd.conf + +Summary: A caching dns proxy for small networks or dialin accounts +Name: @PACKAGE@ +Version: @VERSION@ +Release: @packagerelease@ +License: GPLv3 +Group: Daemons +Source: http://members.home.nl/p.a.rombouts/pdnsd/releases/%{name}-%{version}-%{release}.tar.gz +URL: http://members.home.nl/p.a.rombouts/pdnsd.html +Vendor: Paul A. Rombouts +Packager: Paul A. Rombouts +Prefix: %{_prefix} +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +pdnsd is a proxy DNS daemon with permanent (disk-)cache and the ability +to serve local records. It is designed to detect network outages or hangups +and to prevent DNS-dependent applications like Netscape Navigator from hanging. + +The original author of pdnsd is Thomas Moestl, but pdnsd is no longer maintained +by him. This is an extensively revised version by Paul A. Rombouts. +For a description of the changes see http://members.home.nl/p.a.rombouts/pdnsd.html +and the file README.par in %{_docdir}/%{name}-%{version} + +%{!?distro:You can specify the target distribution when you build the source RPM. For instance, if you're building for a Red Hat system call rpmbuild with:} +%{!?distro: --define "distro RedHat"} +%{?distro:This package was built for a %{distro} distribution.} +%{!?_with_isdn:It's possible to rebuild the source RPM with isdn support using the rpmbuild option:} +%{!?_with_isdn: --with isdn} +%{?_with_isdn:This package was built with isdn support enabled.} +%{!?_with_ipv6:It's possible to rebuild the source RPM with ipv6 support using the rpmbuild option:} +%{!?_with_ipv6: --with ipv6} +%{?_with_ipv6:This package was built with ipv6 support.} +%{?_without_poll:This package was built with the select(2) function instead of poll(2).} + +%prep +%setup + +%build +CFLAGS="${CFLAGS:-$RPM_OPT_FLAGS -Wall}" ./configure \ + --prefix=%{_prefix} --sysconfdir=%{_sysconfdir} --mandir=%{_mandir} \ + --with-cachedir="%{cachedir}" \ + %{?distro:--with-distribution=%{distro}} --enable-specbuild \ + --with-default-id=%{run_as_user} \ + %{?_with_isdn:--enable-isdn} \ + %{?_without_poll:--disable-poll} \ + %{?_without_nptl:--with-thread-lib=linuxthreads} \ + %{?_with_ipv6:--enable-ipv6} \ + %{?_without_tcpqueries:--disable-tcp-queries} \ + %{?_without_debug:--with-debug=0} + +make + +%install +%if "%{run_as_user}" != "nobody" +[ "$(id -un)" != root ] || +id -u %{run_as_user} > /dev/null 2>&1 || +/usr/sbin/useradd -c "Proxy DNS daemon" %{?run_as_uid:-u %{run_as_uid}} \ + -s /sbin/nologin -r -d "%{cachedir}" %{run_as_user} || { + set +x + echo "Cannot create user \"%{run_as_user}\"%{?run_as_uid: with uid=%{run_as_uid}}" + echo "Please select another numerical uid and rebuild with --define \"run_as_uid uid\"" + echo "or create a user named \"%{run_as_user}\" by hand and try again." + exit 1 +} +%endif + +rm -rf "$RPM_BUILD_ROOT" +make DESTDIR="$RPM_BUILD_ROOT" install +cp -f file-list.base file-list +find doc contrib -not -type d -not -iname '*makefile' -not -name '*.am' \ + -not -name '*.in' -not -path 'doc/*.pl' | +sed -e 's/^/%doc --parents /' >> file-list +CURDIR=$PWD; cd "$RPM_BUILD_ROOT" +find . -not -type d '(' -not -name 'pdnsd.conf*' -or -name 'pdnsd.conf.[1-9]*' ')' \ + -not -path '.%{_docdir}/*' -not -path './var/*' | +sed -e 's/^\.// + \:/man:{ + /\.gz$/!s/$/.gz/ + }' >> "$CURDIR/file-list" + +%clean +rm -rf "$RPM_BUILD_ROOT" +#rm -rf %{_builddir}/%{name}-%{srcver} + +%files -f file-list + +%pre +# First stop any running pdnsd daemons +%if "%{distro}" == "SuSE" +/sbin/init.d/pdnsd stop >/dev/null 2>&1 +%endif +%if "%{distro}" == "RedHat" +if [ -f /var/lock/subsys/pdnsd ]; then + if /sbin/pidof pdnsd > /dev/null; then + /sbin/service pdnsd stop >/dev/null 2>&1 + if [ "$1" -ge 2 ]; then touch /var/lock/subsys/pdnsd; fi + else + rm -f /var/lock/subsys/pdnsd + fi +fi +%endif + +%if "%{run_as_user}" != "nobody" +# Add the "pdnsd" user +id -u %{run_as_user} > /dev/null 2>&1 || +/usr/sbin/useradd -c "Proxy DNS daemon" %{?run_as_uid:-u %{run_as_uid}} \ + -s /sbin/nologin -r -d "%{cachedir}" %{run_as_user} || { + echo "Cannot create user \"%{run_as_user}\"%{?run_as_uid: with uid=%{run_as_uid}}" + echo "Please create a user named \"%{run_as_user}\" by hand and try again." + exit 1 +} +[ "$(id -gn %{run_as_user})" = %{run_as_user} ] || { + echo "user \"%{run_as_user}\" does not have an corresponding group called \"%{run_as_user}\"" + echo "Please change the initial group of user \"%{run_as_user}\" to \"%{run_as_user}\" and try again." + exit 1 +} + +if [ -f "%{conffile}" ] && + grep -v -e '^[[:blank:]]*\(#\|\/\/\)' "%{conffile}" | + grep -q -e '\ "%{conffile}" && + echo "In %{conffile} runs_as=\"nobody\" has been replaced by run_as=\"%{run_as_user}\"" +fi +%endif + +if [ -f "%{cachedir}/pdnsd.cache" ]; then + chown -c %{run_as_user}:%{run_as_user} "%{cachedir}/pdnsd.cache" +fi + +%post +%if "%{distro}" == "SuSE" +if [ -w /etc/rc.config ]; then + grep "START_PDNSD" /etc/rc.config > /dev/null + if [ $? -ne 0 ] ; then + echo -e \ +"\n\n#\n# Set to yes to start pdnsd at boot time\n#\nSTART_PDNSD=yes" \ +>> /etc/rc.config + fi +fi +%endif +%if "%{distro}" == "RedHat" +if [ "$1" = 1 ]; then + /sbin/chkconfig --add pdnsd +fi +%endif + +%preun +%if "%{distro}" == "RedHat" +if [ "$1" = 0 ]; then + /sbin/service pdnsd stop >/dev/null 2>&1 + /sbin/chkconfig --del pdnsd +fi +%endif + +%postun +%if "%{distro}" == "RedHat" +if [ "$1" -ge 1 ]; then + /sbin/service pdnsd condrestart >/dev/null 2>&1 +fi +%endif + +%changelog +* Tue Jan 31 2012 Paul A. Rombouts +- Prevent makefiles and perl scripts from being installed + in the documentation directory. +* Sat Jan 28 2012 Paul A. Rombouts +- Update the (Source) URLs. +* Sat Aug 4 2007 Paul Rombouts +- License is now GPL version 3 +* Fri Mar 24 2006 Paul Rombouts +- Instead of using a fixed default value for run_as_uid, + I let useradd choose the uid if run_as_uid is undefined. +* Thu Dec 29 2005 Paul Rombouts +- TCP-query support is now compiled in by default, + but can be disabled using "--without tcpqueries". +* Sun Jul 20 2003 Paul Rombouts +- Changed default run_as ID from "nobody" to "pdnsd" +* Fri Jun 20 2003 Paul Rombouts +- Added configuration option for NPTL. +* Sat Jun 07 2003 Paul Rombouts +- Added automatic definition of distro using _vendor macro. +* Thu May 22 2003 Paul Rombouts +- Ensured that modification times of acconfig.h and configure.in + are not changed by patching to avoid unwanted reconfigure during make phase. +* Tue May 20 2003 Paul Rombouts +- Applied my customized patch file. See READ.par for details. +* Sun May 16 2001 Thomas Moestl +- Make use of chkconfig for Red Hat (patch by Christian Engstler) +* Sun Mar 25 2001 Thomas Moestl +- Merged SuSE fixes by Christian Engstler +* Fri Feb 09 2001 Thomas Moestl +- Merged in a spec fix for mapage inclusion contributed by Sourav K. + Mandal +* Sun Nov 26 2000 Thomas Moestl +- Added some patches contributed by Bernd Leibing +* Tue Aug 15 2000 Thomas Moestl +- Added the distro for configure +* Tue Jul 11 2000 Sourav K. Mandal +- autoconf/automake modifications diff --git a/jni/pdnsd/src/Makefile.am b/jni/pdnsd/src/Makefile.am new file mode 100644 index 00000000..959e669e --- /dev/null +++ b/jni/pdnsd/src/Makefile.am @@ -0,0 +1,24 @@ + +sbin_PROGRAMS = pdnsd + +pdnsd_CFLAGS = -DCONFDIR='"$(sysconfdir)"' $(thread_CFLAGS) + +pdnsd_SOURCES = conf-parser.c conff.c consts.c debug.c dns.c dns_answer.c \ + dns_query.c error.c helpers.c icmp.c list.c main.c netdev.c rr_types.c \ + status.c servers.c thread.c cache.c hash.c conf-parser.h \ + conf-keywords.h conff.h consts.h debug.h dns.h dns_answer.h \ + dns_query.h error.h helpers.h icmp.h ipvers.h list.h netdev.h \ + rr_types.h servers.h status.h thread.h cache.h hash.h pdnsd_assert.h \ + freebsd_netinet_ip_icmp.h + +EXTRA_DIST = make_rr_types_h.pl rr_types.in + +## Try to do this last + +SUBDIRS = . pdnsd-ctl rc test + +$(pdnsd_OBJECTS): rr_types.h + +rr_types.h: make_rr_types_h.pl rr_types.in + perl make_rr_types_h.pl rr_types.in > rr_types.h + diff --git a/jni/pdnsd/src/Makefile.in b/jni/pdnsd/src/Makefile.in new file mode 100644 index 00000000..75569a40 --- /dev/null +++ b/jni/pdnsd/src/Makefile.in @@ -0,0 +1,921 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +sbin_PROGRAMS = pdnsd$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am_pdnsd_OBJECTS = pdnsd-conf-parser.$(OBJEXT) pdnsd-conff.$(OBJEXT) \ + pdnsd-consts.$(OBJEXT) pdnsd-debug.$(OBJEXT) \ + pdnsd-dns.$(OBJEXT) pdnsd-dns_answer.$(OBJEXT) \ + pdnsd-dns_query.$(OBJEXT) pdnsd-error.$(OBJEXT) \ + pdnsd-helpers.$(OBJEXT) pdnsd-icmp.$(OBJEXT) \ + pdnsd-list.$(OBJEXT) pdnsd-main.$(OBJEXT) \ + pdnsd-netdev.$(OBJEXT) pdnsd-rr_types.$(OBJEXT) \ + pdnsd-status.$(OBJEXT) pdnsd-servers.$(OBJEXT) \ + pdnsd-thread.$(OBJEXT) pdnsd-cache.$(OBJEXT) \ + pdnsd-hash.$(OBJEXT) +pdnsd_OBJECTS = $(am_pdnsd_OBJECTS) +pdnsd_LDADD = $(LDADD) +pdnsd_LINK = $(CCLD) $(pdnsd_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(pdnsd_SOURCES) +DIST_SOURCES = $(pdnsd_SOURCES) +RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +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@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pdnsd_CFLAGS = -DCONFDIR='"$(sysconfdir)"' $(thread_CFLAGS) +pdnsd_SOURCES = conf-parser.c conff.c consts.c debug.c dns.c dns_answer.c \ + dns_query.c error.c helpers.c icmp.c list.c main.c netdev.c rr_types.c \ + status.c servers.c thread.c cache.c hash.c conf-parser.h \ + conf-keywords.h conff.h consts.h debug.h dns.h dns_answer.h \ + dns_query.h error.h helpers.h icmp.h ipvers.h list.h netdev.h \ + rr_types.h servers.h status.h thread.h cache.h hash.h pdnsd_assert.h \ + freebsd_netinet_ip_icmp.h + +EXTRA_DIST = make_rr_types_h.pl rr_types.in +SUBDIRS = . pdnsd-ctl rc test +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .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) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: 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-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + 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) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(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: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +pdnsd$(EXEEXT): $(pdnsd_OBJECTS) $(pdnsd_DEPENDENCIES) + @rm -f pdnsd$(EXEEXT) + $(pdnsd_LINK) $(pdnsd_OBJECTS) $(pdnsd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-conf-parser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-conff.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-consts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-dns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-dns_answer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-dns_query.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-helpers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-icmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-netdev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-rr_types.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-servers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-status.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-thread.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +pdnsd-conf-parser.o: conf-parser.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-conf-parser.o -MD -MP -MF $(DEPDIR)/pdnsd-conf-parser.Tpo -c -o pdnsd-conf-parser.o `test -f 'conf-parser.c' || echo '$(srcdir)/'`conf-parser.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-conf-parser.Tpo $(DEPDIR)/pdnsd-conf-parser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='conf-parser.c' object='pdnsd-conf-parser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-conf-parser.o `test -f 'conf-parser.c' || echo '$(srcdir)/'`conf-parser.c + +pdnsd-conf-parser.obj: conf-parser.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-conf-parser.obj -MD -MP -MF $(DEPDIR)/pdnsd-conf-parser.Tpo -c -o pdnsd-conf-parser.obj `if test -f 'conf-parser.c'; then $(CYGPATH_W) 'conf-parser.c'; else $(CYGPATH_W) '$(srcdir)/conf-parser.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-conf-parser.Tpo $(DEPDIR)/pdnsd-conf-parser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='conf-parser.c' object='pdnsd-conf-parser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-conf-parser.obj `if test -f 'conf-parser.c'; then $(CYGPATH_W) 'conf-parser.c'; else $(CYGPATH_W) '$(srcdir)/conf-parser.c'; fi` + +pdnsd-conff.o: conff.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-conff.o -MD -MP -MF $(DEPDIR)/pdnsd-conff.Tpo -c -o pdnsd-conff.o `test -f 'conff.c' || echo '$(srcdir)/'`conff.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-conff.Tpo $(DEPDIR)/pdnsd-conff.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='conff.c' object='pdnsd-conff.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-conff.o `test -f 'conff.c' || echo '$(srcdir)/'`conff.c + +pdnsd-conff.obj: conff.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-conff.obj -MD -MP -MF $(DEPDIR)/pdnsd-conff.Tpo -c -o pdnsd-conff.obj `if test -f 'conff.c'; then $(CYGPATH_W) 'conff.c'; else $(CYGPATH_W) '$(srcdir)/conff.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-conff.Tpo $(DEPDIR)/pdnsd-conff.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='conff.c' object='pdnsd-conff.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-conff.obj `if test -f 'conff.c'; then $(CYGPATH_W) 'conff.c'; else $(CYGPATH_W) '$(srcdir)/conff.c'; fi` + +pdnsd-consts.o: consts.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-consts.o -MD -MP -MF $(DEPDIR)/pdnsd-consts.Tpo -c -o pdnsd-consts.o `test -f 'consts.c' || echo '$(srcdir)/'`consts.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-consts.Tpo $(DEPDIR)/pdnsd-consts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='consts.c' object='pdnsd-consts.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-consts.o `test -f 'consts.c' || echo '$(srcdir)/'`consts.c + +pdnsd-consts.obj: consts.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-consts.obj -MD -MP -MF $(DEPDIR)/pdnsd-consts.Tpo -c -o pdnsd-consts.obj `if test -f 'consts.c'; then $(CYGPATH_W) 'consts.c'; else $(CYGPATH_W) '$(srcdir)/consts.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-consts.Tpo $(DEPDIR)/pdnsd-consts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='consts.c' object='pdnsd-consts.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-consts.obj `if test -f 'consts.c'; then $(CYGPATH_W) 'consts.c'; else $(CYGPATH_W) '$(srcdir)/consts.c'; fi` + +pdnsd-debug.o: debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-debug.o -MD -MP -MF $(DEPDIR)/pdnsd-debug.Tpo -c -o pdnsd-debug.o `test -f 'debug.c' || echo '$(srcdir)/'`debug.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-debug.Tpo $(DEPDIR)/pdnsd-debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='debug.c' object='pdnsd-debug.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-debug.o `test -f 'debug.c' || echo '$(srcdir)/'`debug.c + +pdnsd-debug.obj: debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-debug.obj -MD -MP -MF $(DEPDIR)/pdnsd-debug.Tpo -c -o pdnsd-debug.obj `if test -f 'debug.c'; then $(CYGPATH_W) 'debug.c'; else $(CYGPATH_W) '$(srcdir)/debug.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-debug.Tpo $(DEPDIR)/pdnsd-debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='debug.c' object='pdnsd-debug.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-debug.obj `if test -f 'debug.c'; then $(CYGPATH_W) 'debug.c'; else $(CYGPATH_W) '$(srcdir)/debug.c'; fi` + +pdnsd-dns.o: dns.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns.o -MD -MP -MF $(DEPDIR)/pdnsd-dns.Tpo -c -o pdnsd-dns.o `test -f 'dns.c' || echo '$(srcdir)/'`dns.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns.Tpo $(DEPDIR)/pdnsd-dns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns.c' object='pdnsd-dns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns.o `test -f 'dns.c' || echo '$(srcdir)/'`dns.c + +pdnsd-dns.obj: dns.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns.obj -MD -MP -MF $(DEPDIR)/pdnsd-dns.Tpo -c -o pdnsd-dns.obj `if test -f 'dns.c'; then $(CYGPATH_W) 'dns.c'; else $(CYGPATH_W) '$(srcdir)/dns.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns.Tpo $(DEPDIR)/pdnsd-dns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns.c' object='pdnsd-dns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns.obj `if test -f 'dns.c'; then $(CYGPATH_W) 'dns.c'; else $(CYGPATH_W) '$(srcdir)/dns.c'; fi` + +pdnsd-dns_answer.o: dns_answer.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns_answer.o -MD -MP -MF $(DEPDIR)/pdnsd-dns_answer.Tpo -c -o pdnsd-dns_answer.o `test -f 'dns_answer.c' || echo '$(srcdir)/'`dns_answer.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns_answer.Tpo $(DEPDIR)/pdnsd-dns_answer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns_answer.c' object='pdnsd-dns_answer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns_answer.o `test -f 'dns_answer.c' || echo '$(srcdir)/'`dns_answer.c + +pdnsd-dns_answer.obj: dns_answer.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns_answer.obj -MD -MP -MF $(DEPDIR)/pdnsd-dns_answer.Tpo -c -o pdnsd-dns_answer.obj `if test -f 'dns_answer.c'; then $(CYGPATH_W) 'dns_answer.c'; else $(CYGPATH_W) '$(srcdir)/dns_answer.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns_answer.Tpo $(DEPDIR)/pdnsd-dns_answer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns_answer.c' object='pdnsd-dns_answer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns_answer.obj `if test -f 'dns_answer.c'; then $(CYGPATH_W) 'dns_answer.c'; else $(CYGPATH_W) '$(srcdir)/dns_answer.c'; fi` + +pdnsd-dns_query.o: dns_query.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns_query.o -MD -MP -MF $(DEPDIR)/pdnsd-dns_query.Tpo -c -o pdnsd-dns_query.o `test -f 'dns_query.c' || echo '$(srcdir)/'`dns_query.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns_query.Tpo $(DEPDIR)/pdnsd-dns_query.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns_query.c' object='pdnsd-dns_query.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns_query.o `test -f 'dns_query.c' || echo '$(srcdir)/'`dns_query.c + +pdnsd-dns_query.obj: dns_query.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-dns_query.obj -MD -MP -MF $(DEPDIR)/pdnsd-dns_query.Tpo -c -o pdnsd-dns_query.obj `if test -f 'dns_query.c'; then $(CYGPATH_W) 'dns_query.c'; else $(CYGPATH_W) '$(srcdir)/dns_query.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-dns_query.Tpo $(DEPDIR)/pdnsd-dns_query.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dns_query.c' object='pdnsd-dns_query.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-dns_query.obj `if test -f 'dns_query.c'; then $(CYGPATH_W) 'dns_query.c'; else $(CYGPATH_W) '$(srcdir)/dns_query.c'; fi` + +pdnsd-error.o: error.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-error.o -MD -MP -MF $(DEPDIR)/pdnsd-error.Tpo -c -o pdnsd-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-error.Tpo $(DEPDIR)/pdnsd-error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='error.c' object='pdnsd-error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c + +pdnsd-error.obj: error.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-error.obj -MD -MP -MF $(DEPDIR)/pdnsd-error.Tpo -c -o pdnsd-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-error.Tpo $(DEPDIR)/pdnsd-error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='error.c' object='pdnsd-error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi` + +pdnsd-helpers.o: helpers.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-helpers.o -MD -MP -MF $(DEPDIR)/pdnsd-helpers.Tpo -c -o pdnsd-helpers.o `test -f 'helpers.c' || echo '$(srcdir)/'`helpers.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-helpers.Tpo $(DEPDIR)/pdnsd-helpers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='helpers.c' object='pdnsd-helpers.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-helpers.o `test -f 'helpers.c' || echo '$(srcdir)/'`helpers.c + +pdnsd-helpers.obj: helpers.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-helpers.obj -MD -MP -MF $(DEPDIR)/pdnsd-helpers.Tpo -c -o pdnsd-helpers.obj `if test -f 'helpers.c'; then $(CYGPATH_W) 'helpers.c'; else $(CYGPATH_W) '$(srcdir)/helpers.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-helpers.Tpo $(DEPDIR)/pdnsd-helpers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='helpers.c' object='pdnsd-helpers.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-helpers.obj `if test -f 'helpers.c'; then $(CYGPATH_W) 'helpers.c'; else $(CYGPATH_W) '$(srcdir)/helpers.c'; fi` + +pdnsd-icmp.o: icmp.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-icmp.o -MD -MP -MF $(DEPDIR)/pdnsd-icmp.Tpo -c -o pdnsd-icmp.o `test -f 'icmp.c' || echo '$(srcdir)/'`icmp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-icmp.Tpo $(DEPDIR)/pdnsd-icmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='icmp.c' object='pdnsd-icmp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-icmp.o `test -f 'icmp.c' || echo '$(srcdir)/'`icmp.c + +pdnsd-icmp.obj: icmp.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-icmp.obj -MD -MP -MF $(DEPDIR)/pdnsd-icmp.Tpo -c -o pdnsd-icmp.obj `if test -f 'icmp.c'; then $(CYGPATH_W) 'icmp.c'; else $(CYGPATH_W) '$(srcdir)/icmp.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-icmp.Tpo $(DEPDIR)/pdnsd-icmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='icmp.c' object='pdnsd-icmp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-icmp.obj `if test -f 'icmp.c'; then $(CYGPATH_W) 'icmp.c'; else $(CYGPATH_W) '$(srcdir)/icmp.c'; fi` + +pdnsd-list.o: list.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-list.o -MD -MP -MF $(DEPDIR)/pdnsd-list.Tpo -c -o pdnsd-list.o `test -f 'list.c' || echo '$(srcdir)/'`list.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-list.Tpo $(DEPDIR)/pdnsd-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='list.c' object='pdnsd-list.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-list.o `test -f 'list.c' || echo '$(srcdir)/'`list.c + +pdnsd-list.obj: list.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-list.obj -MD -MP -MF $(DEPDIR)/pdnsd-list.Tpo -c -o pdnsd-list.obj `if test -f 'list.c'; then $(CYGPATH_W) 'list.c'; else $(CYGPATH_W) '$(srcdir)/list.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-list.Tpo $(DEPDIR)/pdnsd-list.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='list.c' object='pdnsd-list.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-list.obj `if test -f 'list.c'; then $(CYGPATH_W) 'list.c'; else $(CYGPATH_W) '$(srcdir)/list.c'; fi` + +pdnsd-main.o: main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-main.o -MD -MP -MF $(DEPDIR)/pdnsd-main.Tpo -c -o pdnsd-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-main.Tpo $(DEPDIR)/pdnsd-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='pdnsd-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c + +pdnsd-main.obj: main.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-main.obj -MD -MP -MF $(DEPDIR)/pdnsd-main.Tpo -c -o pdnsd-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-main.Tpo $(DEPDIR)/pdnsd-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='pdnsd-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` + +pdnsd-netdev.o: netdev.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-netdev.o -MD -MP -MF $(DEPDIR)/pdnsd-netdev.Tpo -c -o pdnsd-netdev.o `test -f 'netdev.c' || echo '$(srcdir)/'`netdev.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-netdev.Tpo $(DEPDIR)/pdnsd-netdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='netdev.c' object='pdnsd-netdev.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-netdev.o `test -f 'netdev.c' || echo '$(srcdir)/'`netdev.c + +pdnsd-netdev.obj: netdev.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-netdev.obj -MD -MP -MF $(DEPDIR)/pdnsd-netdev.Tpo -c -o pdnsd-netdev.obj `if test -f 'netdev.c'; then $(CYGPATH_W) 'netdev.c'; else $(CYGPATH_W) '$(srcdir)/netdev.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-netdev.Tpo $(DEPDIR)/pdnsd-netdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='netdev.c' object='pdnsd-netdev.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-netdev.obj `if test -f 'netdev.c'; then $(CYGPATH_W) 'netdev.c'; else $(CYGPATH_W) '$(srcdir)/netdev.c'; fi` + +pdnsd-rr_types.o: rr_types.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-rr_types.o -MD -MP -MF $(DEPDIR)/pdnsd-rr_types.Tpo -c -o pdnsd-rr_types.o `test -f 'rr_types.c' || echo '$(srcdir)/'`rr_types.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-rr_types.Tpo $(DEPDIR)/pdnsd-rr_types.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rr_types.c' object='pdnsd-rr_types.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-rr_types.o `test -f 'rr_types.c' || echo '$(srcdir)/'`rr_types.c + +pdnsd-rr_types.obj: rr_types.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-rr_types.obj -MD -MP -MF $(DEPDIR)/pdnsd-rr_types.Tpo -c -o pdnsd-rr_types.obj `if test -f 'rr_types.c'; then $(CYGPATH_W) 'rr_types.c'; else $(CYGPATH_W) '$(srcdir)/rr_types.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-rr_types.Tpo $(DEPDIR)/pdnsd-rr_types.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rr_types.c' object='pdnsd-rr_types.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-rr_types.obj `if test -f 'rr_types.c'; then $(CYGPATH_W) 'rr_types.c'; else $(CYGPATH_W) '$(srcdir)/rr_types.c'; fi` + +pdnsd-status.o: status.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-status.o -MD -MP -MF $(DEPDIR)/pdnsd-status.Tpo -c -o pdnsd-status.o `test -f 'status.c' || echo '$(srcdir)/'`status.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-status.Tpo $(DEPDIR)/pdnsd-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='status.c' object='pdnsd-status.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-status.o `test -f 'status.c' || echo '$(srcdir)/'`status.c + +pdnsd-status.obj: status.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-status.obj -MD -MP -MF $(DEPDIR)/pdnsd-status.Tpo -c -o pdnsd-status.obj `if test -f 'status.c'; then $(CYGPATH_W) 'status.c'; else $(CYGPATH_W) '$(srcdir)/status.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-status.Tpo $(DEPDIR)/pdnsd-status.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='status.c' object='pdnsd-status.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-status.obj `if test -f 'status.c'; then $(CYGPATH_W) 'status.c'; else $(CYGPATH_W) '$(srcdir)/status.c'; fi` + +pdnsd-servers.o: servers.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-servers.o -MD -MP -MF $(DEPDIR)/pdnsd-servers.Tpo -c -o pdnsd-servers.o `test -f 'servers.c' || echo '$(srcdir)/'`servers.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-servers.Tpo $(DEPDIR)/pdnsd-servers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='servers.c' object='pdnsd-servers.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-servers.o `test -f 'servers.c' || echo '$(srcdir)/'`servers.c + +pdnsd-servers.obj: servers.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-servers.obj -MD -MP -MF $(DEPDIR)/pdnsd-servers.Tpo -c -o pdnsd-servers.obj `if test -f 'servers.c'; then $(CYGPATH_W) 'servers.c'; else $(CYGPATH_W) '$(srcdir)/servers.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-servers.Tpo $(DEPDIR)/pdnsd-servers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='servers.c' object='pdnsd-servers.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-servers.obj `if test -f 'servers.c'; then $(CYGPATH_W) 'servers.c'; else $(CYGPATH_W) '$(srcdir)/servers.c'; fi` + +pdnsd-thread.o: thread.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-thread.o -MD -MP -MF $(DEPDIR)/pdnsd-thread.Tpo -c -o pdnsd-thread.o `test -f 'thread.c' || echo '$(srcdir)/'`thread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-thread.Tpo $(DEPDIR)/pdnsd-thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='thread.c' object='pdnsd-thread.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-thread.o `test -f 'thread.c' || echo '$(srcdir)/'`thread.c + +pdnsd-thread.obj: thread.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-thread.obj -MD -MP -MF $(DEPDIR)/pdnsd-thread.Tpo -c -o pdnsd-thread.obj `if test -f 'thread.c'; then $(CYGPATH_W) 'thread.c'; else $(CYGPATH_W) '$(srcdir)/thread.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-thread.Tpo $(DEPDIR)/pdnsd-thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='thread.c' object='pdnsd-thread.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-thread.obj `if test -f 'thread.c'; then $(CYGPATH_W) 'thread.c'; else $(CYGPATH_W) '$(srcdir)/thread.c'; fi` + +pdnsd-cache.o: cache.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-cache.o -MD -MP -MF $(DEPDIR)/pdnsd-cache.Tpo -c -o pdnsd-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-cache.Tpo $(DEPDIR)/pdnsd-cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='pdnsd-cache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c + +pdnsd-cache.obj: cache.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-cache.obj -MD -MP -MF $(DEPDIR)/pdnsd-cache.Tpo -c -o pdnsd-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-cache.Tpo $(DEPDIR)/pdnsd-cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='pdnsd-cache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` + +pdnsd-hash.o: hash.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-hash.o -MD -MP -MF $(DEPDIR)/pdnsd-hash.Tpo -c -o pdnsd-hash.o `test -f 'hash.c' || echo '$(srcdir)/'`hash.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-hash.Tpo $(DEPDIR)/pdnsd-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hash.c' object='pdnsd-hash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-hash.o `test -f 'hash.c' || echo '$(srcdir)/'`hash.c + +pdnsd-hash.obj: hash.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -MT pdnsd-hash.obj -MD -MP -MF $(DEPDIR)/pdnsd-hash.Tpo -c -o pdnsd-hash.obj `if test -f 'hash.c'; then $(CYGPATH_W) 'hash.c'; else $(CYGPATH_W) '$(srcdir)/hash.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pdnsd-hash.Tpo $(DEPDIR)/pdnsd-hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hash.c' object='pdnsd-hash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pdnsd_CFLAGS) $(CFLAGS) -c -o pdnsd-hash.obj `if test -f 'hash.c'; then $(CYGPATH_W) 'hash.c'; else $(CYGPATH_W) '$(srcdir)/hash.c'; fi` + +# 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. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; 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" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +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 \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + 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 $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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-sbinPROGRAMS mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile 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-sbinPROGRAMS + +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 -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags ctags-recursive distclean \ + distclean-compile distclean-generic 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-sbinPROGRAMS \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-sbinPROGRAMS + + +$(pdnsd_OBJECTS): rr_types.h + +rr_types.h: make_rr_types_h.pl rr_types.in + perl make_rr_types_h.pl rr_types.in > rr_types.h + +# 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/jni/pdnsd/src/cache.c b/jni/pdnsd/src/cache.c new file mode 100644 index 00000000..4fbb7fb9 --- /dev/null +++ b/jni/pdnsd/src/cache.c @@ -0,0 +1,2723 @@ +/* cache.c - Keep the dns caches. + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2004, 2005, 2007, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cache.h" +#include "hash.h" +#include "conff.h" +#include "helpers.h" +#include "dns.h" +#include "error.h" +#include "debug.h" +#include "thread.h" +#include "ipvers.h" + + +/* A version identifier to prevent reading incompatible cache files */ +static const char cachverid[] = {'p','d','1','3'}; + +/* CACHE STRUCTURE CHANGES IN PDNSD 1.0.0 + * Prior to version 1.0.0, the cache was managed at domain granularity (all records of a domain were handled as a unit), + * which was suboptimal after the lean query feature and the additional record management were included. + * From 1.0.0 on, the cache management was switched to act with RR set granularity. The API of the cache handlers was + * slightly modified, in particular the rr_bucket_t was modified and some parameter list were changed. The cache + * file format had to be changed and is incompatible now. This means that post-1.0.0p1 versions will not read the cache + * files of older versions and vice versa. In addition, cache files from 1.0.0p5 on are incompatible to those of 1.0.0p1 + * to 1.0.0p4. Better delete them before upgrading. + * The "cent" lists common to old versions have vanished; the only access point to the cent's is the hash. + * However, there are now double linked rrset lists. Thus, rrs can be acces through the hash or through the rrset lists. + * The rrset list entries need some additional entries to manage the deletion from rrs lists as well as from the cents. + * + * Nearly all cache functions had to be changed significantly or even to be rewritten for that. Expect some beta time + * because of that. + * There are bonuses visible to the users resulting from this changes however: more consistent cache handling (under + * some circumstances, rrs could be in the cache more than once) and reduced memory requirements, as no rr needs + * to have stored its oname any more. There are more pointers however, and in some cases (CNAMES) the memory require- + * ments for some records may increase. The total should be lower, however. + * + * RRSET_L LIST STRUCTURE: + * The rrset_l rrset list is a simple double-linked list. The oldest entries are at the first positions, the list is sorted + * by age in descending order. Search is done only on insert. + * The rationale for this form is: + * - the purging operation needs to be fast (this way, the first records are the oldest and can easily be purged) + * - the append operation is common and needs to be fast (in normal operation, an appended record was just retrieved + * and therefore is the newest, so it can be appended at the end of the list without search. Only in the case of + * reading a disk cache file, searches are necessary) + * The rrset list is excusively used for purging purposes. + * + * THE DISK CACHE FILES: + * The disk cache file consists of cent's, i.e. structures for every known hostnames with a header and rrs attached to it. + * Therefore, the rr's are not ordered by their age and a search must be performed to insert the into the rr_l in the + * right positions. This operations has some costs (although not all too much), but the other way (rrs stored in order + * of their age and the cent headers separated from them), the rrs would need to be attached to the cent headers, which + * would be even more costly, also in means of disk space. + * + * CHANGES AFTER 1.0.0p1 + * In 1.0.0p5, the cache granularity was changed from rr level to rr set level. This was done because rfc2181 demands + * rr set consistency constraints on rr set level and if we are doing so we can as well save space (and eliminate some + * error-prone algorithms). + * + * CHANGES FOR 1.1.0p1 + * In this version, negative caching support was introduced. Following things were changed for that: + * - new members ts, ttl and flags in dns_cent_t and dns_file_t + * - new caching flag CF_NEGATIVE + * - all functions must accept and deal correctly with empty cents with DF_NEGATIVE set. + * - all functions must accept and deal correctly with empty rrsets with CF_NEGATIVE set. + */ + + +/* + * This is the size the memory cache may exceed the size of the permanent cache. + */ +#define MCSZ 10240 + +/* Some structs used for storing cache entries in a file. */ +typedef struct { + unsigned short rdlen; +/* data (with length rdlen) follows here;*/ +} rr_fbucket_t; + +typedef struct { + unsigned char tp; /* RR type */ + unsigned char num_rr; /* Number of records in RR set. */ + unsigned short flags; /* Flags for RR set. */ + time_t ttl; + time_t ts; +} __attribute__((packed)) +rr_fset_t; + +#if NRRTOT>255 +#warning "Number of cache-able RR types is greater than 255. This can give problems when saving the cache to file." +#endif + +typedef struct { + unsigned char qlen; /* Length of the domain name which follows after the struct. */ + unsigned char num_rrs; /* Number of RR-sets. */ + unsigned short flags; /* Flags for the whole cent. */ + unsigned char c_ns,c_soa; /* Number of trailing name elements in qname to use to find NS or SOA + records to add to the authority section of a response. */ + /* ttl and ts follow but only for negatively cached domains. */ + /* qname (with length qlen) follows here. */ +} __attribute__((packed)) +dns_file_t; + + +/* TTL and timestamp for negatively cached domains. */ +typedef struct { + time_t ttl; + time_t ts; +} __attribute__((packed)) +dom_fttlts_t; + +/* + * This has two modes: Normally, we have rrset, cent and idx filled in; + * for negatively cached cents, we have rrset set to NULL and idx set to -1. + */ +typedef struct rr_lent_s { + struct rr_lent_s *next; + struct rr_lent_s *prev; + rr_set_t *rrset; + dns_cent_t *cent; + int idx; /* This is the array index, not the type of the RR-set. */ +} rr_lent_t; + + +static rr_lent_t *rrset_l=NULL; +static rr_lent_t *rrset_l_tail=NULL; + +/* + * We do not count the hash table sizes here. Those are very small compared + * to the cache entries. + */ +static volatile long cache_size=0; +static volatile long ent_num=0; + +static volatile int cache_w_lock=0; +static volatile int cache_r_lock=0; + +pthread_mutex_t lock_mutex = PTHREAD_MUTEX_INITIALIZER; +/* + * These are condition variables for lock coordination, so that normal lock + * routines do not need to loop. Basically, a process wanting to acquire a lock + * tries first to lock, and if the lock is busy, sleeps on one of the conds. + * If the r lock count has gone to zero one process sleeping on the rw cond + * will be awankened. + * If the rw lock is lifted, either all threads waiting on the r lock or one + * thread waiting on the rw lock is/are awakened. This is determined by policy. + */ +pthread_cond_t rw_cond = PTHREAD_COND_INITIALIZER; +pthread_cond_t r_cond = PTHREAD_COND_INITIALIZER; + +/* This is to suspend the r lock to avoid lock contention by reading threads */ +static volatile int r_pend=0; +static volatile int rw_pend=0; +static volatile int r_susp=0; + +/* This threshold is used to temporarily suspend r locking to give rw locking + * a chance. */ +#define SUSP_THRESH(r_pend) (r_pend/2+2) + +/* + * This is set to 1 once the lock is intialized. This must happen before we get + * multiple threads. + */ +volatile short int use_cache_lock=0; + +/* + This is set to 0 while cache is read from disk. + This must be set to 1 before we start adding new entries. +*/ +static short int insert_sort=1; + + +#ifdef ALLOC_DEBUG +#define cache_free(ptr) { if (dbg) pdnsd_free(ptr); else free(ptr); } +#define cache_malloc(sz) ((dbg)?(pdnsd_malloc(sz)):(malloc(sz))) +#define cache_calloc(n,sz) ((dbg)?(pdnsd_calloc(n,sz)):(calloc(n,sz))) +#define cache_realloc(ptr,sz) ((dbg)?(pdnsd_realloc(ptr,sz)):(realloc(ptr,sz))) +#else +#define cache_free(ptr) {free(ptr);} +#define cache_malloc(sz) (malloc(sz)) +#define cache_calloc(n,sz) (calloc(n,sz)) +#define cache_realloc(ptr,sz) (realloc(ptr,sz)) +#endif + + +/* + * Prototypes for internal use + */ +static void purge_cache(long sz, int lazy); +static void del_cache_ent(dns_cent_t *cent,dns_hash_loc_t *loc); +static void remove_rrl(rr_lent_t *le DBGPARAM); + +/* + * Locking functions. + */ + +/* + * Lock/unlock cache for reading. Concurrent reads are allowed, while writes are forbidden. + * DO NOT MIX THE LOCK TYPES UP WHEN LOCKING/UNLOCKING! + * + * We use a mutex to lock the access to the locks ;-). + * This is because we do not allow read and write to interfere (for which a normal mutex would be + * fine), but we also want to allow concurrent reads. + * We use condition variables, and readlock contention protection. + */ +static void lock_cache_r(void) +{ + if (!use_cache_lock) + return; + pthread_mutex_lock(&lock_mutex); + r_pend++; + while(((rw_pend>SUSP_THRESH(r_pend))?(r_susp=1):r_susp) || cache_w_lock) { + /* This will unlock the mutex while sleeping and relock it before exit */ + pthread_cond_wait(&r_cond, &lock_mutex); + } + cache_r_lock++; + r_pend--; + pthread_mutex_unlock(&lock_mutex); +} + +static void unlock_cache_r(void) +{ + if (!use_cache_lock) + return; + pthread_mutex_lock(&lock_mutex); + if (cache_r_lock>0) + cache_r_lock--; + /* wakeup threads waiting to write */ + if (!cache_r_lock) + pthread_cond_signal(&rw_cond); + pthread_mutex_unlock(&lock_mutex); +} + +/* + * Lock/unlock cache for reading and writing. Concurrent reads and writes are forbidden. + * Do this only if you actually modify the cache. + * DO NOT MIX THE LOCK TYPES UP WHEN LOCKING/UNLOCKING! + * (cant say it often enough) + */ +static void lock_cache_rw(void) +{ + if (!use_cache_lock) + return; + pthread_mutex_lock(&lock_mutex); + rw_pend++; + while(cache_w_lock || cache_r_lock) { + /* This will unlock the mutex while sleeping and relock it before exit */ + pthread_cond_wait(&rw_cond, &lock_mutex); + } + cache_w_lock=1; + rw_pend--; + pthread_mutex_unlock(&lock_mutex); +} + +/* Lock cache for reading and writing, or time out after tm seconds. */ +static int timedlock_cache_rw(int tm) +{ + int retval=0; + struct timeval now; + struct timespec timeout; + + if (!use_cache_lock) + return 0; + pthread_mutex_lock(&lock_mutex); + gettimeofday(&now,NULL); + timeout.tv_sec = now.tv_sec + tm; + timeout.tv_nsec = now.tv_usec * 1000; + rw_pend++; + while(cache_w_lock || cache_r_lock) { + /* This will unlock the mutex while sleeping and relock it before exit */ + if(pthread_cond_timedwait(&rw_cond, &lock_mutex, &timeout) == ETIMEDOUT) + goto cleanup_return; + } + cache_w_lock=1; + retval=1; + cleanup_return: + rw_pend--; + pthread_mutex_unlock(&lock_mutex); + return retval; +} + +static void unlock_cache_rw(void) +{ + if (!use_cache_lock) + return; + pthread_mutex_lock(&lock_mutex); + cache_w_lock=0; + /* always reset r suspension (r locking code will set it again) */ + r_susp=0; + /* wakeup threads waiting to read or write */ + if (r_pend==0 || rw_pend>SUSP_THRESH(r_pend)) + pthread_cond_signal(&rw_cond); /* schedule another rw proc */ + else + pthread_cond_broadcast(&r_cond); /* let 'em all read */ + pthread_mutex_unlock(&lock_mutex); +} + + +/* + If there are other threads waiting to read from or write to + the cache, give up the read/write lock on the cache to give another + thread a chance; then try to get the lock back again. + This can be called regularly during a process that takes + a lot of processor time but has low priority, in order to improve + overall responsiveness. +*/ +static void yield_lock_cache_rw() +{ + if (!use_cache_lock || (!r_pend && !rw_pend)) + return; + + /* Give up the lock */ + pthread_mutex_lock(&lock_mutex); + cache_w_lock=0; + /* always reset r suspension (r locking code will set it again) */ + r_susp=0; + /* wakeup threads waiting to read or write */ + if (r_pend==0 || rw_pend>SUSP_THRESH(r_pend)) + pthread_cond_signal(&rw_cond); /* schedule another rw proc */ + else + pthread_cond_broadcast(&r_cond); /* let 'em all read */ + pthread_mutex_unlock(&lock_mutex); + + usleep_r(1000); + + /* Now try to get the lock back again */ + pthread_mutex_lock(&lock_mutex); + rw_pend++; + while(cache_w_lock || cache_r_lock) { + /* This will unlock the mutex while sleeping and relock it before exit */ + pthread_cond_wait(&rw_cond, &lock_mutex); + } + cache_w_lock=1; + rw_pend--; + pthread_mutex_unlock(&lock_mutex); +} + +/* These are a special version of the ordinary read lock functions. The lock "soft" to avoid deadlocks: they will give up + * after a certain number of bad trials. You have to check the exit status though. + * To avoid blocking mutexes, we cannot use condition variables here. Never mind, these are only used on + * exit. */ +static int softlock_cache_r(void) +{ + if (!use_cache_lock) + return 0; + { + int lk=0,tr=0; + + for(;;) { + if (!softlock_mutex(&lock_mutex)) + return 0; + if(!cache_w_lock) { + lk=1; + cache_r_lock++; + } + pthread_mutex_unlock(&lock_mutex); + if (lk) break; + if (++tr>=SOFTLOCK_MAXTRIES) + return 0; + usleep_r(1000); /*give contol back to the scheduler instead of hammering the lock close*/ + } + } + return 1; +} + +/* On unlocking, we do not wake others. We are about to exit! */ +static int softunlock_cache_r(void) +{ + if (!use_cache_lock) + return 0; + if (!softlock_mutex(&lock_mutex)) + return 0; + if (cache_r_lock>0) + cache_r_lock--; + pthread_mutex_unlock(&lock_mutex); + return 1; +} + +static int softlock_cache_rw(void) +{ + if (!use_cache_lock) + return 0; + { + int lk=0,tr=0; + + for(;;) { + if (!softlock_mutex(&lock_mutex)) + return 0; + if (!(cache_w_lock || cache_r_lock)) { + lk=1; + cache_w_lock=1; + } + pthread_mutex_unlock(&lock_mutex); + if(lk) break; + if (++tr>=SOFTLOCK_MAXTRIES) + return 0; + usleep_r(1000); /*give contol back to the scheduler instead of hammering the lock close*/ + } + } + return 1; +} + +static int softunlock_cache_rw(void) +{ + if (!use_cache_lock) + return 0; + if (!softlock_mutex(&lock_mutex)) + return 0; + cache_w_lock=0; + pthread_mutex_unlock(&lock_mutex); + return 1; +} + +/* + * Serial numbers: Serial numbers are used when additional records are added to the cache: serial numbers are unique to each + * query, so we can determine whether data was added by the query just executed (records can coexist) or not (records must + * be replaced). A serial of 0 is special and will not be used by any query. All records added added authoritatively (as + * chunk) or read from a file can have no query in process and therefore have serial 0, which is != any other serial. + */ +#if 0 +unsigned long l_serial=1; + +unsigned long get_serial() +{ + unsigned long rv; + lock_cache_rw(); + rv=l_serial++; + unlock_cache_rw(); + return rv; +} +#endif + +/* + * Cache/cent handlers + */ + +/* Initialize the cache. Call only once. */ +#if 0 +void init_cache() +{ + mk_hash_ctable(); + mk_dns_hash(); +} +#endif + +/* Initialize the cache lock. Call only once. */ +/* This is now defined as an inline function in cache.h */ +#if 0 +void init_cache_lock() +{ + + use_cache_lock=1; +} +#endif + +/* Empty the cache, freeing all entries that match the include/exclude list. */ +int empty_cache(slist_array sla) +{ + int i; + + /* Wait at most 60 seconds to obtain a lock. */ + if(!timedlock_cache_rw(60)) + return 0; + + for(i=0; ; ) { + if(sla) + free_dns_hash_selected(i,sla); + else + free_dns_hash_bucket(i); + if(++i>=HASH_NUM_BUCKETS) + break; + /* Give another thread a chance */ + yield_lock_cache_rw(); + } + + unlock_cache_rw(); + return 1; +} + +/* Delete the cache. Call only once */ +void destroy_cache() +{ + /* lock the cache, in case that any thread is still accessing. */ + if(!softlock_cache_rw()) { + log_error("Lock failed; could not destroy cache on exit."); + return; + } + free_dns_hash(); +#if DEBUG>0 + if(ent_num || cache_size) { + DEBUG_MSG("After destroying cache, %ld entries (%ld bytes) remaining.\n",ent_num,cache_size); + } +#endif + +#if 0 +#if (TARGET!=TARGET_LINUX) + /* under Linux, this frees no resources but may hang on a crash */ + pthread_mutex_destroy(&lock_mutex); + pthread_cond_destroy(&rw_cond); + pthread_cond_destroy(&r_cond); +#endif +#endif +} + +/* Make a flag value for a dns_cent_t (dns cache entry) from a server record */ +/* Now defined as inline function in cache.h */ +#if 0 +unsigned int mk_flag_val(servparm_t *server) +{ + unsigned int fl=0; + if (!server->purge_cache) + fl|=CF_NOPURGE; + if (server->nocache) + fl|=CF_NOCACHE; + if (server->rootserver) + fl|=CF_ROOTSERV; + return fl; +} +#endif + +/* Initialize a dns cache record (dns_cent_t) with the query name (in + * transport format), a flag value, a timestamp indicating + * the time the query was done, and a TTL. The timestamp and TTL + * are only used if DF_NEGATIVE is set in the flags. Otherwise, + * the timestamps of the individual records are used. DF_NEGATIVE + * is used for whole-domain negative caching. + * By convention, ttl and ts should be set to 0, unless the + * DF_NEGATIVE bit is set. */ +int init_cent(dns_cent_t *cent, const unsigned char *qname, time_t ttl, time_t ts, unsigned flags DBGPARAM) +{ + int i; + size_t namesz=rhnlen(qname); + + cent->qname=cache_malloc(namesz); + if (cent->qname == NULL) + return 0; + memcpy(cent->qname,qname,namesz); + cent->cs=sizeof(dns_cent_t)+namesz; + cent->num_rrs=0; + cent->flags=flags; + if(flags&DF_NEGATIVE) { + cent->neg.lent=NULL; + cent->neg.ttl=ttl; + cent->neg.ts=ts; + } + else { + for(i=0; irr.rrmu[i]=NULL; + cent->rr.rrext=NULL; + } + cent->c_ns=cundef; + cent->c_soa=cundef; + return 1; +} + +/* + * Create a rr record holder using the given values. + */ +static rr_bucket_t *create_rr(unsigned dlen, void *data DBGPARAM) +{ + rr_bucket_t *rrb; + rrb=(rr_bucket_t *)cache_malloc(sizeof(rr_bucket_t)+dlen); + if (rrb == NULL) + return NULL; + rrb->next=NULL; + + rrb->rdlen=dlen; + memcpy(rrb->data,data,dlen); + return rrb; +} + +/* + * Adds an empty rrset_t with the requested data to a cent. This is exactly what you need to + * do to create a negatively cached cent. + */ +static int add_cent_rrset_by_index(dns_cent_t *cent, unsigned int idx, time_t ttl, time_t ts, unsigned flags DBGPARAM) +{ + rr_set_t **rrext, **rrsetpa, *rrset; + + /* If we add a rrset, even a negative one, the domain is not negative any more. */ + if (cent->flags&DF_NEGATIVE) { + int i; + /* need to remove the cent from the lent list. */ + if (cent->neg.lent) + remove_rrl(cent->neg.lent DBGARG); + cent->flags &= ~DF_NEGATIVE; + for(i=0; irr.rrmu[i]=NULL; + cent->rr.rrext=NULL; + } + + if(idx < NRRMU) + rrsetpa = ¢->rr.rrmu[idx]; + else { + idx -= NRRMU; + PDNSD_ASSERT(idx < NRREXT, "add_cent_rrset_by_index: rr-set index out of range"); + rrext = cent->rr.rrext; + if(!rrext) { + int i; + cent->rr.rrext = rrext = cache_malloc(sizeof(rr_set_t*)*NRREXT); + if(!rrext) + return 0; + for(i=0; ics += sizeof(rr_set_t*)*NRREXT; + } + rrsetpa = &rrext[idx]; + } + +#if 0 + if(*rrsetpa) del_rrset(*rrsetpa); +#endif + *rrsetpa = rrset = cache_malloc(sizeof(rr_set_t)); + if (!rrset) + return 0; + rrset->lent=NULL; + rrset->ttl=ttl; + rrset->ts=ts; + rrset->flags=flags; + rrset->rrs=NULL; + cent->cs += sizeof(rr_set_t); + ++cent->num_rrs; + return 1; +} + +int add_cent_rrset_by_type(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags DBGPARAM) +{ + int tpi = type - T_MIN; + + PDNSD_ASSERT(tpi>=0 && tpinext=rrset->rrs; + rrset->rrs=rr; + } + else { + /* append at the end */ + rr->next=(*rtail)->next; + (*rtail)->next=rr; + } + if(rtail) *rtail=rr; + cent->cs += sizeof(rr_bucket_t)+rr->rdlen; +#if DEBUG>0 + if(debug_p) { + rrset = RRARR_INDEX(cent,idx); + if (rrset->flags&CF_NEGATIVE) { + char cflagstr[CFLAGSTRLEN]; + DEBUG_MSG("Tried to add rr to a rrset with CF_NEGATIVE set! flags=%s\n",cflags2str(rrset->flags,cflagstr)); + } + } +#endif + return 1; + + cleanup_return: + free_rr(*rr); + free(rr); + return 0; +} + + +/* Add an rr to a cache entry, giving the ttl, the data length, the rr type + * and a pointer to the data. A record is allocated, and the data is copied into + * it. Do this for all rrs in a cache entry. + * The return value will be 1 in case of success, or 0 in case of a memory allocation + * problem. + */ +int add_cent_rr(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags, + unsigned dlen, void *data DBGPARAM) +{ + int tpi; + unsigned int idx; + rr_set_t *rrset; + rr_bucket_t *rtail, *rrb; + + if ((cent->flags&DF_LOCAL) && !(flags&CF_LOCAL)) + return 1; /* ignore. Local has precedence. */ + + tpi = type - T_MIN; + PDNSD_ASSERT(tpi>=0 && tpittl) + /* The ttl timestamps should be identical. + In case they are not, we will use the smallest one. */ + rrset->ttl= ttl; + + /* OK, some stupid nameservers feel inclined to return the same address twice. Grmbl... */ + rrb=rrset->rrs; + while (rrb) { + if (rrb->rdlen==dlen && memcmp(rrb->data,data,dlen)==0) + return 1; + rtail=rrb; + rrb=rrb->next; + } + } + return add_cent_rr_int(cent,idx,ttl,ts,flags,dlen,data,&rtail DBGARG); +} + +/* Free a complete rrset including all memory. Returns the size of the memory freed */ +int del_rrset(rr_set_t *rrs DBGPARAM) +{ + int rv=sizeof(rr_set_t); + rr_bucket_t *rrb,*rrn; + + if(rrs->lent) remove_rrl(rrs->lent DBGARG); + rrb=rrs->rrs; + while (rrb) { + rv+=sizeof(rr_bucket_t)+rrb->rdlen; + rrn=rrb->next; + free_rr(*rrb); + cache_free(rrb); + rrb=rrn; + } + cache_free(rrs); + return rv; +} + +/* Remove a complete rrset from a cent, freeing the memory. + The second argument should be an RR-set array index, not an RR type! + Returns the size of the memory freed */ +static int del_cent_rrset_by_index(dns_cent_t *cent, int i DBGPARAM) +{ + int rv=0; + rr_set_t **rrspa = RRARR_INDEX_PA_TESTEXT(cent,i); + + if(rrspa) { + rr_set_t *rrs = *rrspa; + if(rrs) { + rv= del_rrset(rrs DBGARG); + *rrspa=NULL; + --cent->num_rrs; + cent->cs -= rv; + cent->flags &= ~DF_AUTH; + } + } + return rv; +} + +#if 0 +static int del_cent_rrset_by_type(dns_cent_t *cent, int type DBGPARAM) +{ + return del_cent_rrset_by_index(cent, rrlkuptab[type-T_MIN] DBGARG); +} +#endif + +#if 0 +/* Free the pointers contained in an rr record. If the rr record is on the heap, + * don't forget to delete itself. This is done extra mainly for extensibility + * -- This is not here any more. The definition is actually an empty macro in + * cache.h. + */ +void free_rr(rr_bucket_t rr) +{ +} +#endif + +/* Free all data referred by a cache entry. */ +void free_cent(dns_cent_t *cent DBGPARAM) +{ + cache_free(cent->qname); + if(cent->flags&DF_NEGATIVE) { + if(cent->neg.lent) + remove_rrl(cent->neg.lent DBGARG); + } + else { + int i; + for (i=0; irr.rrmu[i]; + if (rrs) del_rrset(rrs DBG0); + } + { + rr_set_t **rrext = cent->rr.rrext; + if(rrext) { + for(i=0; iflags&DF_NEGATIVE)) { + for (i=0; irr.rrmu[i]; + if (rrs) { + cent->cs -= del_rrset(rrs DBG0); + /* cent->rr.rrmu[i]=NULL; */ + } + } + { + rr_set_t **rrext = cent->rr.rrext; + if(rrext) { + for(i=0; ics -= del_rrset(rrs DBG0); + } + cache_free(rrext); + /* cent->rr.rrext=NULL; */ + cent->cs -= sizeof(rr_set_t*)*NRREXT; + } + } + cent->num_rrs=0; + cent->flags |= DF_NEGATIVE; + cent->neg.lent=NULL; + } + + cent->neg.ttl=ttl; + cent->neg.ts=ts; +} + +inline static time_t get_rrlent_ts(rr_lent_t *le) +{ + return (le->rrset)?(le->rrset->ts):(le->cent->neg.ts); +} + +/* insert a rrset into the rr_l list. This modifies the rr_set_t if rrs is not NULL! + * The rrset address needs to be constant afterwards. + * idx is the internally used RR-set index, not the RR type! + * Call with locks applied. */ +static int insert_rrl(rr_set_t *rrs, dns_cent_t *cent, int idx) +{ + time_t ts; + rr_lent_t *le,*ne; + + /* No need to add local records to the rr_l list, because purge_cache() ignores them anyway. */ + if((rrs && (rrs->flags&CF_LOCAL)) || (cent->flags&DF_LOCAL)) + return 1; + + if (!(ne=malloc(sizeof(rr_lent_t)))) + return 0; + ne->rrset=rrs; + ne->cent=cent; + ne->idx=idx; + ne->next=NULL; + ne->prev=NULL; + + if(insert_sort) { + /* Since the append at the and is a very common case (and we want this case to be fast), we search back-to-forth. + * Since rr_l is a list and we don't really have fast access to all elements, we do not perform an advanced algorithm + * like binary search.*/ + ts=get_rrlent_ts(ne); + le=rrset_l_tail; + while (le) { + if (ts>=get_rrlent_ts(le)) goto found; + le=le->prev; + } + /* not found, so it needs to be inserted at the start of the list. */ + ne->next=rrset_l; + if (rrset_l) + rrset_l->prev=ne; + else + rrset_l_tail=ne; + rrset_l=ne; + goto finish; + found: + ne->next=le->next; + ne->prev=le; + if (le->next) + le->next->prev=ne; + else + rrset_l_tail=ne; + le->next=ne; + finish:; + } + else { + /* simply append at the end, sorting will be done later with a more efficient algorithm. */ + ne->prev=rrset_l_tail; + if(rrset_l_tail) + rrset_l_tail->next=ne; + else + rrset_l=ne; + rrset_l_tail=ne; + } + + if (rrs) + rrs->lent=ne; + else + cent->neg.lent=ne; + + return 1; +} + +/* Remove a rr from the rr_l list. Call with locks applied. */ +static void remove_rrl(rr_lent_t *le DBGPARAM) +{ + rr_lent_t *next=le->next,*prev=le->prev; + if (next) + next->prev=prev; + else + rrset_l_tail=prev; + if (prev) + prev->next=next; + else + rrset_l=next; + cache_free(le); +} + + +/* Merge two sorted rr_l lists to make a larger sorted list. + The lists are sorted according to increasing time-stamp. + The back links are ignored, these must be fixed using a separate pass. +*/ +static rr_lent_t *listmerge(rr_lent_t *p, rr_lent_t *q) +{ + + if(!p) + return q; + else if(!q) + return p; + else { + rr_lent_t *l=NULL, **s= &l; + + for(;;) { + if(get_rrlent_ts(p) <= get_rrlent_ts(q)) { + *s= p; + s= &p->next; + p= *s; + if(!p) { + *s= q; + break; + } + } + else { /* get_rrlent_ts(p) > get_rrlent_ts(q) */ + *s= q; + s= &q->next; + q= *s; + if(!q) { + *s= p; + break; + } + } + } + + return l; + } +} + +/* Sort the rr_l list using merge sort, which can be more efficient than insertion sort used by rr_insert(). + This algorithm is adapted from the GNU C++ STL implementation for list containers. + Call with locks applied. + Written by Paul Rombouts. +*/ +static void sort_rrl() +{ + /* Do nothing unless the list has length >= 2. */ + if(rrset_l && rrset_l->next) { + /* First sort the list ignoring the back links, these will be fixed later. */ +# define NTMPSORT 32 + /* Because we use an array of fixed length, the length of the list we can sort + is bounded by pow(2,NTMPSORT)-1. */ + rr_lent_t *tmp[NTMPSORT]; /* tmp[i] will either be NULL or point to a sorted list of length pow(2,i). */ + rr_lent_t **fill= tmp, **end=tmp+NTMPSORT, **counter; + rr_lent_t *rem= rrset_l, *carry; + + do { + carry=rem; rem=rem->next; + carry->next=NULL; + for(counter = tmp; counter!=fill && *counter!=NULL; ++counter) { + carry=listmerge(*counter,carry); + *counter=NULL; + } + + PDNSD_ASSERT(counter!=end, "sort_rrl: tmp array overflowed"); + + *counter=carry; + + if(counter==fill) ++fill; + } + while(rem); + + /* Merge together all the remaining list fragments contained in array tmp. */ + carry= tmp[0]; + counter= tmp; + while(++counter!=fill) + carry=listmerge(*counter,carry); + + rrset_l= carry; + + { + /* Restore the backward links. */ + rr_lent_t *p,*q=NULL; + for(p=rrset_l; p; p=p->next) {p->prev=q; q=p;} + rrset_l_tail=q; + } + } +} + + +/* Copy a rr_bucket_t into newly allocated memory */ +inline static rr_bucket_t *copy_rr(rr_bucket_t *rr DBGPARAM) +{ + rr_bucket_t *rrn; + rrn=cache_malloc(sizeof(rr_bucket_t)+rr->rdlen); + if (rrn == NULL) + return NULL; + memcpy(rrn,rr,sizeof(rr_bucket_t)+rr->rdlen); + rrn->next=NULL; + return rrn; +} + + +/* Copy an RR set into newly allocated memory */ +static rr_set_t *copy_rrset(rr_set_t *rrset DBGPARAM) +{ + rr_set_t *rrsc=cache_malloc(sizeof(rr_set_t)); + rr_bucket_t *rr,**rrp; + if (rrsc) { + *rrsc=*rrset; + rrsc->lent=NULL; + rrp=&rrsc->rrs; + rr=rrset->rrs; + while(rr) { + rr_bucket_t *rrc=copy_rr(rr DBGARG); + *rrp=rrc; + if (!rrc) goto cleanup_return; + rrp=&rrc->next; + rr=rr->next; + } + } + return rrsc; + +cleanup_return: + del_rrset(rrsc DBG0); + return NULL; +} + + +/* Copy a cache entry into newly allocated memory */ +dns_cent_t *copy_cent(dns_cent_t *cent DBGPARAM) +{ + dns_cent_t *copy; + + /* + * We do not debug cache internals with it, as mallocs seem to be + * "lost" when they enter the cache for a longer time. + */ + if (!(copy=cache_malloc(sizeof(dns_cent_t)))) + return NULL; + + { + /* copy the name */ + size_t namesz=rhnlen(cent->qname); + if (!(copy->qname=cache_malloc(namesz))) + goto free_return_null; + + memcpy(copy->qname,cent->qname,namesz); + } + copy->cs= cent->cs; + copy->num_rrs= cent->num_rrs; + copy->flags= cent->flags; + copy->c_ns = cent->c_ns; + copy->c_soa= cent->c_soa; + if(cent->flags&DF_NEGATIVE) { + copy->neg.lent=NULL; + copy->neg.ttl= cent->neg.ttl; + copy->neg.ts = cent->neg.ts; + } + else { + int i, ilim; + for (i=0; irr.rrmu[i]=NULL; + copy->rr.rrext=NULL; + + ilim = NRRMU; + if(cent->rr.rrext) { + rr_set_t **rrextc; + ilim = NRRTOT; + copy->rr.rrext = rrextc = cache_malloc(sizeof(rr_set_t*)*NRREXT); + if(!rrextc) goto free_cent_return_null; + + for (i=0; ilent=NULL; + rrp=&rrsc->rrs; + rr=rrset->rrs; + while(rr) { + rr_bucket_t *rrc=copy_rr(rr DBGARG); + *rrp=rrc; + if (!rrc) goto free_cent_return_null; + rrp=&rrc->next; + rr=rr->next; + } + } + } + } + return copy; + + free_cent_return_null: + free_cent(copy DBGARG); + free_return_null: + cache_free(copy); + return NULL; +} + +/* + * Remove all timed out entries of the RR set with the given index. + * idx is the internally used RR-set index, not the RR type! + * Follow some rules based on flags etc. + * This will either delete the whole rrset, or will leave it as a whole (RFC2181 seems to + * go in that direction) + * This was pretty large once upon a time ;-), but now, since we operate in rrsets, was + * shrunk drastically. + * If test is zero and the record is in the cache, we need rw-locks applied. + * If test is nonzero, nothing will actually be deleted. + * Substracts the size of the freed memory from cache_size (if test is zero). + * Returns 1 if the rrset has been (or would have been) deleted. + */ +static int purge_rrset(dns_cent_t *cent, int idx, int test) +{ + rr_set_t *rrs= RRARR_INDEX_TESTEXT(cent,idx); + if (rrs && !(rrs->flags&CF_NOPURGE || rrs->flags&CF_LOCAL) && timedout(rrs)) { + /* well, it must go. */ + if(!test) + cache_size -= del_cent_rrset_by_index(cent,idx DBG0); + return 1; + } + return 0; +} + +/* + Remove all timed out entries of alls RR sets of a cache entry. + The test flag works the same as in purge_rrset(). + Substracts the size of the freed memory from cache_size, just as purge_rrset(). + *numrrsrem is set to the number of remaining RR sets (or the number that would have remained). + Returns the number of items (RR sets or RR set arrays) that have been (or would have been) deleted. +*/ +static int purge_all_rrsets(dns_cent_t *cent, int test, int *numrrsrem) +{ + int rv=0, numrrs=0, numrrext=0; + + if(!(cent->flags&DF_NEGATIVE)) { + int i, ilim= RRARR_LEN(cent); + for(i=0; iflags&CF_NOPURGE || rrs->flags&CF_LOCAL) && timedout(rrs)) { + /* well, it must go. */ + if(!test) + cache_size -= del_cent_rrset_by_index(cent, i DBG0); + ++rv; + } + else { + ++numrrs; + if(i>=NRRMU) ++numrrext; + } + } + } + + /* If the array of less frequently used RRs has become empty, free it. */ + if(cent->rr.rrext && numrrext==0) { + if(!test) { + cache_free(cent->rr.rrext); + cent->rr.rrext=NULL; + cent->cs -= sizeof(rr_set_t*)*NRREXT; + cache_size -= sizeof(rr_set_t*)*NRREXT; + } + ++rv; + } + } + + if(numrrsrem) *numrrsrem=numrrs; + return rv; +} + + +/* + * Purge a cent, deleting timed-out rrs (following the constraints noted in "purge_rrset"). + * Since the cent may actually become empty and be deleted, you may not use it after this call until + * you refetch its address from the hash (if it is still there). + * If test is zero and the record is in the cache, we need rw-locks applied. + * If test is nonzero, nothing will actually be deleted. + * Substracts the size of the freed memory from cache_size (if test is zero). + * If delete is nonzero and the cent was purged empty and no longer needed, it is removed from the cache. + * Returns -1 if the cent was (or would have been) completely removed, + * otherwise returns the number of items that were (or would have been) deleted. + */ +static int purge_cent(dns_cent_t *cent, int delete, int test) +{ + int npurge, numrrs; + + npurge = purge_all_rrsets(cent,test, &numrrs); + + /* If the cache entry was purged empty, delete it from the cache. */ + if (delete && numrrs==0 + && (!(cent->flags&DF_NEGATIVE) || + (!(cent->flags&DF_LOCAL) && timedout_nxdom(cent)))) + { + if(!test) + del_cache_ent(cent,NULL); /* this will subtract the cent's left size from cache_size */ + return -1; + } + + if(!(cent->flags&DF_LOCAL)) { + /* Set stale references to NS or SOA records back to undefined. */ + unsigned scnt=rhnsegcnt(cent->qname); + if(cent->c_ns!=cundef) { + rr_set_t *rrset=NULL; + if(cent->c_ns==scnt) + rrset=getrrset_NS(cent); + else if(cent->c_nsqname,scnt-cent->c_ns),NULL); + if(ce) rrset=getrrset_NS(ce); + } + if(!rrset || !rrset->rrs || (!(rrset->flags&CF_LOCAL) && timedout(rrset))) { + if(!test) + cent->c_ns=cundef; + ++npurge; + } + } + if(cent->c_soa!=cundef) { + rr_set_t *rrset=NULL; + if(cent->c_soa==scnt) + rrset=getrrset_SOA(cent); + else if(cent->c_soaqname,scnt-cent->c_soa),NULL); + if(ce) rrset=getrrset_SOA(ce); + } + if(!rrset || !rrset->rrs || (!(rrset->flags&CF_LOCAL) && timedout(rrset))) { + if(!test) + cent->c_soa=cundef; + ++npurge; + } + } + } + + return npurge; +} + +/* + * Bring cache to a size below or equal the cache size limit (sz). There are two strategies: + * - for cached sets with CF_NOPURGE not set: delete if timed out + * - additional: delete oldest sets. + */ +static void purge_cache(long sz, int lazy) +{ + rr_lent_t *le; + + /* Walk the cache list from the oldest entries to the newest, deleting timed-out + * records. + * XXX: We walk the list a second time if this did not free up enough space - this + * should be done better. */ + le=rrset_l; + while (le && (!lazy || cache_size>sz)) { + /* Note by Paul Rombouts: + * If data integrity is ensured, at most one node is removed from the rrset_l + * per iteration, and this node is the one referenced by le. */ + rr_lent_t *next=le->next; + if (!((le->rrset && (le->rrset->flags&CF_LOCAL)) || + (le->cent->flags&DF_LOCAL))) { + dns_cent_t *ce = le->cent; + if (le->rrset) + purge_rrset(ce, le->idx,0); + /* Side effect: if purge_rrset called del_cent_rrset then le has been freed. + * ce, however, is still guaranteed to be valid. */ + if (ce->num_rrs==0 && (!(ce->flags&DF_NEGATIVE) || + (!(ce->flags&DF_LOCAL) && timedout_nxdom(ce)))) + del_cache_ent(ce,NULL); + } + le=next; + } + if (cache_size<=sz) + return; + + /* we are still above the desired cache size. Well, delete records from the oldest to + * the newest. This is the case where nopurge records are deleted anyway. Only local + * records are kept in any case.*/ + if(!insert_sort) { + sort_rrl(); + insert_sort=1; /* use insertion sort from now on */ + } + + le=rrset_l; + while (le && cache_size>sz) { + rr_lent_t *next=le->next; + if (!((le->rrset && (le->rrset->flags&CF_LOCAL)) || + (le->cent->flags&DF_LOCAL))) { + dns_cent_t *ce = le->cent; + if (le->rrset) + cache_size -= del_cent_rrset_by_index(ce, le->idx DBG0); + /* this will also delete negative cache entries */ + if (ce->num_rrs==0) + del_cache_ent(ce,NULL); + } + le=next; + } +} + +#define log_warn_read_error(f,item) \ + log_warn("%s encountered while reading %s from disk cache file.", \ + ferror(f)?"Error":feof(f)?"EOF":"Incomplete item",item) + +/* + * Load cache from disk and rebuild the hash tables. + */ +void read_disk_cache() +{ + /* The locks are done when we add items. */ + dns_cent_t ce; + int dtsz=512; + unsigned char *data; + unsigned long cnt; + FILE *f; + + char path[strlen(global.cache_dir)+sizeof("/pdnsd.cache")]; + + stpcpy(stpcpy(path,global.cache_dir),"/pdnsd.cache"); + + if (!(f=fopen(path,"r"))) { + log_warn("Could not open disk cache file %s: %s",path,strerror(errno)); + return; + } + + if (!(data = malloc(dtsz))) { + goto fclose_exit; + } + + /* Don't use insertion sort while reading caches entries from disk, because this can be + noticeably inefficient with large cache files. + Entries are simply appended at the end of the rr_l list. + The rr_l list is sorted using a more efficient merge sort after we are done reading. + */ + insert_sort=0; + + { + unsigned nb; + char buf[sizeof(cachverid)]; + + /* check cache version identifier */ + nb=fread(buf,1,sizeof(cachverid),f); + if (nb!=sizeof(cachverid)) { + /* Don't complain about empty files */ + if(nb!=0 || !feof(f)) { + log_warn_read_error(f,"cache version identifier"); + } + goto free_data_fclose; + } + if(memcmp(buf,cachverid,sizeof(cachverid))) { + log_warn("Cache file %s ignored because of incompatible version identifier",path); + goto free_data_fclose; + } + } + + if (fread(&cnt,sizeof(cnt),1,f)!=1) { + log_warn_read_error(f,"entry count"); + goto free_data_fclose; + } + + for(;cnt>0;--cnt) { + dns_file_t fe; + dom_fttlts_t fttlts = {0,0}; + unsigned char nb[256]; + unsigned num_rrs; + unsigned char prevtp; + if (fread(&fe,sizeof(fe),1,f)!=1) { + log_warn_read_error(f,"cache entry header"); + goto free_data_fclose; + } + if(fe.flags&DF_NEGATIVE) { + if (fread(&fttlts,sizeof(fttlts),1,f)!=1) { + log_warn_read_error(f,"cache TTL and timestamp"); + goto free_data_fclose; + } + } + if (fe.qlen) { + int i; + /* Because of its type qlen should be <=255. */ + if (fread(nb,fe.qlen,1,f)!=1) { + log_warn_read_error(f,"domain name"); + goto free_data_fclose; + } + for(i=0;i63 || (i += lb+1)>fe.qlen) { + log_warn("Invalid domain name encountered while reading disk cache file."); + goto free_data_fclose; + } + } + } + nb[fe.qlen]='\0'; + if (!init_cent(&ce, nb, fttlts.ttl, fttlts.ts, fe.flags DBG0)) { + goto free_data_fclose_exit; + } + ce.c_ns=fe.c_ns; ce.c_soa=fe.c_soa; + + /* now, read the rr's */ + prevtp=0; + for (num_rrs=fe.num_rrs;num_rrs;--num_rrs) { + rr_fset_t sh; + unsigned num_rr; + if (fread(&sh,sizeof(sh),1,f)!=1) { + log_warn_read_error(f,"rr header"); + goto free_cent_data_fclose; + } + if(PDNSD_NOT_CACHED_TYPE(sh.tp)) { + log_warn("Invalid rr type encountered while reading disk cache file."); + goto free_data_fclose; + } + if(sh.tp<=prevtp) { + log_warn("Unexpected rr type encountered (not in strict ascending order) while reading disk cache file."); + goto free_data_fclose; + } + prevtp=sh.tp; + /* Add the rrset header in any case (needed for negative caching) */ + if(!add_cent_rrset_by_type(&ce, sh.tp, sh.ttl, sh.ts, sh.flags DBG0)) { + goto free_cent_data_fclose_exit; + } + for (num_rr=sh.num_rr;num_rr;--num_rr) { + rr_fbucket_t rr; + if (fread(&rr,sizeof(rr),1,f)!=1) { + log_warn_read_error(f,"rr data length"); + goto free_cent_data_fclose; + } + if (rr.rdlen>dtsz) { + unsigned char *tmp; + dtsz=rr.rdlen; + tmp=realloc(data,dtsz); + if (!tmp) { + goto free_cent_data_fclose_exit; + } + data=tmp; + } + if (rr.rdlen && fread(data,rr.rdlen,1,f)!=1) { + log_warn_read_error(f,"rr data"); + goto free_cent_data_fclose; + } + if (!add_cent_rr(&ce,sh.tp,sh.ttl,sh.ts,sh.flags,rr.rdlen,data DBG0)) { + goto free_cent_data_fclose_exit; + } + } + } + add_cache(&ce); + free_cent(&ce DBG0); + } +#ifdef DEBUG_HASH + free(data); + fclose(f); + dumphash(); + goto sort_return; +#else + goto free_data_fclose; +#endif + + free_cent_data_fclose: + free_cent(&ce DBG0); + free_data_fclose: + free(data); + fclose(f); +#ifdef DEBUG_HASH + sort_return: +#endif + /* Do we need read/write locks to sort the rr_l list? + As long as at most one thread is sorting, it is OK for the other threads + to read the cache, providing they do not add or delete anything. + */ + lock_cache_r(); + if(!insert_sort) { + sort_rrl(); + insert_sort=1; + } + unlock_cache_r(); + return; + + free_cent_data_fclose_exit: + free_cent(&ce DBG0); + free_data_fclose_exit: + free(data); + fclose_exit: + fclose(f); + log_error("Out of memory in reading cache file. Exiting."); + pdnsd_exit(); +} + +/* write an rr to the file f */ +static int write_rrset(int tp, rr_set_t *rrs, FILE *f) +{ + rr_bucket_t *rr; + rr_fset_t sh; + rr_fbucket_t rf; + unsigned num_rr; + + sh.tp=tp; + + num_rr=0; + for(rr=rrs->rrs; rr && num_rr<255; rr=rr->next) ++num_rr; + sh.num_rr=num_rr; + sh.flags=rrs->flags; + sh.ttl=rrs->ttl; + sh.ts=rrs->ts; + + if (fwrite(&sh,sizeof(sh),1,f)!=1) { + log_error("Error while writing rr header to disk cache: %s", strerror(errno)); + return 0; + } + + rr=rrs->rrs; + for(; num_rr; --num_rr) { + rf.rdlen=rr->rdlen; + if (fwrite(&rf,sizeof(rf),1,f)!=1 || (rf.rdlen && fwrite((rr->data),rf.rdlen,1,f)!=1)) { + log_error("Error while writing rr data to disk cache: %s", strerror(errno)); + return 0; + } + rr=rr->next; + } + + return 1; +} + + +/* + * Write cache to disk on termination. The hash table is lost and needs to be regenerated + * on reload. + * + * The locks are not very fine grained here, but I don't think this needs fixing as this routine + * is only called on exit. + * + */ +void write_disk_cache() +{ + int j, jlim; + dns_cent_t *le; + unsigned long en=0; + dns_hash_pos_t pos; + FILE *f; + unsigned long num_rrs_errs=0; +# define MAX_NUM_RRS_ERRS 10 + + char path[strlen(global.cache_dir)+sizeof("/pdnsd.cache")]; + + stpcpy(stpcpy(path,global.cache_dir),"/pdnsd.cache"); + + DEBUG_MSG("Writing cache to %s\n",path); + + if (!softlock_cache_rw()) { + goto lock_failed; + } + /* purge cache down to allowed size*/ + purge_cache((long)global.perm_cache*1024, 0); + if (!softunlock_cache_rw()) { + goto lock_failed; + } + + if (!softlock_cache_r()) { + goto lock_failed; + } + + if (!(f=fopen(path,"w"))) { + log_warn("Could not open disk cache file %s: %s",path,strerror(errno)); + goto softunlock_return; + } + + /* Write the cache version identifier */ + if (fwrite(cachverid,sizeof(cachverid),1,f)!=1) { + log_error("Error while writing cache version identifier to disk cache: %s", strerror(errno)); + goto fclose_unlock; + } + + for (le=fetch_first(&pos); le; le=fetch_next(&pos)) { + /* count the rr's */ + if(le->flags&DF_NEGATIVE) { + if(!(le->flags&DF_LOCAL)) + ++en; + } + else { + jlim= RRARR_LEN(le); + for (j=0; jflags&CF_LOCAL)) { + ++en; + break; + } + } + } + } + if (fwrite(&en,sizeof(en),1,f)!=1) { + log_error("Error while writing entry count to disk cache: %s", strerror(errno)); + goto fclose_unlock; + } + + for (le=fetch_first(&pos); le; le=fetch_next(&pos)) { + /* now, write the rr's */ + if(le->flags&DF_NEGATIVE) { + if(!(le->flags&DF_LOCAL)) + goto write_rrs; + } + else { + jlim= RRARR_LEN(le); + for (j=0; jflags&CF_LOCAL)) { + goto write_rrs; + } + } + } + continue; + write_rrs: + { + dns_file_t df; + int num_rrs; + const unsigned short *iterlist; + df.qlen=rhnlen(le->qname)-1; /* Don't include the null byte at the end */ + df.num_rrs=0; + df.flags=le->flags; + df.c_ns=le->c_ns; df.c_soa=le->c_soa; + num_rrs=0; + jlim=RRARR_LEN(le); + for (j=0; jflags&CF_LOCAL)) + ++df.num_rrs; + } + } + if(num_rrs!=le->num_rrs && ++num_rrs_errs<=MAX_NUM_RRS_ERRS) { + unsigned char buf[DNSNAMEBUFSIZE]; + log_warn("Counted %d rr record types for %s but cached counter=%d", + num_rrs,rhn2str(le->qname,buf,sizeof(buf)),le->num_rrs); + } + if (fwrite(&df,sizeof(df),1,f)!=1) { + log_error("Error while writing cache entry header to disk cache: %s", strerror(errno)); + goto fclose_unlock; + } + if(le->flags&DF_NEGATIVE) { + dom_fttlts_t fttlts= {le->neg.ttl,le->neg.ts}; + if (fwrite(&fttlts,sizeof(fttlts),1,f)!=1) { + log_error("Error while writing cache TTL and timestamp to disk cache: %s", strerror(errno)); + goto fclose_unlock; + } + } + if (df.qlen && fwrite(le->qname,df.qlen,1,f)!=1) { + log_error("Error while writing domain name to disk cache: %s", strerror(errno)); + goto fclose_unlock; + } + + jlim= NRRITERLIST(le); + iterlist= RRITERLIST(le); + for (j=0; jflags&CF_LOCAL)) { + if(!write_rrset(tp,rrset,f)) + goto fclose_unlock; + } + } + } + } + if(fclose(f)) { + log_error("Could not close cache file %s after writing cache: %s", path,strerror(errno)); + } + softunlock_cache_r(); + DEBUG_MSG("Finished writing cache to disk.\n"); + return; + + fclose_unlock: + fclose(f); + softunlock_return: + softunlock_cache_r(); + return; + + lock_failed: + crash_msg("Lock failed; could not write disk cache."); +} + +/* + * Conflict Resolution. + * The first function is the actual checker; the latter two are wrappers for the respective + * function for convenience only. + * + * We check for conflicts by checking the new data rrset by rrset against the cent. + * This is not bad when considering that new records are hopefully consistent; if they are not, + * we might end up deleteing too much of the old data, which is probably added back through the + * new query, though. + * Having checked additions rrset by rrset, we are at least sure that the resulting record is OK. + * cr_check_add returns 1 if the addition is OK, 0 otherwise. + * This is for records that are already in the cache! + * + * idx is the internally used RR-set index, not the RR type! + */ +static int cr_check_add(dns_cent_t *cent, int idx, time_t ttl, time_t ts, unsigned flags) +{ + time_t nttl; + const struct rr_infos *rri; + + if (flags & CF_NEGATIVE) + return 1; /* no constraints here. */ + + nttl = 0; + rri = &rr_info[idx]; + + if (!(flags & CF_LOCAL)) { + int i, ilim, ncf; + + if(cent->flags & DF_LOCAL) + return 0; /* Local has precedence. */ + + ncf = 0; ilim = RRARR_LEN(cent); + for (i = 0; i < ilim; ++i) { + rr_set_t *rrs= RRARR_INDEX(cent,i); + /* Should be symmetric; check both ways anyway. */ + if (rrs && !(rrs->flags & CF_NEGATIVE) && + ((rri->class & rr_info[i].excludes) || + (rri->excludes & rr_info[i].class))) + { + time_t rttl; + if (rrs->flags & CF_LOCAL) + return 0; /* old was authoritative. */ + ++ncf; + rttl = rrs->ttl + rrs->ts - time(NULL); + if(rttl > 0) nttl += rttl; + } + } + if (ncf == 0) /* no conflicts */ + return 1; + /* Medium ttl of conflicting records */ + nttl /= ncf; + } + if ((flags & CF_LOCAL) || ttl > nttl) { + int i, ilim= RRARR_LEN(cent); + + /* Remove the old records, so that the new one can be added. */ + for (i = 0; i < ilim; ++i) { + rr_set_t *rrs= RRARR_INDEX(cent,i); + /* Should be symmetric; check both ways anyway. */ + if (rrs && !(rrs->flags & CF_NEGATIVE) && + ((rri->class & rr_info[i].excludes) || + (rri->excludes & rr_info[i].class))) { + del_cent_rrset_by_index(cent, i DBG0); + } + } + return 1; + } + /* old records precede */ + return 0; +} + + +inline static void adjust_ttl(rr_set_t *rrset) +{ + if (rrset->flags&CF_NOCACHE) { + rrset->flags &= ~CF_NOCACHE; + rrset->ttl=0; + } + else { + time_t min_ttl= global.min_ttl, neg_ttl=global.neg_ttl; + if((rrset->flags&CF_NEGATIVE) && neg_ttlttlttl=min_ttl; + else { + time_t max_ttl= global.max_ttl; + if(rrset->ttl>max_ttl) + rrset->ttl=max_ttl; + } + } +} + + +/* Only use for negatively cached domains, thus only + if the DF_NEGATIVE bit is set! */ +inline static void adjust_dom_ttl(dns_cent_t *cent) +{ + if (cent->flags&DF_NOCACHE) { + cent->flags &= ~DF_NOCACHE; + cent->neg.ttl=0; + } + else { + time_t min_ttl= global.min_ttl, neg_ttl=global.neg_ttl; + if(/* (cent->flags&DF_NEGATIVE) && */ neg_ttlneg.ttlneg.ttl=min_ttl; + else { + time_t max_ttl= global.max_ttl; + if(cent->neg.ttl>max_ttl) + cent->neg.ttl=max_ttl; + } + } +} + +/* + * Add a ready built dns_cent_t to the hashes, purge if necessary to not exceed cache size + * limits, and add the entries to the hashes. + * As memory is already reserved for the rrs, we only need to wrap up the dns_cent_t and + * alloc memory for it. + * New entries are appended, so we easiliy know the oldest for purging. For fast acces, + * we use hashes instead of ordered storage. + * + * This does not free the argument, and it uses a copy of it, so the caller must do free_cent() + * on it. + * + * The new entries rr sets replace the old ones, i.e. old rr sets with the same key are deleted + * before the new ones are added. + */ +void add_cache(dns_cent_t *cent) +{ + dns_cent_t *ce; + dns_hash_loc_t loc; + int i,ilim; + + lock_cache_rw(); + retry: + if (!(ce=dns_lookup(cent->qname,&loc))) { + /* if the new entry doesn't contain any information, + don't try to add it to the cache because purge_cache() will not + be able to get rid of it. + */ + if(cent->num_rrs==0 && !(cent->flags&DF_NEGATIVE)) + goto purge_cache_return; + + if(!(ce=copy_cent(cent DBG0))) + goto warn_unlock_cache_return; + + if(!(ce->flags&DF_NEGATIVE)) { + ilim= RRARR_LEN(ce); + /* Add the rrs to the rr list */ + for (i=0; iflags&DF_NEGATIVE) { + /* the new entry is negative. So, we need to delete the whole cent, + * and then generate a new one. */ + ilim= RRARR_LEN(ce); + for (i=0; iflags&CF_LOCAL) { + goto unlock_cache_return; /* Do not clobber local records */ + } + } + del_cache_ent(ce,&loc); + goto retry; + } + purge_cent(ce, 0,0); + /* We have a record; add the rrsets replacing old ones */ + cache_size-=ce->cs; + + ilim= RRARR_LEN(cent); + for (i=0; iflags&CF_LOCAL) && (cerrs->flags&CF_LOCAL)) || + ((centrrs->flags&CF_ADDITIONAL) && (!(cerrs->flags&CF_ADDITIONAL) || + (!(centrrs->flags&CF_ROOTSERV) && + (cerrs->flags&CF_ROOTSERV))) && + !timedout(cerrs))))) + { + rr_bucket_t *rr,*rtail; + + del_cent_rrset_by_index(ce,i DBG0); + + if (!cr_check_add(ce, i, centrrs->ttl, centrrs->ts, centrrs->flags)) + continue; /* the new record has been deleted as a conflict resolution measure. */ + + /* pre-initialize a rrset_t for the case we have a negative cached + * rrset, in which case no further rrs will be added. */ + if (!add_cent_rrset_by_index(ce, i, centrrs->ttl, centrrs->ts, centrrs->flags DBG0)) { + goto addsize_unlock_cache_return; + } + rtail=NULL; + for (rr=centrrs->rrs; rr; rr=rr->next) { + if (!add_cent_rr_int(ce,i,centrrs->ttl, centrrs->ts, centrrs->flags, + rr->rdlen, rr->data, &rtail DBG0)) + { + /* cleanup this entry */ + goto cleanup_cent_unlock_cache_return; + } + } + cerrs= RRARR_INDEX(ce,i); + adjust_ttl(cerrs); + if (!insert_rrl(cerrs,ce,i)) { + goto cleanup_cent_unlock_cache_return; + } + } + } + } + ce->flags |= (cent->flags&(DF_AUTH|DF_WILD)); + if(cent->c_ns!=cundef && (ce->c_ns==cundef || ce->c_nsc_ns)) + ce->c_ns=cent->c_ns; + if(cent->c_soa!=cundef && (ce->c_soa==cundef || ce->c_soac_soa)) + ce->c_soa=cent->c_soa; + } + + cache_size += ce->cs; + purge_cache_return: + purge_cache((long)global.perm_cache*1024+MCSZ, 1); + goto unlock_cache_return; + + cleanup_cent_unlock_cache_return: + del_cent_rrset_by_index(ce, i DBG0); + addsize_unlock_cache_return: + cache_size += ce->cs; + goto warn_unlock_cache_return; + + free_cent_unlock_cache_return: + free_cent(ce DBG0); + pdnsd_free(ce); + warn_unlock_cache_return: + log_warn("Out of cache memory."); + unlock_cache_return: + unlock_cache_rw(); +} + +/* + Convert A (and AAAA) records in a ready built cache entry to PTR records suitable for reverse resolving + of numeric addresses and add them to the cache. +*/ +int add_reverse_cache(dns_cent_t * cent) +{ + int tp=T_A; + rr_set_t *rrset= getrrset_A(cent); + + for(;;) { + if(rrset) { + rr_bucket_t *rr; + for(rr=rrset->rrs; rr; rr=rr->next) { + dns_cent_t ce; + unsigned char buf[DNSNAMEBUFSIZE],rhn[DNSNAMEBUFSIZE]; + if(!a2ptrstr((pdnsd_ca *)(rr->data),tp,buf) || !str2rhn(buf,rhn)) + return 0; + if(!init_cent(&ce, rhn, 0, 0, cent->flags DBG0)) + return 0; + if(!add_cent_rr(&ce,T_PTR,rrset->ttl,rrset->ts,rrset->flags,rhnlen(cent->qname),cent->qname DBG0)) { + free_cent(&ce DBG0); + return 0; + } +#ifdef RRMUINDEX_NS + ce.rr.rrmu[RRMUINDEX_NS]=cent->rr.rrmu[RRMUINDEX_NS]; +#endif +#ifdef RRMUINDEX_SOA + ce.rr.rrmu[RRMUINDEX_SOA]=cent->rr.rrmu[RRMUINDEX_SOA]; +#endif + add_cache(&ce); +#ifdef RRMUINDEX_NS + ce.rr.rrmu[RRMUINDEX_NS]=NULL; +#endif +#ifdef RRMUINDEX_SOA + ce.rr.rrmu[RRMUINDEX_SOA]=NULL; +#endif + free_cent(&ce DBG0); + } + } +#if ALLOW_LOCAL_AAAA + if(tp==T_AAAA) + break; + tp=T_AAAA; + rrset= getrrset_AAAA(cent); +#else + break; +#endif + } + return 1; +} + + +/* + Delete a cent from the cache. Call with write locks applied. + Does not delete corresponding entry in hash table, call del_cache_ent() + or del_cache() for that. +*/ +void del_cent(dns_cent_t *cent) +{ + cache_size -= cent->cs; + + /* free the data referred by the cent and the cent itself */ + free_cent(cent DBG0); + free(cent); + + --ent_num; +} + +/* + * Delete a cent from the cache. Call with write locks applied. + */ +static void del_cache_ent(dns_cent_t *cent,dns_hash_loc_t *loc) +{ + dns_cent_t *data; + + /* Delete from the hash */ + if(loc) + data=del_dns_hash_ent(loc); + else + data=del_dns_hash(cent->qname); + if(!data) { + log_warn("Cache entry not found by del_dns_hash() in %s, line %d",__FILE__,__LINE__); + } + else if(data!=cent) { + log_warn("pointer returned by del_dns_hash() does not match cache entry in %s, line %d",__FILE__,__LINE__); + } + del_cent(cent); +} + +/* Delete a cached record. Performs locking. Call this from the outside, NOT del_cache_ent */ +void del_cache(const unsigned char *name) +{ + dns_cent_t *cent; + + lock_cache_rw(); + if ((cent=del_dns_hash(name))) { + del_cent(cent); + } + unlock_cache_rw(); +} + + +/* Invalidate a record by resetting the fetch time to 0. This means that it will be refreshed + * if possible (and will only be served when purge_cache=off;) */ +void invalidate_record(const unsigned char *name) +{ + dns_cent_t *ce; + int i, ilim; + + lock_cache_rw(); + if ((ce=dns_lookup(name,NULL))) { + if(!(ce->flags&DF_NEGATIVE)) { + ilim= RRARR_LEN(ce); + for (i=0; its=0; + rrs->flags &= ~CF_AUTH; + } + } + } + else { + /* set the cent time to 0 (for the case that this was negative) */ + ce->neg.ts=0; + } + ce->flags &= ~DF_AUTH; + } + unlock_cache_rw(); +} + + +/* + Set flags of the cache entry with the specified name. + Don't use this to set the DF_NEGATIVE flag, or you will + risk leaving the cache in an inconsistent state. + Returns 0 if the cache entry cannot be found, otherwise 1. + */ +int set_cent_flags(const unsigned char *name, unsigned flags) +{ + dns_cent_t *ret; + lock_cache_rw(); + ret=dns_lookup(name,NULL); + if (ret) { + ret->flags |= flags; + } + unlock_cache_rw(); + return ret!=NULL; +} + +unsigned char *getlocalowner(unsigned char *name,int tp) +{ + unsigned char *ret=NULL; + dns_cent_t *ce; + unsigned lb; + + lock_cache_r(); + if((lb = *name)) { + while(name += lb+1, lb = *name) { + if((ce=dns_lookup(name,NULL))) { + if(!(ce->flags&DF_LOCAL)) + break; + if(have_rr(ce,tp)) { + ret=name; + break; + } + } + } + } + unlock_cache_r(); + + return ret; +} + + +/* Lookup an entry in the cache using name (in length byte - string notation). + * For thread safety, a copy must be returned, so delete it after use, by first doing + * free_cent to remove the rrs and then by freeing the returned pointer. + * If wild is nonzero, and name can't be found in the cache, lookup_cache() + * will search up the name hierarchy for a record with the DF_NEGATIVE or DF_WILD flag set. + */ +dns_cent_t *lookup_cache(const unsigned char *name, int *wild) +{ + int purge=0; + dns_cent_t *ret; + + /* First try with only read access to the cache. */ + lock_cache_r(); + ret=dns_lookup(name,NULL); + if(wild) { + *wild=0; + if(!ret) { + const unsigned char *nm=name; + unsigned lb=*nm; + if(lb) { + while(nm += lb+1, lb = *nm) { + if ((ret=dns_lookup(nm,NULL))) { + if(ret->flags&DF_NEGATIVE) + /* use this entry */ + *wild=w_neg; + else if(ret->flags&DF_WILD) { + unsigned char buf[DNSNAMEBUFSIZE]; + buf[0]=1; buf[1]='*'; + /* When we get here, at least one element of name + has been removed, so assuming name is not longer + than DNSNAMEBUFSIZE bytes, the remainder is guaranteed to + fit into DNSNAMEBUFSIZE-2 bytes */ + rhncpy(&buf[2],nm); + ret=dns_lookup(buf,NULL); + if(ret) + *wild=w_wild; + } + else if(ret->flags&DF_LOCAL) + *wild=w_locnerr; + else + ret=NULL; + break; + } + } + } + } + } + if (ret) { + if(!(purge=purge_cent(ret, 1,1))) /* test only, don't remove anything yet! */ + ret=copy_cent(ret DBG1); + } + unlock_cache_r(); + + if(purge) { + /* we need exclusive read and write access before we delete anything. */ + lock_cache_rw(); + ret=dns_lookup(name,NULL); + if(wild) { + *wild=0; + if(!ret) { + const unsigned char *nm=name; + unsigned lb=*nm; + if(lb) { + while(nm += lb+1, lb = *nm) { + if ((ret=dns_lookup(nm,NULL))) { + if(ret->flags&DF_NEGATIVE) + /* use this entry */ + *wild=w_neg; + else if(ret->flags&DF_WILD) { + unsigned char buf[DNSNAMEBUFSIZE]; + buf[0]=1; buf[1]='*'; + rhncpy(&buf[2],nm); + ret=dns_lookup(buf,NULL); + if(ret) + *wild=w_wild; + } + else if(ret->flags&DF_LOCAL) + *wild=w_locnerr; + else + ret=NULL; + break; + } + } + } + } + } + if (ret) { + if(purge_cent(ret, 1,0)<0) + ret=NULL; + else + ret=copy_cent(ret DBG1); + } + unlock_cache_rw(); + } + + return ret; +} + +/* lookup_cache_local_rrset() check if there is locally defined RR set of a specific RR type + for name, and if so, returns a copy of the RR set. After use, the copy should be cleaned + up using del_rrset(). + This is potentially much more efficient than using lookup_cache(), if the name is likely + to have a cache entry, but unlikely to have locally defined RR sets. +*/ +rr_set_t *lookup_cache_local_rrset(const unsigned char *name, int type) +{ + rr_set_t *ret=NULL; + dns_cent_t *cent; + + lock_cache_r(); + cent= dns_lookup(name,NULL); + if(cent) { + rr_set_t *rrset=getrrset(cent,type); + if(rrset && (rrset->flags&CF_LOCAL)) { + ret= copy_rrset(rrset); + } + } + unlock_cache_r(); + + return ret; +} + + +#if 0 +/* Add an rr to an existing cache entry or create a new entry if necessary. + * The rr is treated with the precedence of an additional or off-topic record, ie. regularly retrieved + * have precedence. + * You cannot add a negative additional record. Makes no sense anyway. */ +int add_cache_rr_add(const unsigned char *name, int tp, time_t ttl, time_t ts, unsigned flags, unsigned dlen, void *data, unsigned long serial) +{ + dns_hash_loc_t loc; + dns_cent_t *ret; + rr_set_t *rrs; + int rv=0; + + lock_cache_rw(); + if (!(ret=dns_lookup(name,&loc))) { + if (!(ret=cache_malloc(sizeof(dns_cent_t)))) + goto unlock_return; + if(!init_cent(ret, name, 0, 0, 0 DBG0)) { + pdnsd_free(ret); + goto unlock_return; + } + if(!add_dns_hash(ret,&loc)) { + free_cent(ret DBG0); + pdnsd_free(ret); + goto unlock_return; + } + ++ent_num; + } + else { + /* purge the record. */ + purge_cent(ret,0,0); + cache_size-=ret->cs; + } + rrs=getrrset(ret,tp); + if (rrs && + ((rrs->flags&CF_NEGATIVE && !(rrs->flags&CF_LOCAL)) || + (rrs->flags&CF_NOPURGE && timedout(rrs)) || + (rrs->flags&CF_ADDITIONAL && rrs->serial!=serial) || + (rrs->serial==serial && rrs->ttl!=(ttlglobal.max_ttl?global.max_ttl:ttl))))) { + del_cent_rrset_by_type(ret,tp DBG0); + rrs=NULL; + } + if (rrs==NULL || rrs->serial==serial) { + if (cr_check_add(ret,rrlkuptab[tp-T_MIN],ttl,ts,flags)) { + if (add_cent_rr(ret,tp,ttl,ts,flags,dlen,data,serial DBG0)) { + rr_set_t *rrsnew; + if (!rrs && (rrsnew=getrrset(ret,tp)) && !insert_rrl(rrsnew,ret,rrlkuptab[tp-T_MIN])) { + del_cent_rrset_by_type(ret,tp DBG0); + } + else { + cache_size+=ret->cs; + purge_cent(ret,1,0); + rv=1; + goto unlock_return; + } + } + } + } else { + rv=1; + } + cache_size+=ret->cs; + + unlock_return: + unlock_cache_rw(); + return rv; +} +#endif + +/* Report the cache status to the file descriptor f, for the status fifo (see status.c) */ +int report_cache_stat(int f) +{ + /* Cache size and entry counters are volatile (and even the entries + in the global struct can change), so make copies to get consistent data. + Even better would be to use locks, but that could be rather costly. */ + long csz= cache_size, en= ent_num; + long pc= global.perm_cache; + long mc= pc*1024+MCSZ; + + fsprintf_or_return(f,"\nCache status:\n=============\n"); + fsprintf_or_return(f,"%ld kB maximum disk cache size.\n",pc); + fsprintf_or_return(f,"%ld of %ld bytes (%.3g%%) memory cache used in %ld entries" + " (avg %.5g bytes/entry).\n", + csz, mc, (((double)csz)/mc)*100, en, + ((double)csz)/en); + return 0; +} + + +#define timestamp2str(ts,now,buf) \ +{ \ + struct tm tstm; \ + if(!((ts) && localtime_r(&(ts), &tstm) && \ + strftime(buf, sizeof(buf), \ + ((ts)<=(now) && (now)-(ts)<365*24*60*60/2)?" %m/%d %T":"%Y/%m/%d %T", \ + &tstm)>0)) \ + strcpy(buf," "); \ +} + +/* Dump contents of a cache entry to file descriptor fd. + Returns 1 on success, -1 if there is an IO error. +*/ +static int dump_cent(int fd, dns_cent_t *cent) +{ + time_t now; + char tstr[sizeof "2000/12/31 23:59:59"],dbuf[1024]; + + fsprintf_or_return(fd,"%s\n",rhn2str(cent->qname,ucharp dbuf,sizeof(dbuf))); + now=time(NULL); + + if(cent->flags&DF_NEGATIVE) { + timestamp2str(cent->neg.ts,now,tstr); + fsprintf_or_return(fd,"%s (domain negated)\n",tstr); + } + else { + int i, n= NRRITERLIST(cent); + const unsigned short *iterlist= RRITERLIST(cent); + for(i=0; its,now,tstr); + if(rrset->flags&CF_NEGATIVE) { + fsprintf_or_return(fd,"%s %-7s (negated)\n",tstr,rrnames[tp-T_MIN]); + } + else { + rr_bucket_t *rr; + for(rr=rrset->rrs; rr; rr=rr->next) { + switch (tp) { + case T_CNAME: + case T_MB: + case T_MD: + case T_MF: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + rhn2str((unsigned char *)(rr->data),ucharp dbuf,sizeof(dbuf)); + break; +#if IS_CACHED_MINFO || IS_CACHED_RP +#if IS_CACHED_MINFO + case T_MINFO: +#endif +#if IS_CACHED_RP + case T_RP: +#endif + { + unsigned char *p=(unsigned char *)(rr->data); + int n; + rhn2str(p,ucharp dbuf,sizeof(dbuf)); + n=strlen(dbuf); + dbuf[n++] = ' '; + if(n>=sizeof(dbuf)) + goto hex_dump; + rhn2str(skiprhn(p),ucharp dbuf+n,sizeof(dbuf)-n); + } + break; +#endif + case T_MX: +#if IS_CACHED_AFSDB + case T_AFSDB: +#endif +#if IS_CACHED_RT + case T_RT: +#endif +#if IS_CACHED_KX + case T_KX: +#endif + { + unsigned char *p=(unsigned char *)(rr->data); + unsigned pref; + int n; + GETINT16(pref,p); + n=sprintf(dbuf,"%u ",pref); + if(n<0) goto hex_dump; + rhn2str(p,ucharp dbuf+n,sizeof(dbuf)-n); + } + break; + case T_SOA: + { + unsigned char *p=(unsigned char *)(rr->data); + char *q; + int n,rem; + uint32_t serial,refresh,retry,expire,minimum; + rhn2str(p,ucharp dbuf,sizeof(dbuf)); + n=strlen(dbuf); + dbuf[n++] = ' '; + if(n>=sizeof(dbuf)) + goto hex_dump; + q=dbuf+n; + rem=sizeof(dbuf)-n; + p=skiprhn(p); + rhn2str(p,ucharp q,rem); + n=strlen(q); + q[n++] = ' '; + if(n>=rem) + goto hex_dump; + q += n; + rem -= n; + p=skiprhn(p); + GETINT32(serial,p); + GETINT32(refresh,p); + GETINT32(retry,p); + GETINT32(expire,p); + GETINT32(minimum,p); + n=snprintf(q,rem,"%lu %lu %lu %lu %lu", + (unsigned long)serial,(unsigned long)refresh, + (unsigned long)retry,(unsigned long)expire, + (unsigned long)minimum); + if(n<0 || n>=rem) + goto hex_dump; + } + break; +#if IS_CACHED_HINFO || IS_CACHED_TXT || IS_CACHED_SPF +#if IS_CACHED_HINFO + case T_HINFO: +#endif +#if IS_CACHED_TXT + case T_TXT: +#endif +#if IS_CACHED_SPF + case T_SPF: +#endif + { + /* TXT records are not necessarily validated + before they are stored in the cache, so + we need to be careful. */ + unsigned char *p=(unsigned char *)(rr->data); + char *q=dbuf; + int j=0,n,rem=sizeof(dbuf); + while(jrdlen) { + unsigned lb; + if(rem<3) + goto hex_dump; + if(j) { + *q++ = ' '; + --rem; + } + *q++ = '"'; + --rem; + lb=*p++; + if((j += lb+1)>rr->rdlen) + goto hex_dump; + n=escapestr(charp p,lb,q,rem); + if(n<0 || n+1>=rem) + goto hex_dump; + q += n; + *q++ = '"'; + rem -= n+1; + p += lb; + } + *q=0; + } + break; +#endif +#if IS_CACHED_PX + case T_PX: + { + unsigned char *p=(unsigned char *)(rr->data); + char *q; + unsigned pref; + int n,rem; + GETINT16(pref,p); + n=sprintf(dbuf,"%u ",pref); + if(n<0) goto hex_dump; + q=dbuf+n; + rem=sizeof(dbuf)-n; + rhn2str(p,ucharp q,rem); + n=strlen(q); + q[n++] = ' '; + if(n>=rem) + goto hex_dump; + rhn2str(skiprhn(p),ucharp q+n,rem-n); + } + break; +#endif +#if IS_CACHED_SRV + case T_SRV: + { + unsigned char *p=(unsigned char *)(rr->data); + unsigned priority,weight,port; + int n; + GETINT16(priority,p); + GETINT16(weight,p); + GETINT16(port,p); + n=sprintf(dbuf,"%u %u %u ",priority,weight,port); + if(n<0) goto hex_dump; + rhn2str(p,ucharp dbuf+n,sizeof(dbuf)-n); + } + break; +#endif +#if IS_CACHED_NXT + case T_NXT: + { + unsigned char *p=(unsigned char *)(rr->data); + int n,rlen; + rhn2str(p,ucharp dbuf,sizeof(dbuf)); + n=strlen(dbuf); + dbuf[n++] = ' '; + if(n>=sizeof(dbuf)) + goto hex_dump; + rlen=rhnlen(p); + hexdump(p+rlen,rr->rdlen-rlen,dbuf+n,sizeof(dbuf)-n); + } + break; +#endif +#if IS_CACHED_NAPTR + case T_NAPTR: + { + unsigned char *p=(unsigned char *)(rr->data); + char *q; + unsigned order,pref; + int n,rem,j; + GETINT16(order,p); + GETINT16(pref,p); + n=sprintf(dbuf,"%u %u ",order,pref); + if(n<0) goto hex_dump; + q=dbuf+n; + rem=sizeof(dbuf)-n; + for (j=0;j<3;++j) { + unsigned lb; + if(rem<2) + goto hex_dump; + *q++ = '"'; + --rem; + lb=*p++; + n=escapestr(charp p,lb,q,rem); + if(n<0 || n+2>=rem) + goto hex_dump; + q += n; + *q++ = '"'; + *q++ = ' '; + rem -= n+2; + p += lb; + } + rhn2str(p,ucharp q,rem); + } + break; +#endif +#if IS_CACHED_LOC + case T_LOC: + /* Binary data length has not necessarily been validated */ + if(rr->rdlen!=16) + goto hex_dump; + if(!loc2str(rr->data,dbuf,sizeof(dbuf))) + goto hex_dump; + break; +#endif + case T_A: + if (!inet_ntop(AF_INET,rr->data,dbuf,sizeof(dbuf))) + goto hex_dump; + break; +#if IS_CACHED_AAAA && defined(AF_INET6) + case T_AAAA: + if (!inet_ntop(AF_INET6,rr->data,dbuf,sizeof(dbuf))) + goto hex_dump; + break; +#endif + default: + hex_dump: + hexdump(rr->data,rr->rdlen,dbuf,sizeof(dbuf)); + } + fsprintf_or_return(fd,"%s %-7s %s\n",tstr,rrnames[tp-T_MIN],dbuf); + } + } + } + } + } + fsprintf_or_return(fd,"\n"); + return 1; +} + +/* Dump cache contents to file descriptor fd. + If name is not null, restricts information to that name, + otherwise dumps information about all names found in the cache. + Returns 1 on success, 0 if the name is not found, -1 is there is an IO error. + Mainly for debugging purposes. +*/ +int dump_cache(int fd, const unsigned char *name, int exact) +{ + int rv=0; + lock_cache_r(); + if(name && exact) { + dns_cent_t *cent=dns_lookup(name,NULL); + if(cent) + rv=dump_cent(fd,cent); + } + else { + dns_cent_t *cent; + dns_hash_pos_t pos; + for (cent=fetch_first(&pos); cent; cent=fetch_next(&pos)) { + unsigned int nrem; + if(!name || (domain_match(name,cent->qname,&nrem,NULL),nrem==0)) + if((rv=dump_cent(fd,cent))<0) + break; + } + } + unlock_cache_r(); + return rv; +} + + +#if DEBUG>0 + +/* Added by Paul Rombouts: This is only used in debug messages. */ +const char cflgnames[NCFLAGS*3]={'N','E','G','L','O','C','A','U','T','N','O','C','A','D','D','N','O','P','R','T','S'}; +const char dflgnames[NDFLAGS*3]={'N','E','G','L','O','C','A','U','T','N','O','C','W','L','D'}; + +char *flags2str(unsigned flags,char *buf,int nflags,const char *flgnames) +{ + char *p=buf; + int i,nflgchars=3*nflags; + for(i=0;ibuf) *p++='|'; + p=mempcpy(p,&flgnames[i],3); + } + flags >>= 1; + } + if(p==buf) + *p++='0'; + *p=0; + return buf; +} +#endif diff --git a/jni/pdnsd/src/cache.h b/jni/pdnsd/src/cache.h new file mode 100644 index 00000000..5056dec7 --- /dev/null +++ b/jni/pdnsd/src/cache.h @@ -0,0 +1,306 @@ +/* cache.h - Definitions for the dns cache + + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2003, 2004, 2005, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _CACHE_H_ +#define _CACHE_H_ + +#include +#include "ipvers.h" +#include +#include "list.h" +#include "dns.h" +#include "conff.h" + +struct rr_lent_s; + +/* + * These values are converted to host byte order. the data is _not_. + */ +typedef struct rr_b_s { + struct rr_b_s *next; /* this is the next pointer in the dns_cent_t list. */ + unsigned rdlen; +#if ALLOW_LOCAL_AAAA || defined(ENABLE_IPV6) + struct in6_addr data[0]; /* dummy for alignment */ +#else + struct in_addr data[0]; +#endif +} rr_bucket_t; + +typedef struct { + struct rr_lent_s *lent; /* this points to the list entry */ + time_t ttl; + time_t ts; + unsigned short flags; + rr_bucket_t *rrs; +} rr_set_t; + + +typedef struct { + unsigned char *qname; /* Name of the domain in length byte - string notation. */ + size_t cs; /* Size of the cache entry, including RR sets. */ + unsigned short num_rrs; /* The number of RR sets. When this decreases to 0, the cent is deleted. */ + unsigned short flags; /* Flags for the whole domain. */ + union { + struct { /* Fields used only for negatively cached domains. */ + struct rr_lent_s *lent; /* list entry for the whole cent. */ + time_t ttl; /* TTL for negative caching. */ + time_t ts; /* Timestamp. */ + } neg; + struct { /* Fields used only for domains that actually exist. */ + rr_set_t *(rrmu[NRRMU]); /* The most used records. + Use the the value obtained from rrlkuptab[] as index. */ + rr_set_t **rrext; /* Pointer (may be NULL) to an array of size NNRREXT storing the + less frequently used records. */ + } rr; + }; + unsigned char c_ns,c_soa; /* Number of trailing name elements in qname to use to find NS or SOA + records to add to the authority section of a response. */ +} dns_cent_t; + +/* This value is used to represent an undefined c_ns or c_soa field. */ +#define cundef 0xff + +/* + * the flag values for RR sets in the cache + */ +#define CF_NEGATIVE 1 /* this one is for per-RRset negative caching*/ +#define CF_LOCAL 2 /* Local zone entry */ +#define CF_AUTH 4 /* authoritative record */ +#define CF_NOCACHE 8 /* Only hold for the cache latency time period, then purge. + * Not really written to cache, but used by add_cache. */ +#define CF_ADDITIONAL 16 /* This was fetched as an additional or "off-topic" record. */ +#define CF_NOPURGE 32 /* Do not purge this record */ +#define CF_ROOTSERV 64 /* This record was directly obtained from a root server */ + +#define CFF_NOINHERIT (CF_LOCAL|CF_AUTH|CF_ADDITIONAL|CF_ROOTSERV) /* not to be inherited on requery */ + +/* + * the flag values for whole domains in the cache + */ +#define DF_NEGATIVE 1 /* this one is for whole-domain negative caching (created on NXDOMAIN)*/ +#define DF_LOCAL 2 /* local record (in conj. with DF_NEGATIVE) */ +#define DF_AUTH 4 /* authoritative record */ +#define DF_NOCACHE 8 /* Only hold for the cache latency time period, then purge. + * Only used for negatively cached domains. + * Not really written to cache, but used by add_cache. */ +#define DF_WILD 16 /* subdomains of this domain have wildcard records */ + +/* #define DFF_NOINHERIT (DF_NEGATIVE) */ /* not to be inherited on requery */ + +enum {w_wild=1, w_neg, w_locnerr}; /* Used to distinguish different types of wildcard records. */ + +#if DEBUG>0 +#define NCFLAGS 7 +#define NDFLAGS 5 +#define CFLAGSTRLEN (NCFLAGS*4) +#define DFLAGSTRLEN (NDFLAGS*4) +extern const char cflgnames[]; +extern const char dflgnames[]; +char *flags2str(unsigned flags,char *buf,int nflags,const char *flgnames); +#define cflags2str(flags,buf) flags2str(flags,buf,NCFLAGS,cflgnames) +#define dflags2str(flags,buf) flags2str(flags,buf,NDFLAGS,dflgnames) +#endif + +/* + * This is the time in secs any record remains at least in the cache before it is purged. + * (exception is that the cache is full) + */ +#define CACHE_LAT 120 +#define CLAT_ADJ(ttl) ((ttl)ts+CLAT_ADJ((rrset)->ttl)neg.ts+CLAT_ADJ((cent)->neg.ttl)purge_cache) + fl|=CF_NOPURGE; + if (server->nocache) + fl|=CF_NOCACHE; + if (server->rootserver) + fl|=CF_ROOTSERV; + return fl; +} + +int init_cent(dns_cent_t *cent, const unsigned char *qname, time_t ttl, time_t ts, unsigned flags DBGPARAM); +int add_cent_rrset_by_type(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags DBGPARAM); +int add_cent_rr(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags,unsigned dlen, void *data DBGPARAM); +int del_rrset(rr_set_t *rrs DBGPARAM); +void free_cent(dns_cent_t *cent DBGPARAM); +void free_cent0(void *ptr); +void negate_cent(dns_cent_t *cent, time_t ttl, time_t ts); +void del_cent(dns_cent_t *cent); + +/* Because this is empty by now, it is defined as an empty macro to save overhead.*/ +/*void free_rr(rr_bucket_t cent);*/ +#define free_rr(x) + +dns_cent_t *copy_cent(dns_cent_t *cent DBGPARAM); + +#if 0 +unsigned long get_serial(void); +#endif + +/* Get pointer to rrset given cache entry and rr type value. */ +inline static rr_set_t *getrrset(dns_cent_t *cent, int type) + __attribute__((always_inline)); +inline static rr_set_t *getrrset(dns_cent_t *cent, int type) +{ + if(!(cent->flags&DF_NEGATIVE)) { + int tpi= type - T_MIN; + + if(tpi>=0 && tpirr.rrmu[idx]; + else { + idx -= NRRMU; + if(idx < NRREXT) { + rr_set_t **rrext= cent->rr.rrext; + if(rrext) + return rrext[idx]; + } + } + } + } + + return NULL; +} + +/* This version of getrrset is slightly more efficient, + but also more dangerous, because it performs less checks. + It is safe to use if T_MIN <= type <= T_MAX and cent + is not negative. +*/ +inline static rr_set_t *getrrset_eff(dns_cent_t *cent, int type) + __attribute__((always_inline)); +inline static rr_set_t *getrrset_eff(dns_cent_t *cent, int type) +{ + unsigned int idx = rrlkuptab[type-T_MIN]; + if(idx < NRRMU) + return cent->rr.rrmu[idx]; + else { + idx -= NRRMU; + if(idx < NRREXT) { + rr_set_t **rrext= cent->rr.rrext; + if(rrext) + return rrext[idx]; + } + } + + return NULL; +} + + +/* have_rr() tests whether a cache entry has at least one record of a given type. + Only use if T_MIN <= type <=T_MAX +*/ +inline static int have_rr(dns_cent_t *cent, int type) + __attribute__((always_inline)); +inline static int have_rr(dns_cent_t *cent, int type) +{ + rr_set_t *rrset; + return !(cent->flags&DF_NEGATIVE) && (rrset=getrrset_eff(cent, type)) && rrset->rrs; +} + +/* Some quick and dirty and hopefully fast macros. */ +#define PDNSD_NOT_CACHED_TYPE(type) ((type)T_MAX || rrlkuptab[(type)-T_MIN]>=NRRTOT) + +/* This is useful for iterating over all the RR types in a cache entry in strict ascending order. */ +#define NRRITERLIST(cent) ((cent)->flags&DF_NEGATIVE?0:(cent)->rr.rrext?NRRTOT:NRRMU) +#define RRITERLIST(cent) ((cent)->flags&DF_NEGATIVE?NULL:(cent)->rr.rrext?rrcachiterlist:rrmuiterlist) + +/* The following macros use array indices as arguments, not RR type values! */ +#define GET_RRSMU(cent,i) (!((cent)->flags&DF_NEGATIVE)?(cent)->rr.rrmu[i]:NULL) +#define GET_RRSEXT(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrext?(cent)->rr.rrext[i]:NULL) +#define HAVE_RRMU(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrmu[i] && (cent)->rr.rrmu[i]->rrs) +#define HAVE_RREXT(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrext && (cent)->rr.rrext[i] && (cent)->rr.rrext[i]->rrs) + +#define RRARR_LEN(cent) ((cent)->flags&DF_NEGATIVE?0:(cent)->rr.rrext?NRRTOT:NRRMU) + +/* This allows us to index the RR-set arrays in a cache entry as if they formed one contiguous array. */ +#define RRARR_INDEX_TESTEXT(cent,i) ((cent)->flags&DF_NEGATIVE?NULL:(i)rr.rrmu[i]:(cent)->rr.rrext?(cent)->rr.rrext[(i)-NRRMU]:NULL) +/* This gets the address where the pointer to an RR-set is stored in a cache entry, + given the cache entry and an RR-set index. + Address may be NULL if no storage space for the type has been allocated. */ +#define RRARR_INDEX_PA_TESTEXT(cent,i) ((cent)->flags&DF_NEGATIVE?NULL:(i)rr.rrmu[i]:(cent)->rr.rrext?&(cent)->rr.rrext[(i)-NRRMU]:NULL) + +/* The following macros should only be used if 0 <= i < RRARR_LEN(cent) ! */ +#define RRARR_INDEX(cent,i) ((i)rr.rrmu[i]:(cent)->rr.rrext[(i)-NRRMU]) +#define RRARR_INDEX_PA(cent,i) ((i)rr.rrmu[i]:&(cent)->rr.rrext[(i)-NRRMU]) + +#endif diff --git a/jni/pdnsd/src/conf-keywords.h b/jni/pdnsd/src/conf-keywords.h new file mode 100644 index 00000000..2bcdacfe --- /dev/null +++ b/jni/pdnsd/src/conf-keywords.h @@ -0,0 +1,238 @@ +/* conf-keywords.h - Tables used by parser of configuration file. + Based on information previously contained in conf-lex.y and conf-parse.y + + Copyright (C) 2004,2005,2006,2007,2008,2009,2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +enum { + ERROR, + + GLOBAL, + SERVER, + RR, + NEG, + SOURCE, + INCLUDE_F, + + PERM_CACHE, + CACHE_DIR, + SERVER_PORT, + SERVER_IP, + OUTGOING_IP, + SCHEME_FILE, + LINKDOWN_KLUGE, + MAX_TTL, + MIN_TTL, + RUN_AS, + STRICT_SETUID, + USE_NSS, + PARANOID, + IGNORE_CD, + STATUS_CTL, + DAEMON, + C_TCP_SERVER, + PID_FILE, + C_VERBOSITY, + C_QUERY_METHOD, + RUN_IPV4, + IPV4_6_PREFIX, + C_DEBUG, + C_CTL_PERMS, + C_PROC_LIMIT, + C_PROCQ_LIMIT, + TCP_QTIMEOUT, + C_PAR_QUERIES, + C_RAND_RECS, + NEG_TTL, + NEG_RRS_POL, + NEG_DOMAIN_POL, + QUERY_PORT_START, + QUERY_PORT_END, + UDP_BUFSIZE, + DELEGATION_ONLY, + + IP, + PORT, + SCHEME, + UPTEST, + TIMEOUT, + PING_TIMEOUT, + PING_IP, + UPTEST_CMD, + QUERY_TEST_NAME, + INTERVAL, + INTERFACE, + DEVICE, + PURGE_CACHE, + CACHING, + LEAN_QUERY, + EDNS_QUERY, + PRESET, + PROXY_ONLY, + ROOT_SERVER, + RANDOMIZE_SERVERS, + INCLUDE, + EXCLUDE, + POLICY, + REJECTLIST, + REJECTPOLICY, + REJECTRECURSIVELY, + LABEL, + + A, + PTR, + MX, + SOA, + CNAME, + TXT, + SPF, + NAME, + OWNER, + TTL, + TYPES, + FILET, + SERVE_ALIASES, + AUTHREC, + REVERSE +}; + + +/* Table for looking up section headers. Order alphabetically! */ +static const namevalue_t section_headers[]= { + {"global", GLOBAL}, + {"include", INCLUDE_F}, + {"neg", NEG}, + {"rr", RR}, + {"server", SERVER}, + {"source", SOURCE} +}; + +/* Table for looking up global options. Order alphabetically! */ +static const namevalue_t global_options[]= { + {"cache_dir", CACHE_DIR}, + {"ctl_perms", C_CTL_PERMS}, + {"daemon", DAEMON}, + {"debug", C_DEBUG}, + {"delegation_only", DELEGATION_ONLY}, + {"ignore_cd", IGNORE_CD}, + {"interface", SERVER_IP}, + {"ipv4_6_prefix", IPV4_6_PREFIX}, + {"linkdown_kluge", LINKDOWN_KLUGE}, + {"max_ttl", MAX_TTL}, + {"min_ttl", MIN_TTL}, + {"neg_domain_pol", NEG_DOMAIN_POL}, + {"neg_rrs_pol", NEG_RRS_POL}, + {"neg_ttl", NEG_TTL}, + {"outgoing_ip", OUTGOING_IP}, + {"outside_interface", OUTGOING_IP}, + {"par_queries", C_PAR_QUERIES}, + {"paranoid", PARANOID}, + {"perm_cache", PERM_CACHE}, + {"pid_file", PID_FILE}, + {"proc_limit", C_PROC_LIMIT}, + {"procq_limit", C_PROCQ_LIMIT}, + {"query_method", C_QUERY_METHOD}, + {"query_port_end", QUERY_PORT_END}, + {"query_port_start", QUERY_PORT_START}, + {"randomize_recs", C_RAND_RECS}, + {"run_as", RUN_AS}, + {"run_ipv4", RUN_IPV4}, + {"scheme_file", SCHEME_FILE}, + {"server_ip", SERVER_IP}, + {"server_port", SERVER_PORT}, + {"status_ctl", STATUS_CTL}, + {"strict_setuid", STRICT_SETUID}, + {"tcp_qtimeout", TCP_QTIMEOUT}, + {"tcp_server", C_TCP_SERVER}, + {"timeout", TIMEOUT}, + {"udpbufsize", UDP_BUFSIZE}, + {"use_nss", USE_NSS}, + {"verbosity", C_VERBOSITY} +}; + +/* Table for looking up server options. Order alphabetically! */ +static const namevalue_t server_options[]= { + {"caching", CACHING}, + {"device", DEVICE}, + {"edns_query", EDNS_QUERY}, + {"exclude", EXCLUDE}, + {"file", FILET}, + {"include", INCLUDE}, + {"interface", INTERFACE}, + {"interval", INTERVAL}, + {"ip", IP}, + {"label", LABEL}, + {"lean_query", LEAN_QUERY}, + {"ping_ip", PING_IP}, + {"ping_timeout", PING_TIMEOUT}, + {"policy", POLICY}, + {"port", PORT}, + {"preset", PRESET}, + {"proxy_only", PROXY_ONLY}, + {"purge_cache", PURGE_CACHE}, + {"query_test_name", QUERY_TEST_NAME}, + {"randomize_servers", RANDOMIZE_SERVERS}, + {"reject", REJECTLIST}, + {"reject_policy", REJECTPOLICY}, + {"reject_recursively", REJECTRECURSIVELY}, + {"root_server", ROOT_SERVER}, + {"scheme", SCHEME}, + {"timeout", TIMEOUT}, + {"uptest", UPTEST}, + {"uptest_cmd", UPTEST_CMD} +}; + +/* Table for looking up rr options. Order alphabetically! */ +static const namevalue_t rr_options[]= { + {"a", A}, + {"authrec", AUTHREC}, + {"cname", CNAME}, + {"mx", MX}, + {"name", NAME}, + {"ns", OWNER}, + {"owner", OWNER}, + {"ptr", PTR}, + {"reverse", REVERSE}, + {"soa", SOA}, + {"spf", SPF}, + {"ttl", TTL}, + {"txt", TXT} +}; + +/* Table for looking up source options. Order alphabetically! */ +static const namevalue_t source_options[]= { + {"authrec", AUTHREC}, + {"file", FILET}, + {"ns", OWNER}, + {"owner", OWNER}, + {"serve_aliases", SERVE_ALIASES}, + {"ttl", TTL} +}; + +/* Table for looking up include options. Order alphabetically! */ +static const namevalue_t include_options[]= { + {"file", FILET} +}; + +/* Table for looking up neg options. Order alphabetically! */ +static const namevalue_t neg_options[]= { + {"name", NAME}, + {"ttl", TTL}, + {"types", TYPES} +}; diff --git a/jni/pdnsd/src/conf-parser.c b/jni/pdnsd/src/conf-parser.c new file mode 100644 index 00000000..9cf9180e --- /dev/null +++ b/jni/pdnsd/src/conf-parser.c @@ -0,0 +1,2118 @@ +/* conf-parser.c - Parser for pdnsd config files. + Based on the files conf-lex.l and conf-parse.y written by + Thomas Moestl. + This version was rewritten in C from scratch by Paul A. Rombouts + and doesn't require (f)lex or yacc/bison. + + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011 Paul A. Rombouts. + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include "ipvers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(HAVE_STRUCT_IFREQ) +#include +#endif +#include "conff.h" +#include "consts.h" +#include "cache.h" +#include "dns.h" +#include "helpers.h" +#include "rr_types.h" +#include "netdev.h" +#include "conf-keywords.h" +#include "conf-parser.h" + + +/* Check that include files are not nested deeper than MAXINCLUDEDEPTH, + as a precaution against infinite recursion. */ +#define MAXINCLUDEDEPTH 100 + +static char *report_error (const char *conftype, unsigned linenr, const char *msg) +{ + char *retval; + if(linenr) { + if(asprintf(&retval, "Error in %s (line %u): %s",conftype,linenr,msg)<0) + retval=NULL; + } + else { + if(asprintf(&retval, "Error in %s: %s",conftype,msg)<0) + retval=NULL; + } + + return retval; +} + +static char *report_errorf (const char *conftype, unsigned linenr, const char *frm,...) printfunc(3, 4); +static char *report_errorf (const char *conftype, unsigned linenr, const char *frm,...) +{ + char *msg,*retval; int mlen; + va_list va; + va_start(va,frm); + mlen=vasprintf(&msg,frm,va); + va_end(va); + if(mlen<0) return NULL; + retval=report_error(conftype,linenr,msg); + free(msg); + return retval; +} + +/* return pointer to next character in linebuffer after skipping blanks and comments */ +static char* getnextp(char **buf, size_t *n, FILE* in, char *p, unsigned *linenr, char **errstr) +{ + if(!p) goto nextline; + tryagain: + if(!*p) { + nextline: + do { + if(!in || getline(buf,n,in)<0) { + *errstr=NULL; + return NULL; + } + ++*linenr; + p=*buf; + } while(!*p); + } + if(isspace(*p)) { + ++p; goto tryagain; + } + if(*p=='#') { + skip_rest_of_line: + if(*linenr) + goto nextline; + else { + p=strchr(p,'\n'); + if(p) { + ++p; + goto tryagain; + } + else + goto nextline; + } + } + if(*p=='/') { + if(*(p+1)=='/') + goto skip_rest_of_line; + if(*(p+1)=='*') { + int lev=1; + p +=2; + for(;;) { + while(*p) { + if(*p=='/' && *(p+1)=='*') { + ++lev; + p +=2; + continue; + } + else if(*p=='*' && *(p+1)=='/') { + p +=2; + if(--lev==0) goto tryagain; + continue; + } + ++p; + } + if(!in || getline(buf,n,in)<0) { + *errstr="comment without closing */"; + return NULL; + } + ++*linenr; + p=*buf; + } + } + } + + return p; +} + +static char translescapedchar(char c) +{ + switch(c) { + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + } + return c; +} + +/* Scan a buffer for a string and copy the decoded (i.e. unescaped) version into + another buffer. + + A string either begins after and ends before a double-quote ("), + or simply consists of a sequence of "non-special" characters, + starting at the current position. + A back-slash (\) acts as an escape character, preventing any character + following it from terminating the string. Thus, for example, + back-slash double-quote (\") may be used to include double-quotes + in a string. + A number of escape sequences are interpreted as in C, e.g. + \t, \n, \r yield control-chars as in C. + + char **curp should point to the position in the buffer where + the scanning should begin. It will be updated to point + to the first character past the scanned string. + + char *outbuf is used to store the decoded string. + size_t outbufsz should be the size of outbuf. + + The return value is the length of the decoded string, unless an error occurs, + in which case -1 is returned and *errstr is assigned an error message. + The returned length may be larger than outbufsz, in which case the buffer + is filled with only the first outbufsz chars of the string. +*/ +static int scan_string(char **curp,char *outbuf, unsigned outbufsz, char **errstr) +{ + char *cur=*curp; + unsigned i=0; + + if(*cur=='"') { + /* Double-quoted string. */ + ++cur; /* Skip opening quote. */ + for(;; ++i,++cur) { + if(!*cur) goto noclosingquote; + if(*cur=='"') break; + if(*cur=='\\') { + if(!*++cur) goto nofollowingchar; + if(i=sizeof(buf)) \ + {CLEANUP_HANDLERS; goto string_too_long;} \ + } +# define REPORT_ERROR(msg) (*errstr=report_error(conftype,linenr,msg)) +# if !defined(CPP_C99_VARIADIC_MACROS) + /* GNU C Macro Varargs style. */ +# define REPORT_ERRORF(args...) (*errstr=report_errorf(conftype,linenr,args)) +#else + /* ANSI C99 style. */ +# define REPORT_ERRORF(...) (*errstr=report_errorf(conftype,linenr,__VA_ARGS__)) +# endif +# define PARSERROR {CLEANUP_HANDLERS; goto free_linebuf_return;} +# define OUTOFMEMERROR {CLEANUP_HANDLERS; goto out_of_memory;} +# define CLEANUP_GOTO(lab) {CLEANUP_HANDLERS; goto lab;} + + *errstr=NULL; + if(in) { + linebuf=malloc(buflen); + if(!linebuf) { + /* If malloc() just failed, allocating space for an error message is unlikely to succeed. */ + return 0; + } + if(global) + conftype="config file"; + else + conftype="include file"; + } + else + conftype="config string"; + + p=prestr; + while((p=getnextp(&linebuf,&buflen,in,p,&linenr,&getnextperr))) { + if(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + sechdr=lookup_keyword(ps,len,section_headers); + if(!sechdr) { + REPORT_ERRORF("invalid section header: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='{') goto expected_bropen; + ++p; + SKIP_BLANKS(p); + + switch(sechdr) { + case GLOBAL: + if(!global) { + REPORT_ERROR(in?"global section not allowed in include file": + "global section not allowed in eval string"); + PARSERROR; + } + + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,global_options); + if(!option) { + REPORT_ERRORF("invalid option for global section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') goto expected_equals; + ++p; + SKIP_BLANKS(p); + + switch(option) { + pdnsd_a *ipaddrp; + + case PERM_CACHE: + if (isalpha(*p)) { + int cnst; + SCAN_ALPHANUM(ps,p,len); + cnst=lookup_const(ps,len); + if(cnst==C_OFF) { + global->perm_cache=0; + } + else + goto bad_perm_cache_option; + } + else if(isdigit(*p)) { + global->perm_cache=strtol(p,&p,0); + } + else { + bad_perm_cache_option: + REPORT_ERROR("bad qualifier in perm_cache= option."); + PARSERROR; + } + break; + + case CACHE_DIR: + SCAN_STRING(p,strbuf,len); + STRNDUP(global->cache_dir,strbuf,len); + break; + + case SERVER_PORT: + SCAN_UNSIGNED_NUM(global->port,p,"server_port option") + break; + + case OUTGOING_IP: + ipaddrp= &global->out_a; + goto scan_ip_or_interface; + + case SERVER_IP: + ipaddrp= &global->a; + scan_ip_or_interface: + SCAN_STRING(p,strbuf,len); + { + const char *err; + if ((err=parse_ip(strbuf,ipaddrp))) { +#if defined(HAVE_STRUCT_IFREQ) && defined(IFNAMSIZ) && defined(SIOCGIFADDR) + if(!strcmp(err,"bad IP address") && lenipv4= ((struct sockaddr_in *)&req.ifr_addr)->sin_addr; +# endif +# ifdef ENABLE_IPV6 + ELSE_IPV6 + ipaddrp->ipv6= ((struct sockaddr_in6 *)&req.ifr_addr)->sin6_addr; +# endif + close(fd); + } + else { + REPORT_ERRORF("Failed to get IP address of %s: %s",req.ifr_name,strerror(errno)); + if(fd!=-1) close(fd); + PARSERROR; + } + } + else +#endif + { + REPORT_ERRORF("%s for the %s= option.",err,option==SERVER_IP?"server_ip":"outgoing_ip"); + PARSERROR; + } + } + } + break; + + case SCHEME_FILE: + SCAN_STRING(p,strbuf,len); + STRNDUP(global->scheme_file, strbuf,len); + break; + + case LINKDOWN_KLUGE: + ASSIGN_ON_OFF(global->lndown_kluge,p,C_ON,"bad qualifier in linkdown_kluge= option."); + break; + + case MAX_TTL: + SCAN_TIMESECS(global->max_ttl,p,"max_ttl option"); + break; + + case MIN_TTL: + SCAN_TIMESECS(global->min_ttl,p,"min_ttl option"); + break; + + case RUN_AS: + SCAN_STRING(p,strbuf,len); + STRNCP(global->run_as, strbuf,len, "run_as"); + break; + + case STRICT_SETUID: + ASSIGN_ON_OFF(global->strict_suid, p,C_ON,"bad qualifier in strict_setuid= option."); + break; + + case USE_NSS: + ASSIGN_ON_OFF(global->use_nss, p,C_ON,"bad qualifier in use_nss= option."); + break; + + case PARANOID: + ASSIGN_ON_OFF(global->paranoid, p,C_ON,"bad qualifier in paranoid= option."); + break; + + case IGNORE_CD: { + int ignore_cd; + ASSIGN_ON_OFF(ignore_cd, p,C_ON,"bad qualifier in ignore_cd= option."); + fprintf(stderr, "Warning: ignore_cd option in configuration file is obsolete and currently has no effect.\n"); + } + break; + + case STATUS_CTL: { + int cnst; + ASSIGN_CONST(cnst, p,cnst==C_ON || cnst==C_OFF ,"bad qualifier in status_pipe= option."); + if(!cmdline.stat_pipe) global->stat_pipe=(cnst==C_ON); + } + break; + + case DAEMON: { + int cnst; + ASSIGN_CONST(cnst, p,cnst==C_ON || cnst==C_OFF ,"bad qualifier in daemon= option."); + if(!cmdline.daemon) global->daemon=(cnst==C_ON); + } + break; + + case C_TCP_SERVER: { + int cnst; + ASSIGN_CONST(cnst, p,cnst==C_ON || cnst==C_OFF ,"bad qualifier in tcp_server= option."); + if(!cmdline.notcp) { + global->notcp=(cnst==C_OFF); +#ifdef NO_TCP_SERVER + if(!global->notcp) { + REPORT_ERROR("pdnsd was compiled without TCP server support. tcp_server=on is not allowed."); + PARSERROR; + } +#endif + } + } + break; + + case PID_FILE: + SCAN_STRING(p,strbuf,len); + if(!cmdline.pidfile) {STRNDUP(global->pidfile,strbuf,len);} + break; + + case C_VERBOSITY: { + int val; + SCAN_UNSIGNED_NUM(val,p,"verbosity option"); + if(!cmdline.verbosity) global->verbosity=val; + } + break; + + case C_QUERY_METHOD: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==TCP_ONLY || cnst==UDP_ONLY || cnst==TCP_UDP || cnst==UDP_TCP,"bad qualifier in query_method= option."); +#ifdef NO_TCP_QUERIES + if (cnst==TCP_ONLY) { + REPORT_ERROR("the tcp_only option is only available when pdnsd is compiled with TCP support."); + PARSERROR; + } + else +#endif +#ifdef NO_UDP_QUERIES + if (cnst==UDP_ONLY) { + REPORT_ERROR("the udp_only option is only available when pdnsd is compiled with UDP support."); + PARSERROR; + } + else +#endif +#if defined(NO_TCP_QUERIES) || defined(NO_UDP_QUERIES) + if (cnst==TCP_UDP) { + REPORT_ERROR("the tcp_udp option is only available when pdnsd is compiled with both TCP and UDP support."); + PARSERROR; + } + else if (cnst==UDP_TCP) { + REPORT_ERROR("the udp_tcp option is only available when pdnsd is compiled with both TCP and UDP support."); + PARSERROR; + } + else +#endif + if(!cmdline.query_method) global->query_method=cnst; + } + break; + + case RUN_IPV4: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF,"bad qualifier in run_ipv4= option."); +#ifndef ENABLE_IPV4 + if(cnst==C_ON) { + REPORT_ERROR("You can only set run_ipv4=on when pdnsd is compiled with IPv4 support."); + PARSERROR; + } +#endif +#ifndef ENABLE_IPV6 + if(cnst==C_OFF) { + REPORT_ERROR("You can only set run_ipv4=off when pdnsd is compiled with IPv6 support."); + PARSERROR; + } +#endif +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + if(!cmdlineipv) { + run_ipv4=(cnst==C_ON); cmdlineipv=-1; + } + else if(cmdlineipv<0 && run_ipv4!=(cnst==C_ON)) { + REPORT_ERROR(cmdlineipv==-1? + "IPv4/IPv6 conflict: you are trying to set run_ipv4 to a value that conflicts with a previous run_ipv4 setting.": + "You must set the run_ipv4 option before specifying IP addresses."); + PARSERROR; + } +#endif + } + break; + + case IPV4_6_PREFIX: + SCAN_STRING(p,strbuf,len); +#ifdef ENABLE_IPV6 + if(!cmdline.prefix) { + if(inet_pton(AF_INET6,strbuf,&global->ipv4_6_prefix)<=0) { + REPORT_ERROR("ipv4_6_prefix: argument not a valid IPv6 address."); + PARSERROR; + } + } +#else + fprintf(stderr,"pdnsd was compiled without IPv6 support. ipv4_6_prefix option in config file will be ignored.\n"); +#endif + break; + + case C_DEBUG: { + int cnst; + ASSIGN_CONST(cnst, p,cnst==C_ON || cnst==C_OFF ,"bad qualifier in debug= option."); + if(!cmdline.debug) { + global->debug=(cnst==C_ON); +#if !DEBUG + if(global->debug) + fprintf(stderr,"pdnsd was compiled without debugging support. debug=on has no effect.\n"); +#endif + } + } + break; + + case C_CTL_PERMS: + SCAN_UNSIGNED_NUM(global->ctl_perms, p,"ctl_perms option"); + break; + + case C_PROC_LIMIT: + SCAN_UNSIGNED_NUM(global->proc_limit, p,"proc_limit option"); + break; + + case C_PROCQ_LIMIT: + SCAN_UNSIGNED_NUM(global->procq_limit, p,"procq_limit option"); + break; + + case TCP_QTIMEOUT: + SCAN_TIMESECS(global->tcp_qtimeout, p,"tcp_qtimeout option"); + break; + + case TIMEOUT: + SCAN_TIMESECS(global->timeout, p,"global timeout option"); + break; + + case C_PAR_QUERIES: { + int val; + SCAN_UNSIGNED_NUM(val, p,"par_queries option"); + if(val<=0) { + REPORT_ERROR("bad value for par_queries."); + PARSERROR; + } else { + global->par_queries=val; + } + } + break; + + case C_RAND_RECS: + ASSIGN_ON_OFF(global->rnd_recs, p,C_ON,"bad qualifier in randomize_recs= option."); + break; + + case NEG_TTL: + SCAN_TIMESECS(global->neg_ttl, p,"neg_ttl option"); + break; + + case NEG_RRS_POL: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF || cnst==C_DEFAULT || cnst==C_AUTH, + "bad qualifier in neg_rrs_pol= option."); + global->neg_rrs_pol=cnst; + } + break; + + case NEG_DOMAIN_POL: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF || cnst==C_AUTH,"bad qualifier in neg_domain_pol= option."); + global->neg_domain_pol=cnst; + } + break; + + case QUERY_PORT_START: { + int val; + if(isalpha(*p)) { + int cnst; + SCAN_ALPHANUM(ps,p,len); + cnst=lookup_const(ps,len); + if(cnst==C_NONE) + val=-1; + else + goto bad_port_start_option; + } + else if(isdigit(*p)) { + val=strtol(p,&p,0); + if(val>65535) { + REPORT_ERROR("value for query_port_start out of range."); + PARSERROR; + } + else if(val<1024) + fprintf(stderr,"Warning: query_port_start=%i but source ports <1204 can only be used as root.\n", + val); + } + else { + bad_port_start_option: + REPORT_ERROR("bad qualifier in query_port_start= option."); + PARSERROR; + } + global->query_port_start=val; + } + break; + + case QUERY_PORT_END: { + int val; + SCAN_UNSIGNED_NUM(val,p,"query_port_end option"); + if(val>65535) { + REPORT_ERROR("value for query_port_end out of range."); + PARSERROR; + } + global->query_port_end=val; + } + break; + + case UDP_BUFSIZE: { + int val; + SCAN_UNSIGNED_NUM(val,p,"udpbufsize"); + if(val<512 || val>65535-(20+8)) { + REPORT_ERROR("value for udpbufsize out of range."); + PARSERROR; + } + global->udpbufsize=val; + } + break; + + case DELEGATION_ONLY: + SCAN_STRING_LIST(&global->deleg_only_zones,p,strbuf,len,zone_add) + break; + + default: /* we should never get here */ + goto internal_parse_error; + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') goto expected_semicolon; + ++p; + SKIP_BLANKS(p); + } + + if(*p!='}') goto expected_closing_brace; + if (global->query_port_end < global->query_port_start) { + REPORT_ERROR("query_port_end may not be smaller than query_port_start."); + PARSERROR; + } + break; + + case SERVER: { + servparm_t server; + + if(!servers) { + REPORT_ERROR(in?"server section not allowed in include file": + "server section not allowed in eval string"); + PARSERROR; + } + + server=serv_presets; +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER (free_servparm(&server)) + + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,server_options); + if(!option) { + REPORT_ERRORF("invalid option for server section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') CLEANUP_GOTO(expected_equals); + ++p; + SKIP_BLANKS(p); + + switch(option) { + case IP: + SCAN_STRING_LIST(&server.atup_a,p,strbuf,len,addr_add_); + break; + + case FILET: + SCAN_STRING(p,strbuf,len); + { + char *errmsg; + if (!read_resolv_conf(strbuf, &server.atup_a, &errmsg)) { + if(errmsg) {REPORT_ERROR(errmsg); free(errmsg);} + else *errstr=NULL; + PARSERROR; + } + } + break; + + case PORT: + SCAN_UNSIGNED_NUM(server.port,p,"port option"); + break; + + case SCHEME: + SCAN_STRING(p,strbuf,len); + STRNCP(server.scheme, strbuf,len, "scheme"); + break; + + case UPTEST: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_PING || cnst==C_NONE || cnst==C_IF || cnst==C_EXEC || cnst==C_DEV || cnst==C_DIALD || cnst==C_QUERY,"bad qualifier in uptest= option."); + server.uptest=cnst; + } + break; + + case TIMEOUT: + SCAN_TIMESECS(server.timeout,p,"timeout option"); + break; + + case PING_TIMEOUT: + SCAN_UNSIGNED_NUM(server.ping_timeout,p,"ping_timeout option"); + break; + + case PING_IP: + SCAN_STRING(p,strbuf,len); + { + const char *err; + if ((err=parse_ip(strbuf,&server.ping_a))) { + REPORT_ERRORF("%s for the ping_ip= option.",err); + PARSERROR; + } + } + break; + + case UPTEST_CMD: + SCAN_STRING(p,strbuf,len); + STRNDUP(server.uptest_cmd, strbuf,len); + SKIP_BLANKS(p); + if(*p==',') { + ++p; + SKIP_BLANKS(p); + SCAN_STRING(p,strbuf,len); + STRNCP(server.uptest_usr, strbuf,len, "second argument of uptest_cmd"); + } + break; + + case QUERY_TEST_NAME: + if(isalpha(*p)) { + int cnst; + SCAN_ALPHANUM(ps,p,len); + if(*p!='.' && *p!='-') { + cnst=lookup_const(ps,len); + if(cnst==C_NONE) { + if(server.query_test_name) + free(server.query_test_name); + server.query_test_name=NULL; + break; + } + } + p=ps; /* reset current char pointer and try again. */ + } + { + unsigned char tname[DNSNAMEBUFSIZE], *copy; + unsigned sz; + + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,tname); + sz=rhnlen(tname); + copy= malloc(sz); + if(!copy) { + OUTOFMEMERROR; + } + memcpy(copy,tname,sz); + if(server.query_test_name) + free(server.query_test_name); + server.query_test_name=copy; + } + break; + + case INTERVAL: + if(isalpha(*p)) { + int cnst; + SCAN_ALPHANUM(ps,p,len); + cnst=lookup_const(ps,len); + if(cnst==C_ONQUERY) { + server.interval=-1; + } + else if(cnst==C_ONTIMEOUT) { + server.interval=-2; + } + else { + goto bad_interval_option; + } + } + else if(isdigit(*p)) { + char *err; + server.interval=strtotime(p,&p,&err); + if(err) { + REPORT_ERRORF("bad time specification in interval= option: %s",err); + PARSERROR; + } + } + else { + bad_interval_option: + REPORT_ERROR("bad qualifier in interval= option."); + PARSERROR; + } + break; + + case INTERFACE: + SCAN_STRING(p,strbuf,len); + STRNCP(server.interface, strbuf,len, "interface"); + break; + + case DEVICE: + SCAN_STRING(p,strbuf,len); + STRNCP(server.device, strbuf,len, "device"); + break; + + case PURGE_CACHE: + ASSIGN_ON_OFF(server.purge_cache,p,C_ON,"bad qualifier in purge_cache= option."); + break; + + case CACHING: + ASSIGN_ON_OFF(server.nocache,p,C_OFF,"bad qualifier in caching= option."); + break; + + case LEAN_QUERY: + ASSIGN_ON_OFF(server.lean_query,p,C_ON,"bad qualifier in lean_query= option."); + break; + + case EDNS_QUERY: + ASSIGN_ON_OFF(server.edns_query,p,C_ON,"bad qualifier in edns_query= option."); + break; + + case PRESET: + ASSIGN_ON_OFF(server.preset,p,C_ON,"bad qualifier in preset= option."); + break; + + case PROXY_ONLY: + ASSIGN_ON_OFF(server.is_proxy,p,C_ON,"bad qualifier in proxy_only= option."); + break; + + case ROOT_SERVER: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF || cnst==C_DISCOVER,"bad qualifier in root_server= option."); + server.rootserver= (cnst==C_DISCOVER? 2: cnst==C_ON); + } + break; + + case RANDOMIZE_SERVERS: + ASSIGN_ON_OFF(server.rand_servers,p,C_ON,"bad qualifier in randomize_servers= option."); + break; + + case POLICY: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_INCLUDED || cnst==C_EXCLUDED || cnst==C_SIMPLE_ONLY || cnst==C_FQDN_ONLY,"bad qualifier in policy= option."); + server.policy=cnst; + } + break; + + case INCLUDE: + SCAN_STRING_LIST(&server.alist,p,strbuf,len,include_list_add) + break; + + case EXCLUDE: + SCAN_STRING_LIST(&server.alist,p,strbuf,len,exclude_list_add) + break; + + case REJECTLIST: + SCAN_STRING_LIST(&server,p,strbuf,len,reject_add_); + break; + + case REJECTPOLICY: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_FAIL || cnst==C_NEGATE,"bad qualifier in reject_policy= option."); + server.rejectpolicy=cnst; + } + break; + + case REJECTRECURSIVELY: + ASSIGN_ON_OFF(server.rejectrecursively,p,C_ON,"bad qualifier in reject_recursively= option."); + break; + + case LABEL: + SCAN_STRING(p,strbuf,len); + STRNDUP(server.label,strbuf,len); + break; + + default: /* we should never get here */ + CLEANUP_GOTO(internal_parse_error); + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') CLEANUP_GOTO(expected_semicolon); + ++p; + SKIP_BLANKS(p); + } + + if(*p!='}') CLEANUP_GOTO(expected_closing_brace); + if (server.uptest==C_EXEC) { + if (!server.uptest_cmd) { + REPORT_ERROR("you must specify uptest_cmd if you specify uptest=exec!"); + PARSERROR; + } + } + if (server.is_proxy && server.rootserver) { + REPORT_ERROR("A server may not be specified as both a proxy and a root-server."); + PARSERROR; + } + if(server.rootserver && (server.policy==C_SIMPLE_ONLY || server.policy==C_FQDN_ONLY)) + fprintf(stderr,"Warning: using policy=%s with a root-server usually makes no sense.", + const_name(server.policy)); + if (DA_NEL(server.atup_a)) { + check_localaddrs(&server); + if(!DA_NEL(server.atup_a)) { + REPORT_ERROR("Server section contains only local IP addresses.\n" + "Bind pdnsd to a different local IP address or specify different port numbers" + " in global section and server section if you want pdnsd to query servers on" + " the same machine."); + PARSERROR; + } + } + { + int j,n=DA_NEL(server.atup_a); + for(j=0;jis_up=server.preset; + /* A negative test interval means don't test at startup or reconfig. */ + if(server.interval<0) at->i_ts=time(NULL); + } + } + if(server.interval==-1) global->onquery=1; + + if (!(*servers=DA_GROW1_F(*servers,(void(*)(void*))free_servparm))) { + OUTOFMEMERROR; + } + DA_LAST(*servers)= server; +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER + } + break; + + case RR: { + /* Initialize c_cent to all zeros. + Then it should be safe to call free_cent() on it, even before calling init_cent(). */ + dns_cent_t c_cent={0}; + time_t c_ttl=86400; + unsigned c_flags=DF_LOCAL; + unsigned char reverse=0; + +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER (free_cent(&c_cent DBG0)) + + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,rr_options); + if(!option) { + REPORT_ERRORF("invalid option for rr section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') CLEANUP_GOTO(expected_equals); + ++p; + SKIP_BLANKS(p); + + switch(option) { + int tp; const char *tpname; + case NAME: { + unsigned char c_name[DNSNAMEBUFSIZE]; + if (c_cent.qname) { + REPORT_ERROR("You may specify only one name in a rr section."); + PARSERROR; + } + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,c_name); + if (!init_cent(&c_cent, c_name, 0, 0, c_flags DBG0)) + goto out_of_memory; + } + break; + + case TTL: + SCAN_TIMESECS(c_ttl,p, "ttl option"); + break; + + case AUTHREC: { + int cnst; + if (c_cent.qname) { + REPORT_ERROR("The authrec= option has no effect unless it precedes name= in a rr section."); + PARSERROR; + } + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF,"Bad qualifier in authrec= option."); + c_flags=(cnst==C_ON)?DF_LOCAL:0; + } + break; + + case REVERSE: + ASSIGN_ON_OFF(reverse,p,C_ON,"bad qualifier in reverse= option."); + break; + + case A: { + unsigned int sz; + pdnsd_ca c_a; + + if (!c_cent.qname) + goto no_name_spec; + SCAN_STRING(p,strbuf,len); + if (inet_aton(strbuf,&c_a.ipv4)) { + tp=T_A; + sz=sizeof(struct in_addr); + } + else +#if ALLOW_LOCAL_AAAA + if (inet_pton(AF_INET6,strbuf,&c_a.ipv6)>0) { + tp=T_AAAA; + sz=sizeof(struct in6_addr); + } + else +#endif + { + REPORT_ERROR("bad IP address in a= option."); + PARSERROR; + } + + if(!add_cent_rr(&c_cent,tp,c_ttl,0,CF_LOCAL,sz,&c_a DBG0)) + goto add_rr_failed; + } + break; + + case OWNER: + tp=T_NS; + goto scan_name; + case CNAME: + tp=T_CNAME; + goto scan_name; + case PTR: + tp=T_PTR; + scan_name: + { + unsigned char c_name[DNSNAMEBUFSIZE]; + + if (!c_cent.qname) + goto no_name_spec; + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,c_name); + if(!add_cent_rr(&c_cent,tp,c_ttl,0,CF_LOCAL,rhnlen(c_name),c_name DBG0)) + goto add_rr_failed; + } + break; + + case MX: { + unsigned char *cp; + unsigned pref; + unsigned char c_mx[2+DNSNAMEBUFSIZE]; + + if (!c_cent.qname) + goto no_name_spec; + cp=c_mx+2; + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,cp); + SKIP_COMMA(p,"missing second argument (preference level) of mx= option"); + SCAN_UNSIGNED_NUM(pref,p,"second argument of mx= option"); + cp=c_mx; + PUTINT16(pref,cp); + if(!add_cent_rr(&c_cent,T_MX,c_ttl,0,CF_LOCAL,2+rhnlen(cp),c_mx DBG0)) + goto add_rr_failed; + } + break; + + case SOA: { + unsigned int blen,rlen; + unsigned char *bp; + uint32_t val; + unsigned char buf[2*DNSNAMEBUFSIZE+20]; + + if (!c_cent.qname) + goto no_name_spec; + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,buf); + rlen=rhnlen(buf); + blen=rlen; + bp=buf+rlen; + SKIP_COMMA(p,"missing 2nd argument of soa= option"); + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,bp); + rlen=rhnlen(bp); + blen += rlen; + bp += rlen; + SKIP_COMMA(p,"missing 3rd argument of soa= option"); + SCAN_UNSIGNED_NUM(val,p,"3rd argument of soa= option"); + PUTINT32(val,bp); + SKIP_COMMA(p,"missing 4th argument of soa= option"); + SCAN_TIMESECS(val,p,"4th argument of soa= option"); + PUTINT32(val,bp); + SKIP_COMMA(p,"missing 5th argument of soa= option"); + SCAN_TIMESECS(val,p,"5th argument of soa= option"); + PUTINT32(val,bp); + SKIP_COMMA(p,"missing 6th argument of soa= option"); + SCAN_TIMESECS(val,p,"6th argument of soa= option"); + PUTINT32(val,bp); + SKIP_COMMA(p,"missing 7th argument of soa= option"); + SCAN_TIMESECS(val,p,"7th argument of soa= option"); + PUTINT32(val,bp); + blen += 20; + if(!add_cent_rr(&c_cent,T_SOA,c_ttl,0,CF_LOCAL,blen,buf DBG0)) + goto add_rr_failed; + } + break; + case SPF: +#if IS_CACHED_SPF + tp=T_SPF; tpname="spf"; + goto define_txt_rr; +#else + REPORT_ERROR("Missing support for caching SPF records in rr section"); + PARSERROR; +#endif + case TXT: +#if IS_CACHED_TXT + tp=T_TXT; tpname="txt"; +#else + REPORT_ERROR("Missing support for caching TXT records in rr section"); + PARSERROR; +#endif +#if IS_CACHED_TXT || IS_CACHED_SPF +#if IS_CACHED_SPF + define_txt_rr: +#endif + { + unsigned char *rbuf; + unsigned sz,allocsz; + int rv; + + if (!c_cent.qname) + goto no_name_spec; + rbuf=NULL; + sz=allocsz=0; +# undef CLEANUP_HANDLER2 +# define CLEANUP_HANDLER2 (free(rbuf)) + + for(;;) { + unsigned char *newbuf,*cp; + unsigned newsz=sz+256; + int n; + if(newsz>allocsz) { + allocsz += 512; + newbuf=realloc(rbuf,allocsz); + if(!newbuf) { + OUTOFMEMERROR; + } + rbuf=newbuf; + } + cp = rbuf+sz; + n=scan_string(&p, charp (cp+1), 255, &scanstrerr); + if(n==-1) { + REPORT_ERRORF("%s in %s= option", scanstrerr, tpname); + PARSERROR; + } + if(n>255) { + REPORT_ERRORF("string longer than 255 bytes in %s= option", tpname); + PARSERROR; + } + *cp=n; + sz += n+1; + if(sz>0xffff) { + REPORT_ERRORF("data exceeds maximum size (65535 bytes) in %s= option", tpname); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!=',') break; + ++p; + SKIP_BLANKS(p); + } + rv=add_cent_rr(&c_cent,tp,c_ttl,0,CF_LOCAL,sz,rbuf DBG0); + CLEANUP_HANDLER2; +# undef CLEANUP_HANDLER2 +# define CLEANUP_HANDLER2 + if(!rv) + goto add_rr_failed; + } + break; +#endif + default: /* we should never get here */ + CLEANUP_GOTO(internal_parse_error); + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') CLEANUP_GOTO(expected_semicolon); + ++p; + SKIP_BLANKS(p); + } + + if(*p!='}') CLEANUP_GOTO(expected_closing_brace); + if (!c_cent.qname) + goto no_name_spec; + if(c_cent.qname[0]==1 && c_cent.qname[1]=='*') { + /* Wild card record. Set the DF_WILD flag for the name with '*.' removed. */ + if(!set_cent_flags(&c_cent.qname[2],DF_WILD)) { + unsigned char buf[DNSNAMEBUFSIZE]; + rhn2str(c_cent.qname,buf,sizeof(buf)); + REPORT_ERRORF("You must define some records for '%s'" + " before you can define records for the wildcard name '%s'", + &buf[2],buf); + PARSERROR; + } + } + + add_cache(&c_cent); + if(reverse) { + if(!add_reverse_cache(&c_cent)) { + REPORT_ERROR("Can't convert IP address in a= option" + " into form suitable for reverse resolving."); + PARSERROR; + } + } + CLEANUP_HANDLER; + break; + + add_rr_failed: + OUTOFMEMERROR; +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER + } + + case SOURCE: { + unsigned char c_owner[DNSNAMEBUFSIZE]; + time_t c_ttl; + unsigned c_flags; + unsigned char c_aliases; + + c_owner[0]='\0'; + c_ttl=86400; + c_flags=DF_LOCAL; + c_aliases=0; + + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,source_options); + if(!option) { + REPORT_ERRORF("invalid option for source section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') goto expected_equals; + ++p; + SKIP_BLANKS(p); + + switch(option) { + case OWNER: + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,c_owner); + break; + + case TTL: + SCAN_TIMESECS(c_ttl,p,"ttl option"); + break; + + case FILET: + if (!c_owner[0]) { + REPORT_ERROR("you must specify owner before file= in source records."); + PARSERROR; + } + SCAN_STRING(p,strbuf,len); + { + char *errmsg; + if (!read_hosts(strbuf, c_owner, c_ttl, c_flags, c_aliases, &errmsg)) { + if(errmsg) { REPORT_ERROR(errmsg); free(errmsg); } + else *errstr=NULL; + PARSERROR; + } + } + break; + + case SERVE_ALIASES: + ASSIGN_ON_OFF(c_aliases,p,C_ON,"Bad qualifier in serve_aliases= option."); + break; + + case AUTHREC: { + int cnst; + ASSIGN_CONST(cnst,p,cnst==C_ON || cnst==C_OFF,"Bad qualifier in authrec= option."); + c_flags=(cnst==C_ON)?DF_LOCAL:0; + } + break; + + default: /* we should never get here */ + goto internal_parse_error; + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') goto expected_semicolon; + ++p; + SKIP_BLANKS(p); + } + } + break; + + case INCLUDE_F: { + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,include_options); + if(!option) { + REPORT_ERRORF("invalid option for include section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') goto expected_equals; + ++p; + SKIP_BLANKS(p); + + switch(option) { + case FILET: + if(includedepth>=MAXINCLUDEDEPTH) { + REPORT_ERRORF("maximum include depth (%d) exceeded.",MAXINCLUDEDEPTH); + PARSERROR; + } + SCAN_STRING(p,strbuf,len); + { + char *errmsg; + if (!read_config_file(strbuf, NULL, NULL, includedepth+1, &errmsg)) { + if(errmsg) { + if(linenr) { + if(asprintf(errstr, "In file %s included at line %u:\n%s",strbuf,linenr,errmsg)<0) + *errstr=NULL; + } + else { + if(asprintf(errstr, "In file %s:\n%s",strbuf,errmsg)<0) + *errstr=NULL; + } + free(errmsg); + } + else + *errstr=NULL; + PARSERROR; + } + } + break; + + default: /* we should never get here */ + goto internal_parse_error; + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') goto expected_semicolon; + ++p; + SKIP_BLANKS(p); + } + } + break; + + case NEG: { + unsigned char c_name[DNSNAMEBUFSIZE]; + time_t c_ttl; + unsigned char htp,hdtp; + + htp=0; + hdtp=0; + c_name[0]='\0'; + c_ttl=86400; + + while(isalpha(*p)) { + SCAN_ALPHANUM(ps,p,len); + option=lookup_keyword(ps,len,neg_options); + if(!option) { + REPORT_ERRORF("invalid option for neg section: %.*s",(int)len,ps); + PARSERROR; + } + SKIP_BLANKS(p); + if(*p!='=') goto expected_equals; + ++p; + SKIP_BLANKS(p); + + switch(option) { + case NAME: + SCAN_STRING(p,strbuf,len); + PARSESTR2RHN(ucharp strbuf,len,c_name); + break; + + case TTL: + SCAN_TIMESECS(c_ttl,p, "ttl option"); + break; + + case TYPES: + if (!c_name[0]) { + REPORT_ERROR("you must specify a name before the types= option."); + PARSERROR; + } + if (isalpha(*p)) { + int cnst; + dns_cent_t c_cent /* ={0} */; + SCAN_ALPHANUM(ps,p,len); + cnst=lookup_const(ps,len); + if(cnst==C_DOMAIN) { + if (htp) { + REPORT_ERROR("You may not specify types=domain together with other types!"); + PARSERROR; + } + hdtp=1; + if (!init_cent(&c_cent, c_name, c_ttl, 0, DF_LOCAL|DF_NEGATIVE DBG0)) + goto out_of_memory; + } + else if(cnst==0) { + if (hdtp) { + REPORT_ERROR("You may not specify types=domain together with other types!"); + PARSERROR; + } + htp=1; + if (!init_cent(&c_cent, c_name, 0, 0, 0 DBG0)) + goto out_of_memory; +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER (free_cent(&c_cent DBG0)) + for(;;) { + { + TEMPSTRNCPY(buf,ps,len); + cnst=rr_tp_byname(buf); + } + if(cnst==-1) { + REPORT_ERRORF("unrecognized rr type '%.*s' used as argument for types= option.",(int)len,ps); + PARSERROR; + } + if(PDNSD_NOT_CACHED_TYPE(cnst)) { + REPORT_ERRORF("illegal rr type '%.*s' used as argument for types= option.",(int)len,ps); + PARSERROR; + } + if (!getrrset_eff(&c_cent,cnst) && !add_cent_rrset_by_type(&c_cent,cnst,c_ttl,0,CF_LOCAL|CF_NEGATIVE DBG0)) { + OUTOFMEMERROR; + } + SKIP_BLANKS(p); + if(*p!=',') break; + ++p; + SKIP_BLANKS(p); + if (!isalpha(*p)) + {CLEANUP_GOTO(bad_types_option);} + SCAN_ALPHANUM(ps,p,len); + } + } + else + goto bad_types_option; + + add_cache(&c_cent); + CLEANUP_HANDLER; +# undef CLEANUP_HANDLER +# define CLEANUP_HANDLER + } + else { + bad_types_option: + REPORT_ERROR("Bad argument for types= option."); + PARSERROR; + } + break; + + default: /* we should never get here */ + goto internal_parse_error; + } /* end of switch(option) */ + + SKIP_BLANKS(p); + if(*p!=';') goto expected_semicolon; + ++p; + SKIP_BLANKS(p); + } + } + break; + + default: /* we should never get here */ + goto internal_parse_error; + } /* end of switch(sechdr) */ + + if(*p!='}') goto expected_closing_brace; + ++p; + } + else { + REPORT_ERROR("expected section header"); + PARSERROR; + } + } + + if(!in || feof(in)) { + if(getnextperr) { + REPORT_ERROR(getnextperr); + PARSERROR; + } + retval=1; /* success */ + } + else + goto input_error; + + goto free_linebuf_return; + + expected_bropen: + REPORT_ERROR("expected opening brace after section name"); + PARSERROR; + + expected_closing_brace: + REPORT_ERROR("expected beginning of new option or closing brace"); + PARSERROR; + + expected_equals: + REPORT_ERROR("expected equals sign after option name"); + PARSERROR; + + expected_semicolon: + REPORT_ERROR("too many arguments to option or missing semicolon"); + PARSERROR; + + string_err: + REPORT_ERROR(scanstrerr); + PARSERROR; + + string_too_long: + REPORT_ERROR("string length exceeds buffer size"); + PARSERROR; + + no_name_spec: + REPORT_ERROR("you must specify a name before a,ptr,cname,mx,ns(owner) and soa records."); + PARSERROR; + + internal_parse_error: + if(asprintf(errstr,"Internal inconsistency detected while parsing line %u of %s.\n" + "Please consider reporting this error to one of the maintainers.\n",linenr,conftype)<0) + *errstr=NULL; + PARSERROR; + + out_of_memory: + /* If malloc() just failed, allocating space for an error message is unlikely to succeed. */ + *errstr=NULL; + PARSERROR; + + unexpected_eof: + if(!in || feof(in)) { + REPORT_ERROR(getnextperr?getnextperr:in?"unexpected end of file":"unexpected end of input string"); + } + else + input_error: { + if(asprintf(errstr,"Error while reading config file: %s",strerror(errno))<0) + *errstr=NULL; + } + + free_linebuf_return: + free(linebuf); + return retval; + +#undef SKIP_BLANKS +#undef SCAN_STRING +#undef REPORT_ERROR +#undef REPORT_ERRORF +#undef PARSERROR +#undef OUTOFMEMERROR +#undef CLEANUP_GOTO +} + + +/* Convert a string representation of an IP address into a binary format. */ +static const char* parse_ip(const char *ipstr, pdnsd_a *a) +{ +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + if(!cmdlineipv) cmdlineipv=-2; +#endif + { + if(!strcmp(ipstr,"any")) { +#ifdef ENABLE_IPV4 + if (run_ipv4) + a->ipv4.s_addr=INADDR_ANY; +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 + a->ipv6=in6addr_any; +#endif + } + else if(!str2pdnsd_a(ipstr,a)) { +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + if(run_ipv4 && inet_pton(AF_INET6,ipstr,&a->ipv6)>0) { + return "You should set run_ipv4=off or use the command-line option -6" + " before specifying an IPv6 address"; + } +#endif + return "bad IP address"; + } + } + return NULL; +} + +/* Add an IP address to the list of name servers. */ +static const char *addr_add(atup_array *ata, const char *ipstr) +{ + atup_t *at; + pdnsd_a addr; + +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + if(!cmdlineipv) cmdlineipv=-2; +#endif + { + if(!str2pdnsd_a(ipstr,&addr)) { +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + if(run_ipv4 && inet_pton(AF_INET6,ipstr,&addr.ipv6)>0) { + fprintf(stderr,"IPv6 address \"%s\" in config file ignored while running in IPv4 mode.\n",ipstr); + return NULL; + } +#endif + return "bad IP address"; + } + } + + if (!(*ata=DA_GROW1(*ata))) { + return "out of memory!"; + } + at=&DA_LAST(*ata); + SET_PDNSD_A2(&at->a, &addr); + at->is_up=0; + at->i_ts=0; + return NULL; +} + + +/* Helper functions for making netmasks */ +inline static uint32_t mk_netmask4(int len) +{ + uint32_t m; + + if(len<=0) + return 0; + + m= ~(uint32_t)0; + return (len<32)? htonl(m<<(32-len)): m; +} + +#if ALLOW_LOCAL_AAAA +inline static void mk_netmask6(struct in6_addr *m, int len) +{ + uint32_t *ma = (uint32_t *)m; + ma[0] = mk_netmask4(len); + ma[1] = mk_netmask4(len -= 32); + ma[2] = mk_netmask4(len -= 32); + ma[3] = mk_netmask4(len -= 32); +} +#endif + +/* Add an IP address/mask to the reject lists. */ +static const char *reject_add(servparm_t *serv, const char *ipstr) +{ + char *slash=strchr(ipstr,'/'); int mlen=0; + + if(slash) { + *slash++=0; + + if(*slash && isdigit(*slash)) { + char *endptr; + int l = strtol(slash,&endptr,10); + if(!*endptr) { + mlen=l; + slash=NULL; + } + } + } + else + mlen=128; /* Works for both IPv4 and IPv6 */ + + { + addr4maskpair_t am; + + am.mask.s_addr = mk_netmask4(mlen); + if(inet_aton(ipstr,&am.a) && (!slash || inet_aton(slash,&am.mask))) { + if(!(serv->reject_a4=DA_GROW1(serv->reject_a4))) + return "out of memory!"; + + DA_LAST(serv->reject_a4) = am; + return NULL; + } + } +#if ALLOW_LOCAL_AAAA + { + addr6maskpair_t am; + + mk_netmask6(&am.mask,mlen); + if(inet_pton(AF_INET6,ipstr,&am.a)>0 && (!slash || inet_pton(AF_INET6,slash,&am.mask)>0)) { + if(!(serv->reject_a6=DA_GROW1(serv->reject_a6))) + return "out of memory!"; + + DA_LAST(serv->reject_a6) = am; + return NULL; + } + } +#endif + + return "bad IP address"; +} + +/* Try to avoid the possibility that pdnsd will query itself. */ +static void check_localaddrs(servparm_t *serv) +{ + if(serv->port == global.port) { + atup_array ata=serv->atup_a; + int i,j=0,n=DA_NEL(ata); + for(i=0;ia))) { + char buf[ADDRSTR_MAXLEN]; + fprintf(stderr,"Local name-server address \"%s\" ignored in config file.\n", + pdnsd_a2str(PDNSD_A2_TO_A(&at->a),buf,ADDRSTR_MAXLEN)); + continue; + } + } + else { + if(equiv_inaddr2(&global.a,&at->a)) { + char buf[ADDRSTR_MAXLEN]; + fprintf(stderr,"Ignoring name-server address \"%s\" in config file (identical to server_ip address).\n", + pdnsd_a2str(PDNSD_A2_TO_A(&at->a),buf,ADDRSTR_MAXLEN)); + continue; + } + } + if(jatup_a=DA_RESIZE(ata,j); + } +} + +/* Read the name server addresses from a resolv.conf-style file. */ +static int read_resolv_conf(const char *fn, atup_array *ata, char **errstr) +{ + int rv=0; + FILE *f; + char *buf; + size_t buflen=256; + unsigned linenr=0; + + if (!(f=fopen(fn,"r"))) { + if(asprintf(errstr, "Failed to open %s: %s", fn, strerror(errno))<0) + *errstr=NULL; + return 0; + } + buf=malloc(buflen); + if(!buf) { + *errstr=NULL; + goto fclose_return; + } + while(getline(&buf,&buflen,f)>=0) { + size_t len; + char *p,*ps; + ++linenr; + p=buf; + for(;; ++p) { + if(!*p) goto nextline; + if(!isspace(*p)) break; + } + ps=p; + do { + if(!*++p) goto nextline; + } while(!isspace(*p)); + len=p-ps; + if(len==strlitlen("nameserver") && !strncmp(ps,"nameserver",len)) { + const char *errmsg; + do { + if(!*++p) goto nextline; + } while (isspace(*p)); + ps=p; + do { + ++p; + } while(*p && !isspace(*p)); + len=p-ps; + { + TEMPSTRNCPY(ipstr,ps,len); + errmsg=addr_add(ata, ipstr); + } + if(errmsg) { + if(asprintf(errstr, "%s in line %u of file %s", errmsg,linenr,fn)<0) + *errstr=NULL; + goto cleanup_return; + } + } + nextline:; + } + if (feof(f)) + rv=1; + else if(asprintf(errstr, "Failed to read %s: %s", fn, strerror(errno))<0) + *errstr=NULL; + cleanup_return: + free(buf); + fclose_return: + fclose(f); + return rv; +} + +static const char *slist_add(slist_array *sla, const char *nm, unsigned int len, int tp) +{ + slist_t *sl; + int exact=1; + const char *err; + size_t sz; + unsigned char rhn[DNSNAMEBUFSIZE]; + + if (len>1 && *nm=='.') { + exact=0; + ++nm; + --len; + } + if((err=parsestr2rhn(ucharp nm,len,rhn))) + return err; + sz=rhnlen(rhn); + if (!(*sla=DA_GROW1_F(*sla,free_slist_domain))) { + return "out of memory!"; + } + sl=&DA_LAST(*sla); + + sl->exact=exact; + sl->rule=tp; + if (!(sl->domain=malloc(sz))) + return "out of memory!"; + memcpy(sl->domain,rhn,sz); + return NULL; +} + +static const char *zone_add(zone_array *za, const char *zone, unsigned int len) +{ + zone_t z; + const char *err; + size_t sz; + unsigned char rhn[DNSNAMEBUFSIZE]; + + if((err=parsestr2rhn(ucharp zone,len,rhn))) + return err; + sz=rhnlen(rhn); + if(!(*za=DA_GROW1_F(*za,free_zone)) || !(DA_LAST(*za)=z=malloc(sz))) + return "out of memory!"; + memcpy(z,rhn,sz); + return NULL; +} + diff --git a/jni/pdnsd/src/conf-parser.h b/jni/pdnsd/src/conf-parser.h new file mode 100644 index 00000000..d3a3e99d --- /dev/null +++ b/jni/pdnsd/src/conf-parser.h @@ -0,0 +1,29 @@ +/* conf-parser.h - definitions for parser of pdnsd config files. + The parser was rewritten in C from scratch and doesn't require (f)lex + or yacc/bison. + + Copyright (C) 2004,2008 Paul A. Rombouts. + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#ifndef CONF_PARSER_H +#define CONF_PARSER_H + +int confparse(FILE* in, char *prestr, globparm_t *global, servparm_array *servers, int includedepth, char **errstr); + +#endif /* CONF_PARSER_H */ diff --git a/jni/pdnsd/src/conff.c b/jni/pdnsd/src/conff.c new file mode 100644 index 00000000..db6c5d19 --- /dev/null +++ b/jni/pdnsd/src/conff.c @@ -0,0 +1,544 @@ +/* conff.c - Maintain configuration information + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipvers.h" +#include "conff.h" +#include "consts.h" +#include "helpers.h" +#include "conf-parser.h" +#include "servers.h" +#include "icmp.h" + + +globparm_t global={ + perm_cache: 2048, + cache_dir: NULL, + pidfile: NULL, + port: 53, + a: PDNSD_A_INITIALIZER, + out_a: PDNSD_A_INITIALIZER, +#ifdef ENABLE_IPV6 + ipv4_6_prefix: IN6ADDR_ANY_INIT, +#endif + max_ttl: 604800, + min_ttl: 120, + neg_ttl: 900, + neg_rrs_pol: C_DEFAULT, + neg_domain_pol: C_AUTH, + verbosity: VERBOSITY, + run_as: "", + daemon: 0, + debug: 0, + stat_pipe: 0, + notcp: 0, + strict_suid: 1, + use_nss: 1, + paranoid: 0, + lndown_kluge: 0, + onquery: 0, + rnd_recs: 1, + ctl_perms: 0600, + scheme_file: NULL, + proc_limit: 40, + procq_limit: 60, + tcp_qtimeout: TCP_TIMEOUT, + timeout: 0, + par_queries: PAR_QUERIES, + query_method: M_PRESET, + query_port_start: 1024, + query_port_end: 65535, + udpbufsize: 1024, + deleg_only_zones: NULL +}; + +servparm_t serv_presets={ + port: 53, + uptest: C_NONE, + timeout: 120, + interval: 900, + ping_timeout: 600, + scheme: "", + uptest_cmd: NULL, + uptest_usr: "", + interface: "", + device: "", + query_test_name: NULL, + label: NULL, + purge_cache: 0, + nocache: 0, + lean_query: 1, + edns_query: 0, + is_proxy: 0, + rootserver: 0, + rand_servers: 0, + preset: 1, + rejectrecursively: 0, + rejectpolicy: C_FAIL, + policy: C_INCLUDED, + alist: NULL, + atup_a: NULL, + reject_a4: NULL, +#if ALLOW_LOCAL_AAAA + reject_a6: NULL, +#endif + ping_a: PDNSD_A_INITIALIZER +}; + +servparm_array servers=NULL; + +static void free_zones(zone_array za); +static void free_server_data(servparm_array sa); +static int report_server_stat(int f,int i); + + +/* + * Read a configuration file, saving the results in a (separate) global section and servers array, + * and the cache. + * + * char *nm should contain the name of the file to read. If it is NULL, the name of the config file + * read during startup is used. + * + * globparm_t *global should point to a struct which will be used to store the data of the + * global section(s). If it is NULL, no global sections are allowed in the + * file. + * + * servparm_array *servers should point to a dynamic array which will be grown to store the data + * of the server sections. If it is NULL, no server sections are allowed + * in the file. + * + * char **errstr is used to return a possible error message. + * In case of failure, *errstr will refer to a newly allocated string. + * + * read_config_file returns 1 on success, 0 on failure. + */ +int read_config_file(const char *nm, globparm_t *global, servparm_array *servers, int includedepth, char **errstr) +{ + int retval=0; + const char *conftype= (global?"config":"include"); + FILE *in; + + if (nm==NULL) + nm=conf_file; + + if (!(in=fopen(nm,"r"))) { + if(asprintf(errstr,"Error: Could not open %s file %s: %s",conftype,nm,strerror(errno))<0) + *errstr=NULL; + return 0; + } + + retval=confparse(in,NULL,global,servers,includedepth,errstr); +close_file: + if(fclose(in) && retval) { + if(asprintf(errstr,"Error: Could not close %s file %s: %s", + conftype,nm,strerror(errno))<0) + *errstr=NULL; + return 0; + } + if(retval && servers && !DA_NEL(*servers)) { + if(asprintf(errstr,"Error: no server sections defined in config file %s",nm)<0) + *errstr=NULL; + return 0; + } + return retval; +} + +/* + * Re-Read the configuration file. + * Return 1 on success, 0 on failure. + * In case of failure, the old configuration will be unchanged (although the cache may not) and + * **errstr will refer to a newly allocated string containing an error message. + */ +int reload_config_file(const char *nm, char **errstr) +{ + globparm_t global_new; + servparm_array servers_new; + + global_new=global; + global_new.cache_dir=NULL; + global_new.pidfile=NULL; + global_new.scheme_file=NULL; + global_new.deleg_only_zones=NULL; + global_new.onquery=0; + servers_new=NULL; + if(read_config_file(nm,&global_new,&servers_new,0,errstr)) { + if(global_new.cache_dir && strcmp(global_new.cache_dir,global.cache_dir)) { + *errstr=strdup("Cannot reload config file: the specified cache_dir directory has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.pidfile && (!global.pidfile || strcmp(global_new.pidfile,global.pidfile))) { + *errstr=strdup("Cannot reload config file: the specified pid_file has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.scheme_file && strcmp(global_new.scheme_file,global.scheme_file)) { + *errstr=strdup("Cannot reload config file: the specified scheme_file has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.port!=global.port) { + *errstr=strdup("Cannot reload config file: the specified server_port has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(!ADDR_EQUIV(&global_new.a,&global.a)) { + *errstr=strdup("Cannot reload config file: the specified interface address (server_ip) has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } +#ifdef ENABLE_IPV6 + if(!IN6_ARE_ADDR_EQUAL(&global_new.ipv4_6_prefix,&global.ipv4_6_prefix)) { + *errstr=strdup("Cannot reload config file: the specified ipv4_6_prefix has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } +#endif + if(strcmp(global_new.run_as,global.run_as)) { + *errstr=strdup("Cannot reload config file: the specified run_as id has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.daemon!=global.daemon) { + *errstr=strdup("Cannot reload config file: the daemon option has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.debug!=global.debug) { + *errstr=strdup("Cannot reload config file: the debug option has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.stat_pipe!=global.stat_pipe) { + *errstr=strdup("Cannot reload config file: the status_ctl option has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.notcp!=global.notcp) { + *errstr=strdup("Cannot reload config file: the tcp_server option has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.strict_suid!=global.strict_suid) { + *errstr=strdup("Cannot reload config file: the strict_setuid option has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(global_new.ctl_perms!=global.ctl_perms) { + *errstr=strdup("Cannot reload config file: the specified ctl_perms has changed.\n" + "Try restarting pdnsd instead."); + goto cleanup_return; + } + if(ping_isocket==-1 +#ifdef ENABLE_IPV6 + && ping6_isocket==-1 +#endif + ) { + int i,n=DA_NEL(servers_new); + for (i=0;idomain); +} + +void free_slist_array(slist_array sla) +{ + int j,m=DA_NEL(sla); + for(j=0;juptest_cmd); + free(serv->query_test_name); + free(serv->label); + da_free(serv->atup_a); + free_slist_array(serv->alist); + da_free(serv->reject_a4); +#if ALLOW_LOCAL_AAAA + da_free(serv->reject_a6); +#endif +} + +static void free_server_data(servparm_array sa) +{ + int i,n=DA_NEL(sa); + for(i=0;ireject_a4!=NULL || (s)->reject_a6!=NULL) +#else +#define serv_has_rejectlist(s) ((s)->reject_a4!=NULL) +#endif + + +/* Report the current status of server i to the file descriptor f. + Call with locks applied. +*/ +static int report_server_stat(int f,int i) +{ + servparm_t *st=&DA_INDEX(servers,i); + int j,m; + + fsprintf_or_return(f,"Server %i:\n------\n",i); + fsprintf_or_return(f,"\tlabel: %s\n",st->label?st->label:"(none)"); + m=DA_NEL(st->atup_a); + if(st->rootserver>1 && m) + fsprintf_or_return(f,"\tThe following name servers will be used for discovery of rootservers only:\n"); + for(j=0;jatup_a,j); + {char buf[ADDRSTR_MAXLEN]; + fsprintf_or_return(f,"\tip: %s\n",pdnsd_a2str(PDNSD_A2_TO_A(&at->a),buf,ADDRSTR_MAXLEN));} + fsprintf_or_return(f,"\tserver assumed available: %s\n",at->is_up?"yes":"no"); + } + fsprintf_or_return(f,"\tport: %hu\n",st->port); + fsprintf_or_return(f,"\tuptest: %s\n",const_name(st->uptest)); + fsprintf_or_return(f,"\ttimeout: %li\n",(long)st->timeout); + if(st->interval>0) { + fsprintf_or_return(f,"\tuptest interval: %li\n",(long)st->interval); + } else { + fsprintf_or_return(f,"\tuptest interval: %s\n", + st->interval==-1?"onquery": + st->interval==-2?"ontimeout": + "(never retest)"); + } + fsprintf_or_return(f,"\tping timeout: %li\n",(long)st->ping_timeout); + {char buf[ADDRSTR_MAXLEN]; + fsprintf_or_return(f,"\tping ip: %s\n",is_inaddr_any(&st->ping_a)?"(using server ip)":pdnsd_a2str(&st->ping_a,buf,ADDRSTR_MAXLEN));} + if(st->interface[0]) { + fsprintf_or_return(f,"\tinterface: %s\n",st->interface); + } + if(st->device[0]) { + fsprintf_or_return(f,"\tdevice (for special Linux ppp device support): %s\n",st->device); + } + if(st->uptest_cmd) { + fsprintf_or_return(f,"\tuptest command: %s\n",st->uptest_cmd); + fsprintf_or_return(f,"\tuptest user: %s\n",st->uptest_usr[0]?st->uptest_usr:"(process owner)"); + } + if(st->query_test_name) { + unsigned char nmbuf[DNSNAMEBUFSIZE]; + fsprintf_or_return(f,"\tname used in query uptest: %s\n", + rhn2str(st->query_test_name,nmbuf,sizeof(nmbuf))); + } + if (st->scheme[0]) { + fsprintf_or_return(f,"\tscheme: %s\n", st->scheme); + } + fsprintf_or_return(f,"\tforce cache purging: %s\n",st->purge_cache?"on":"off"); + fsprintf_or_return(f,"\tserver is cached: %s\n",st->nocache?"off":"on"); + fsprintf_or_return(f,"\tlean query: %s\n",st->lean_query?"on":"off"); + fsprintf_or_return(f,"\tUse EDNS in outgoing queries: %s\n",st->edns_query?"on":"off"); + fsprintf_or_return(f,"\tUse only proxy?: %s\n",st->is_proxy?"on":"off"); + fsprintf_or_return(f,"\tAssumed root server: %s\n",st->rootserver?(st->rootserver==1?"yes":"discover"):"no"); + fsprintf_or_return(f,"\tRandomize server query order: %s\n",st->rand_servers?"yes":"no"); + fsprintf_or_return(f,"\tDefault policy: %s\n",const_name(st->policy)); + fsprintf_or_return(f,"\tPolicies:%s\n", st->alist?"":" (none)"); + for (j=0;jalist);++j) { + slist_t *sl=&DA_INDEX(st->alist,j); + unsigned char buf[DNSNAMEBUFSIZE]; + fsprintf_or_return(f,"\t\t%s: %s%s\n", + sl->rule==C_INCLUDED?"include":"exclude", + sl->exact?"":".", + rhn2str(sl->domain,buf,sizeof(buf))); + } + if(serv_has_rejectlist(st)) { + fsprintf_or_return(f,"\tAddresses which should be rejected in replies:\n"); + m=DA_NEL(st->reject_a4); + for (j=0;jreject_a4,j); + char abuf[ADDRSTR_MAXLEN],mbuf[ADDRSTR_MAXLEN]; + fsprintf_or_return(f,"\t\t%s/%s\n",inet_ntop(AF_INET,&am->a,abuf,sizeof(abuf)), + inet_ntop(AF_INET,&am->mask,mbuf,sizeof(mbuf))); + } +#if ALLOW_LOCAL_AAAA + m=DA_NEL(st->reject_a6); + for (j=0;jreject_a6,j); + char abuf[INET6_ADDRSTRLEN],mbuf[INET6_ADDRSTRLEN]; + fsprintf_or_return(f,"\t\t%s/%s\n",inet_ntop(AF_INET6,&am->a,abuf,sizeof(abuf)), + inet_ntop(AF_INET6,&am->mask,mbuf,sizeof(mbuf))); + } +#endif + fsprintf_or_return(f,"\tReject policy: %s\n",const_name(st->rejectpolicy)); + fsprintf_or_return(f,"\tReject recursively: %s\n",st->rejectrecursively?"yes":"no"); + } + return 0; +} diff --git a/jni/pdnsd/src/conff.h b/jni/pdnsd/src/conff.h new file mode 100644 index 00000000..a07b1561 --- /dev/null +++ b/jni/pdnsd/src/conff.h @@ -0,0 +1,190 @@ +/* conff.h - Definitions for configuration management. + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef CONFF_H +#define CONFF_H + +/* XXX should use the system defined ones. */ +/* #define MAXPATH 1024 */ +/* #define MAXIFNAME 31 */ + +#include +#include +#include +#include +#include +#include "ipvers.h" +#include "list.h" + +/* From main.c */ +#if DEBUG>0 +extern short int debug_p; +#else +#define debug_p 0 +#endif +extern short int stat_pipe; +extern pthread_t main_thrid; +extern uid_t init_uid; +extern char *conf_file; + +/* ----------- */ + +typedef DYNAMIC_ARRAY(pdnsd_a) *addr_array; +typedef DYNAMIC_ARRAY(pdnsd_a2) *addr2_array; + +typedef struct { + time_t i_ts; + char is_up; + pdnsd_a2 a; +} atup_t; +typedef DYNAMIC_ARRAY(atup_t) *atup_array; + +typedef struct { + unsigned char *domain; + short exact; + short rule; +} slist_t; +typedef DYNAMIC_ARRAY(slist_t) *slist_array; + +typedef struct { + struct in_addr a,mask; +} addr4maskpair_t; + +typedef DYNAMIC_ARRAY(addr4maskpair_t) *a4_array; + +#if ALLOW_LOCAL_AAAA +typedef struct { + struct in6_addr a,mask; +} addr6maskpair_t; + +typedef DYNAMIC_ARRAY(addr6maskpair_t) *a6_array; +#endif + +typedef struct { + unsigned short port; + short uptest; + time_t timeout; + time_t interval; + time_t ping_timeout; + char scheme[32]; + char *uptest_cmd; + char uptest_usr[21]; + char interface[IFNAMSIZ]; + char device[IFNAMSIZ]; + unsigned char *query_test_name; + char *label; + char purge_cache; + char nocache; + char lean_query; + char edns_query; + char is_proxy; + char rootserver; + char rand_servers; + char preset; + char rejectrecursively; + short rejectpolicy; + short policy; + slist_array alist; + atup_array atup_a; + a4_array reject_a4; +#if ALLOW_LOCAL_AAAA + a6_array reject_a6; +#endif + pdnsd_a ping_a; +} servparm_t; +typedef DYNAMIC_ARRAY(servparm_t) *servparm_array; + +typedef unsigned char *zone_t; +typedef DYNAMIC_ARRAY(zone_t) *zone_array; + +typedef struct { + long perm_cache; + char *cache_dir; + char *pidfile; + int port; + pdnsd_a a; + pdnsd_a out_a; +#ifdef ENABLE_IPV6 + struct in6_addr ipv4_6_prefix; +#endif + time_t max_ttl; + time_t min_ttl; + time_t neg_ttl; + short neg_rrs_pol; + short neg_domain_pol; + short verbosity; + char run_as[21]; + char daemon; + char debug; + char stat_pipe; + char notcp; + char strict_suid; + char use_nss; + char paranoid; + char lndown_kluge; + char onquery; + char rnd_recs; + int ctl_perms; + char *scheme_file; + int proc_limit; + int procq_limit; + time_t tcp_qtimeout; + time_t timeout; + int par_queries; + int query_method; + int query_port_start; + int query_port_end; + int udpbufsize; + zone_array deleg_only_zones; +} globparm_t; + +typedef struct { + char +#ifdef ENABLE_IPV6 + prefix, +#endif + pidfile, + verbosity, + pdnsduser, + daemon, + debug, + stat_pipe, + notcp, + query_method; +} cmdlineflags_t; + +extern globparm_t global; +extern cmdlineflags_t cmdline; +extern servparm_t serv_presets; + +extern servparm_array servers; + +int read_config_file(const char *nm, globparm_t *global, servparm_array *servers, int includedepth, char **errstr); +int reload_config_file(const char *nm, char **errstr); +void free_zone(void *ptr); +void free_slist_domain(void *ptr); +void free_slist_array(slist_array sla); +void free_servparm(servparm_t *serv); + +int report_conf_stat(int f); +#endif diff --git a/jni/pdnsd/src/consts.c b/jni/pdnsd/src/consts.c new file mode 100644 index 00000000..c875a091 --- /dev/null +++ b/jni/pdnsd/src/consts.c @@ -0,0 +1,133 @@ +/* consts.c - Common config constants & handling + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2005, 2006, 2007, 2009 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include "consts.h" +#include "rr_types.h" + + +/* Order alphabetically!! */ +static const namevalue_t const_dic[]={ + {"auth", C_AUTH}, + {"default", C_DEFAULT}, + {"dev", C_DEV}, + {"diald", C_DIALD}, + {"discover", C_DISCOVER}, + {"domain", C_DOMAIN}, + {"excluded", C_EXCLUDED}, + {"exec", C_EXEC}, + {"fail", C_FAIL}, + {"false", C_OFF}, + {"fqdn_only", C_FQDN_ONLY}, + {"if", C_IF}, + {"included", C_INCLUDED}, + {"negate", C_NEGATE}, + {"no", C_OFF}, + {"none", C_NONE}, + {"off", C_OFF}, + {"on", C_ON}, + {"onquery", C_ONQUERY}, + {"ontimeout", C_ONTIMEOUT}, + {"ping", C_PING}, + {"query", C_QUERY}, + {"simple_only", C_SIMPLE_ONLY}, + {"tcp_only", TCP_ONLY}, + {"tcp_udp", TCP_UDP}, + {"true", C_ON}, + {"udp_only", UDP_ONLY}, + {"udp_tcp", UDP_TCP}, + {"yes", C_ON} +}; + +/* Added by Paul Rombouts */ +static const char *const const_names[]={ + "error", + "on", + "off", + "default", + "discover", + "none", + "if", + "exec", + "ping", + "query", + "onquery", + "ontimeout", + "udp_only", + "tcp_only", + "tcp_udp", + "udp_tcp", + "dev", + "diald", + "included", + "excluded", + "simple_only", + "fqdn_only", + "auth", + "domain", + "fail", + "negate" +}; + +/* compare two strings. + The first one is given as pointer to a char array of length len (which + should not contain any null chars), + the second one as a pointer to a null terminated char array. +*/ +inline static int keyncmp(const char *key1, int len, const char *key2) +{ + int cmp=strncmp(key1,key2,len); + if(cmp) return cmp; + return -(int)((unsigned char)(key2[len])); +} + +int binsearch_keyword(const char *name, int len, const namevalue_t dic[], int range) +{ + int i=0,j=range; + + while(i0) + i=k+1; + else + return dic[k].val; + } + + return 0; +} + + +int lookup_const(const char *name, int len) +{ + return binsearch_keyword(name,len,const_dic,sizeof(const_dic)/sizeof(namevalue_t)); +} + +/* Added by Paul Rombouts */ +const char *const_name(int c) +{ + return (c>=0 && c. +*/ + + +#ifndef CONSTS_H +#define CONSTS_H + +#include + +#define C_RRTOFFS 64 + +enum { + C_ERR, + C_ON, + C_OFF, + C_DEFAULT, + C_DISCOVER, + C_NONE, + C_IF, + C_EXEC, + C_PING, + C_QUERY, + C_ONQUERY, + C_ONTIMEOUT, + UDP_ONLY, + TCP_ONLY, + TCP_UDP, + UDP_TCP, + C_DEV, + C_DIALD, + C_INCLUDED, + C_EXCLUDED, + C_SIMPLE_ONLY, + C_FQDN_ONLY, + C_AUTH, + C_DOMAIN, + C_FAIL, + C_NEGATE +}; + +typedef struct { + const char *name; + int val; +} namevalue_t; + +int binsearch_keyword(const char *name, int len, const namevalue_t dic[], int range); +int lookup_const(const char *name, int len); +const char *const_name(int c); /* Added by Paul Rombouts */ + +#endif diff --git a/jni/pdnsd/src/debug.c b/jni/pdnsd/src/debug.c new file mode 100644 index 00000000..dd7f244d --- /dev/null +++ b/jni/pdnsd/src/debug.c @@ -0,0 +1,64 @@ +/* debug.c - Various debugging facilities + * Copyright (C) 2001 Thomas Moestl + * + * This file is part of the pdnsd package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 THE REGENTS OR CONTRIBUTORS 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. + */ + +#include +#include +#include +#include "helpers.h" +#include "error.h" + + +/* + * This is indeed very primitive (it does not track allocation failures + * and so on). It should be expanded some time. + */ +#ifdef ALLOC_DEBUG +void *DBGcalloc(size_t n, size_t sz, char *file, int line) +{ + DEBUG_MSG("+ calloc, %s:%d\n", file, line); + return calloc(n, sz); +} + +void *DBGmalloc(size_t sz, char *file, int line) +{ + DEBUG_MSG("+ malloc, %s:%d\n", file, line); + return malloc(sz); +} + +void *DBGrealloc(void *ptr, size_t sz, char *file, int line) +{ + if (ptr == NULL && sz != 0) + DEBUG_MSG("+ realloc, %s:%d\n", file, line); + if (ptr != NULL && sz == 0) + DEBUG_MSG("- realloc(0), %s:%d\n", file, line); + return realloc(ptr, sz); +} +void DBGfree(void *ptr, char *file, int line) +{ + DEBUG_MSG("- free, %s:%d\n", file, line); + free(ptr); +} +#endif diff --git a/jni/pdnsd/src/debug.h b/jni/pdnsd/src/debug.h new file mode 100644 index 00000000..02f0e5d4 --- /dev/null +++ b/jni/pdnsd/src/debug.h @@ -0,0 +1,52 @@ +/* debug.h - Various debugging facilities + * Copyright (C) 2001 Thomas Moestl + * + * This file is part of the pdnsd package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 THE REGENTS OR CONTRIBUTORS 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 DEBUG_H +#define DEBUG_H + +/* + * A hand-rolled alloc debug factility, because most available libraries have + * problems with at least one thread implementation. + */ +#ifdef ALLOC_DEBUG +void *DBGcalloc(size_t n, size_t sz, char *file, int line); +void *DBGmalloc(size_t sz, char *file, int line); +void *DBGrealloc(void *ptr, size_t sz, char *file, int line); +void DBGfree(void *ptr, char *file, int line); + +#define pdnsd_calloc(n,sz) DBGcalloc(n,sz,__FILE__,__LINE__) +#define pdnsd_malloc(sz) DBGmalloc(sz,__FILE__,__LINE__) +#define pdnsd_realloc(ptr,sz) DBGrealloc(ptr,sz,__FILE__,__LINE__) +#define pdnsd_free(ptr) DBGfree(ptr,__FILE__,__LINE__) +#else +#define pdnsd_calloc calloc +#define pdnsd_malloc malloc +#define pdnsd_realloc realloc +#define pdnsd_free free +#endif + +#endif /* def DEBUG_H */ diff --git a/jni/pdnsd/src/dns.c b/jni/pdnsd/src/dns.c new file mode 100644 index 00000000..a02d7fde --- /dev/null +++ b/jni/pdnsd/src/dns.c @@ -0,0 +1,617 @@ +/* dns.c - Declarations for dns handling and generic dns functions + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include "error.h" +#include "helpers.h" +#include "dns.h" + + +/* Decompress a name record, taking the whole message as msg, returning its results in tgt + * (which should be able hold at least DNSNAMEBUFSIZE chars), + * taking sz as the remaining msg size (it is returned decremented by the name length, ready for further use) and + * a source pointer (it is returned pointing to the location after the name). msgsize is the size of the whole message, + * len is the total name length. + * msg and msgsz are needed for decompression (see rfc1035). The returned data is decompressed, but still in the + * rr name form (length byte - string of that length, terminated by a 0 length byte). + * + * Returned is a dns return code, with one exception: RC_TRUNC, as defined in dns.h, indicates that the message is + * truncated at the name (which needs a special return code, as it might or might not be fatal). + */ +int decompress_name(unsigned char *msg, size_t msgsz, unsigned char **src, size_t *sz, unsigned char *tgt, unsigned int *len) +{ + unsigned int lb,offs; + unsigned int hops=0,tpos=0; + unsigned char *lptr=*src; + size_t oldsz=*sz; + size_t newsz=oldsz; + + if (newsz==0) + goto name_outside_data; + if (lptr-msg>=msgsz) + goto name_outside_msg; + + for(;;) { + newsz--; + lb=*lptr++; + + if(lb>0x3f) { + if (lb<0xc0) /* The two highest bits must be either 00 or 11 */ + goto unsupported_lbl_bits; + if (newsz==0) + goto name_outside_data; + if (lptr-msg>=msgsz) + goto name_outside_msg; + newsz--; + offs=((lb&0x3f)<<8)|(*lptr); + if (offs>=msgsz) + goto offset_outside_msg; + lptr=msg+offs; + goto jumped; + } + tgt[tpos++]=lb; + if (lb==0) + break; + + if (newsz<=lb) + goto name_outside_data; + if (lptr+lb-msg>=msgsz) + goto name_outside_msg; + if (tpos+lb>DNSNAMEBUFSIZE-1) /* terminating null byte has to follow */ + goto name_buf_full; + newsz -= lb; + do { + /* if (!*lptr || *lptr=='.') + return RC_FORMAT; */ + tgt[tpos++]=*lptr++; + } while(--lb); + } + goto return_OK; + + jumped: + ++hops; + for(;;) { + lb=*lptr++; + + while(lb>0x3f) { + if (lb<0xc0) /* The two highest bits must be either 00 or 11 */ + goto unsupported_lbl_bits; + if (lptr-msg>=msgsz) + goto name_outside_msg; + if (++hops>255) + goto too_many_hops; + offs=((lb&0x3f)<<8)|(*lptr); + if (offs>=msgsz) + goto offset_outside_msg; + lptr=msg+offs; + lb=*lptr++; + } + tgt[tpos++]=lb; + if (lb==0) + break; + + if (lptr+lb-msg>=msgsz) + goto name_outside_msg; + if(tpos+lb>DNSNAMEBUFSIZE-1) /* terminating null byte has to follow */ + goto name_buf_full; + do { + /* if (!*lptr || *lptr=='.') + return RC_FORMAT; */ + tgt[tpos++]=*lptr++; + } while(--lb); + } + return_OK: + *src += oldsz-newsz; + *sz = newsz; + if(len) *len=tpos; + return RC_OK; + + name_outside_data: + DEBUG_MSG("decompress_name: compressed name extends outside data field.\n"); + return RC_TRUNC; + + name_outside_msg: + DEBUG_MSG("decompress_name: compressed name extends outside message.\n"); + return RC_FORMAT; + + unsupported_lbl_bits: + DEBUG_MSG(lb==0x41?"decompress_name: Bit-string labels not supported.\n": + "decompress_name: unsupported label type.\n"); + return RC_FORMAT; + + offset_outside_msg: + DEBUG_MSG("decompress_name: offset points outside message.\n"); + return RC_FORMAT; + + name_buf_full: + DEBUG_MSG("decompress_name: decompressed name larger than %u bytes.\n", DNSNAMEBUFSIZE); + return RC_FORMAT; + + too_many_hops: + DEBUG_MSG("decompress_name: too many offsets in compressed name.\n"); + return RC_FORMAT; +} + +#if 0 +/* Compare two names (ordinary C-strings) back-to-forth and return the longest match. + The comparison is done at name granularity. + The return value is the length of the match in name elements. + *os (*od) is set to the offset in the domain name ms (md) of the match. + */ +int domain_name_match(const unsigned char *ms, const unsigned char *md, int *os, int *od) +{ + int i,j,k=0,offs,offd; + + offs=i=strlen(ms); offd=j=strlen(md); + if(i && ms[i-1]=='.') --offs; + if(j && md[j-1]=='.') --offd; + + if(i==0 || (i==1 && *ms=='.') || j==0 || (j==1 && *md=='.')) + /* Special case: root domain */ + ; + else { + --i; if(ms[i]=='.') --i; + --j; if(md[j]=='.') --j; + while(tolower(ms[i]) == tolower(md[j])) { + if(ms[i]=='.') { + ++k; + offs=i+1; offd=j+1; + } + if(i==0 || j==0) { + if((i==0 || ms[i-1]=='.') && (j==0 || md[j-1]=='.')) { + ++k; + offs=i; offd=j; + } + break; + } + --i; --j; + } + } + if(os) *os=offs; + if(od) *od=offd; + return k; +} +#endif + +/* Compare the names (in length byte-string notation) back-to-forth and return the longest match. + The comparison is done at name granularity. + The return value is the length of the match in name elements. + *os (*od) is set to the offset in the domain name ms (md) of the match. + */ +unsigned int domain_match(const unsigned char *ms, const unsigned char *md, unsigned int *os, unsigned int *od) +{ + unsigned int i,j,k,n,ns=0,nd=0,offs,offd; + unsigned char lb,ls[128],ld[128]; + + /* first collect all length bytes */ + i=0; + while((lb=ms[i])) { + PDNSD_ASSERT(ns<128, "domain_match: too many name segments"); + ls[ns++]=lb; + i += ((unsigned)lb)+1; + } + + j=0; + while((lb=md[j])) { + PDNSD_ASSERT(nd<128, "domain_match: too many name segments"); + ld[nd++]=lb; + j += ((unsigned)lb)+1; + } + + n=ns; if(n>nd) n=nd; + + for(k=1; offs=i,offd=j,k<=n; ++k) { + lb=ls[ns-k]; + if(lb!=ld[nd-k]) goto mismatch; + for(;lb;--lb) + if(tolower(ms[--i]) != tolower(md[--j])) goto mismatch; + --i; --j; + } + mismatch: + + if(os) *os=offs; + if(od) *od=offd; + return k-1; +} + +/* compress the domain name in in and put the result (of maximum length of rhnlen(in)) and + * fill cb with compression information for further strings.*cb may be NULL initially. + * offs is the offset the generated string will be placed in the packet. + * retval: 0 - error, otherwise length + * When done, just free() cb (if it is NULL, free will behave correctly). + * It is guaranteed (and insured by assertions) that the output is smaller or equal in + * size to the input. + */ +unsigned int compress_name(unsigned char *in, unsigned char *out, unsigned int offs, dlist *cb) +{ + compel_t *ci; + unsigned int longest=0,lrem=0,coffs=0; + unsigned int rl=0; + unsigned ilen = rhnlen(in); + unsigned short add=1; + + PDNSD_ASSERT(ilen<=DNSNAMEBUFSIZE, "compress_name: name too long"); + + /* part 1: compression */ + for (ci=dlist_first(*cb); ci; ci=dlist_next(ci)) { + unsigned int rv,rem,to; + if ((rv=domain_match(in, ci->s, &rem,&to))>longest) { + /* + * This has some not obvious implications that should be noted: If a + * domain name as saved in the list has been compressed, we only can + * index the non-compressed part. We rely here that the first occurence + * can't be compressed. So we take the first occurence of a given length. + * This works perfectly, but watch it if you change something. + */ + unsigned int newoffs= ci->index + to; + /* Only use if the offset is not too large. */ + if(newoffs<=0x3fff) { + longest=rv; + lrem=rem; + coffs= newoffs; + } + } + } + if (longest>0) { + PDNSD_ASSERT(lrem+2 <= ilen, "compress_name: length increased"); + memcpy(out, in,lrem); + out[lrem]=0xc0|((coffs&0x3f00)>>8); + out[lrem+1]=coffs&0xff; + rl=lrem+2; + add= lrem!=0; + } + else { + memcpy(out,in,ilen); + rl=ilen; + } + + /* part 2: addition to the cache structure */ + if (add) { + if (!(*cb=dlist_grow(*cb,sizeof(compel_t)+ilen))) + return 0; + ci=dlist_last(*cb); + ci->index=offs; + memcpy(ci->s,in,ilen); + } + return rl; +} + +/* Convert a numeric IP address into a domain name representation + (C string) suitable for PTR records. + buf is assumed to be at least DNSNAMEBUFSIZE bytes in size. +*/ +int a2ptrstr(pdnsd_ca *a, int tp, unsigned char *buf) +{ + if(tp==T_A) { + unsigned char *p=(unsigned char *)&a->ipv4.s_addr; + int n=snprintf(charp buf,DNSNAMEBUFSIZE,"%u.%u.%u.%u.in-addr.arpa.",p[3],p[2],p[1],p[0]); + if(n<0 || n>=DNSNAMEBUFSIZE) + return 0; + } + else +#if ALLOW_LOCAL_AAAA + if(tp==T_AAAA) { + unsigned char *p=(unsigned char *)&a->ipv6; + int i,offs=0; + for (i=15;i>=0;--i) { + unsigned char bt=p[i]; + int n=snprintf(charp(buf+offs), DNSNAMEBUFSIZE-offs,"%x.%x.",bt&0xf,(bt>>4)&0xf); + if(n<0) return 0; + offs+=n; + if(offs>=DNSNAMEBUFSIZE) return 0; + } + if(!strncp(charp(buf+offs),"ip6.arpa.",DNSNAMEBUFSIZE-offs)) + return 0; + } + else +#endif + return 0; + return 1; +} + +/* + * Add records for a host as read from a hosts-style file. + * Returns 1 on success, 0 in an out of memory condition, and -1 when there was a problem with + * the record data. + */ +static int add_host(unsigned char *pn, unsigned char *rns, pdnsd_ca *a, int tp, int a_sz, time_t ttl, unsigned flags, int reverse) +{ + dns_cent_t ce; + + if (!init_cent(&ce, pn, 0, 0, flags DBG0)) + return 0; + if (!add_cent_rr(&ce,tp,ttl,0,CF_LOCAL,a_sz,a DBG0)) + goto free_cent_return0; + if (!add_cent_rr(&ce,T_NS,ttl,0,CF_LOCAL,rhnlen(rns),rns DBG0)) + goto free_cent_return0; + add_cache(&ce); + free_cent(&ce DBG0); + if (reverse) { + unsigned char b2[DNSNAMEBUFSIZE],rhn[DNSNAMEBUFSIZE]; + if(!a2ptrstr(a,tp,b2)) + return -1; + if (!str2rhn(b2,rhn)) + return -1; + if (!init_cent(&ce, rhn, 0, 0, flags DBG0)) + return 0; + if (!add_cent_rr(&ce,T_PTR,ttl,0,CF_LOCAL,rhnlen(pn),pn DBG0)) + goto free_cent_return0; + if (!add_cent_rr(&ce,T_NS,ttl,0,CF_LOCAL,rhnlen(rns),rns DBG0)) + goto free_cent_return0; + add_cache(&ce); + free_cent(&ce DBG0); + } + return 1; + + free_cent_return0: + free_cent(&ce DBG0); + return 0; +} + +/* + * Read a file in /etc/hosts-format and add generate rrs for it. + * Errors are largely ignored so that we can skip entries we do not understand + * (but others possibly do). + */ +int read_hosts(const char *fn, unsigned char *rns, time_t ttl, unsigned flags, int aliases, char **errstr) +{ + int rv=0; + FILE *f; + char *buf; + size_t buflen=256; + + if (!(f=fopen(fn,"r"))) { + if(asprintf(errstr, "Failed to source %s: %s", fn, strerror(errno))<0) *errstr=NULL; + return 0; + } + buf=malloc(buflen); + if(!buf) { + *errstr=NULL; + goto fclose_return; + } + while(getline(&buf,&buflen,f)>=0) { + unsigned int len; + unsigned char *p,*pn,*pi; + unsigned char rhn[DNSNAMEBUFSIZE]; + int tp,sz; + pdnsd_ca a; + + p= ucharp strchr(buf,'#'); + if(p) *p=0; + p= ucharp buf; + for(;;) { + if(!*p) goto nextline; + if(!isspace(*p)) break; + ++p; + } + pi=p; + do { + if(!*++p) goto nextline; + } while(!isspace(*p)); + *p=0; + do { + if(!*++p) goto nextline; + } while (isspace(*p)); + pn=p; + do { + ++p; + } while(*p && !isspace(*p)); + len=p-pn; + if (parsestr2rhn(pn,len,rhn)!=NULL) + continue; + if (inet_aton(charp pi,&a.ipv4)) { + tp=T_A; + sz=sizeof(struct in_addr); + } else { +#if ALLOW_LOCAL_AAAA /* We don't read them otherwise, as the C library may not be able to to that.*/ + if (inet_pton(AF_INET6,charp pi,&a.ipv6)>0) { + tp=T_AAAA; + sz=sizeof(struct in6_addr); + } else +#endif + continue; + } + { + int res=add_host(rhn, rns, &a, tp,sz, ttl, flags, 1); + if(res==0) { + *errstr= NULL; + goto cleanup_return; + } + else if(res<0) + continue; + } + if(aliases) { + for(;;) { + for(;;) { + if(!*p) goto nextline; + if(!isspace(*p)) break; + ++p; + } + pn=p; + do { + ++p; + } while(*p && !isspace(*p)); + len=p-pn; + if (parsestr2rhn(pn,len,rhn)!=NULL) + break; + if (add_host(rhn, rns, &a, tp,sz, ttl, flags, 0) == 0) { + *errstr= NULL; + goto cleanup_return; + } + } + } + nextline:; + } + if (feof(f)) + rv=1; + else if(asprintf(errstr, "Failed to source %s: %s", fn, strerror(errno))<0) *errstr=NULL; + cleanup_return: + free(buf); + fclose_return: + fclose(f); + return rv; +} + + +/* Get the name of an RR type given its value. */ +const char *getrrtpname(int tp) +{ + return tp>=T_MIN && tp<=T_MAX? rrnames[tp-T_MIN]: "[unknown]"; +} + +#if DEBUG>0 +/* + * Const decoders for debugging display + */ +static const char *const c_names[C_NUM] = {"IN","CS","CH","HS"}; +static const char *const qt_names[QT_NUM]={"IXFR","AXFR","MAILB","MAILA","*"}; + +const char *get_cname(int id) +{ + if (id>=C_MIN && id<=C_MAX) + return c_names[id-C_MIN]; + if (id==QC_ALL) + return "*"; + return "[unknown]"; +} + +const char *get_tname(int id) +{ + if (id>=T_MIN && id<=T_MAX) + return rrnames[id-T_MIN]; + else if (id>=QT_MIN && id<=QT_MAX) + return qt_names[id-QT_MIN]; + return "[unknown]"; +} + + +#define NRC 17 +static const char *const e_names[NRC]={ + "no error", + "query format error", + "server failed", + "non-existent domain", + "not supported", + "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", + "name not contained in zone", + "11", + "12", + "13", + "14", + "15", + "bad OPT version" +}; + +const char *get_ename(int id) +{ + if (id>=0 && idaa) + p=mempcpy(p, " AA", 3); + if (hdr->tc) + p=mempcpy(p, " TC", 3); + if (hdr->rd) + p=mempcpy(p, " RD", 3); + if (hdr->ra) + p=mempcpy(p, " RA", 3); + if (hdr->z) + p=mempcpy(p, " Z", 2); + if (hdr->ad) + p=mempcpy(p, " AD", 3); + if (hdr->cd) + p=mempcpy(p, " CD", 3); + *p=0; + + return buf; +} + +#endif + + +#if DEBUG>=9 +/* Based on debug code contributed by Kiyo Kelvin Lee. */ + +void debug_dump_dns_msg(void *data, size_t len) +{ + unsigned char *udata = (unsigned char *)data; +# define dmpchksz 16 + char buf[dmpchksz*4+2]; + size_t i, j, k, l; + + DEBUG_MSG("pointer=%p len=%lu\n", udata, (unsigned long)len); + + for (i = 0; i < len; i += dmpchksz) { + char *cp = buf; + k = l = i + dmpchksz; + if(k > len) k = len; + for (j = i; j < k; ++j) { + int n = sprintf(cp, "%02x ", udata[j]); + cp += n; + } + for (; j < l; ++j) { + *cp++ = ' '; + *cp++ = ' '; + *cp++ = ' '; + } + *cp++ = ' '; + for (j = i; j < k; ++j) { + *cp++ = isprint(udata[j]) ? udata[j] : '.'; + } + PDNSD_ASSERT(cp < buf + sizeof(buf), "debug_dump_dns_msg: line buffer overflowed"); + *cp = '\0'; + DEBUG_MSG("%s\n", buf); + } + + if(len >= sizeof(dns_hdr_t)) { + dns_hdr_t *hdr = (dns_hdr_t *)data; + + DEBUG_MSG( + "id=%04x qr=%x opcode=%x aa=%x tc=%x rd=%x " + "ra=%x z=%x ad=%x cd=%x rcode=%x\n", + ntohs(hdr->id), hdr->qr, hdr->opcode, hdr->aa, hdr->tc, hdr->rd, + hdr->ra, hdr->z, hdr->ad, hdr->cd, hdr->rcode); + DEBUG_MSG( + "qdcount=%04x ancount=%04x nscount=%04x arcount=%04x\n", + ntohs(hdr->qdcount), ntohs(hdr->ancount), ntohs(hdr->nscount), ntohs(hdr->arcount)); + } +} +#endif diff --git a/jni/pdnsd/src/dns.h b/jni/pdnsd/src/dns.h new file mode 100644 index 00000000..0f6a4ac1 --- /dev/null +++ b/jni/pdnsd/src/dns.h @@ -0,0 +1,309 @@ +/* dns.h - Declarations for dns handling and generic dns functions + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef DNS_H +#define DNS_H + +#include +#include +#include +#include +#include +#include +#include "rr_types.h" +#include "list.h" +#include "ipvers.h" + +#if (TARGET==TARGET_BSD) +# if !defined(__BIG_ENDIAN) +# if defined(BIG_ENDIAN) +# define __BIG_ENDIAN BIG_ENDIAN +# elif defined(_BIG_ENDIAN) +# define __BIG_ENDIAN _BIG_ENDIAN +# endif +# endif +# if !defined(__LITTLE_ENDIAN) +# if defined(LITTLE_ENDIAN) +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# elif defined(_LITTLE_ENDIAN) +# define __LITTLE_ENDIAN _LITTLE_ENDIAN +# endif +# endif +# if !defined(__BYTE_ORDER) +# if defined(BYTE_ORDER) +# define __BYTE_ORDER BYTE_ORDER +# elif defined(_BYTE_ORDER) +# define __BYTE_ORDER _BYTE_ORDER +# endif +# endif +#endif + +/* Deal with byte orders */ +#ifndef __BYTE_ORDER +# if defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) +# error Fuzzy endianness system! Both __LITTLE_ENDIAN and __BIG_ENDIAN have been defined! +# endif +# if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) +# error Strange Endianness-less system! Neither __LITTLE_ENDIAN nor __BIG_ENDIAN has been defined! +# endif +# if defined(__LITTLE_ENDIAN) +# define __BYTE_ORDER __LITTLE_ENDIAN +# elif defined(__BIG_ENDIAN) +# define __BYTE_ORDER __BIG_ENDIAN +# endif +#endif + +/* special rr type codes for queries */ +#define QT_MIN 251 +#define QT_IXFR 251 +#define QT_AXFR 252 +#define QT_MAILB 253 +#define QT_MAILA 254 +#define QT_ALL 255 +#define QT_MAX 255 +#define QT_NUM 5 + +/* rr classes */ +#define C_MIN 1 +#define C_IN 1 +#define C_CS 2 +#define C_CH 3 +#define C_HS 4 +#define C_MAX 4 +#define C_NUM 4 + +/* special classes for queries */ +#define QC_ALL 255 + +/* status codes */ +#define RC_OK 0 +#define RC_FORMAT 1 +#define RC_SERVFAIL 2 +#define RC_NAMEERR 3 +#define RC_NOTSUPP 4 +#define RC_REFUSED 5 +#define RC_BADVERS 16 + +/* + * special internal retvals + */ +#define RC_NOTCACHED 0xfffa +#define RC_CACHED 0xfffb +#define RC_STALE 0xfffc +#define RC_TCPREFUSED 0xfffd +#define RC_TRUNC 0xfffe +#define RC_FATALERR 0xffff + +/* query/response */ +#define QR_QUERY 0 +#define QR_RESP 1 + +/*opcodes */ +#define OP_QUERY 0 +#define OP_IQUERY 1 +#define OP_STATUS 2 + +#if 0 +typedef struct { + /* the name is the first field. It has variable length, so it can't be put in the struct */ + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t rdlength; + /* rdata follows */ +} __attribute__((packed)) rr_hdr_t; + +#define sizeof_rr_hdr_t (sizeof rr_hdr_t) +#else + +/* We will not actually use the rr_hdr_t type, only its size: + sizeof(rr_hdr_t) = 2 + 2 + 4 + 2 */ +#define sizeof_rr_hdr_t 10 +#endif + +#define sizeof_opt_pseudo_rr (1+sizeof_rr_hdr_t) + +#if 0 +typedef struct { + /* The server name and maintainer mailbox are the first two fields. It has variable length, */ + /* so they can't be put in the struct */ + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; +} __attribute__((packed)) soa_r_t; + + +typedef struct { +/* char qname[];*/ + uint16_t qtype; + uint16_t qclass; +} __attribute__((packed)) std_query_t; +#endif + + +typedef struct { + uint16_t id; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int rd:1; + unsigned int tc:1; + unsigned int aa:1; + unsigned int opcode:4; + unsigned int qr:1; + unsigned int rcode:4; + unsigned int cd:1; + unsigned int ad:1; + unsigned int z :1; + unsigned int ra:1; +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int qr:1; + unsigned int opcode:4; + unsigned int aa:1; + unsigned int tc:1; + unsigned int rd:1; + unsigned int ra:1; + unsigned int z :1; + unsigned int ad:1; + unsigned int cd:1; + unsigned int rcode:4; +#else +# error "Please define __BYTE_ORDER to be __LITTLE_ENDIAN or __BIG_ENDIAN" +#endif + uint16_t qdcount; + uint16_t ancount; + uint16_t nscount; + uint16_t arcount; +} __attribute__((packed)) dns_hdr_t; + + +/* A structure that can also be used for DNS messages over TCP. */ +typedef struct { +#ifndef NO_TCP_QUERIES + uint16_t len; +#endif + dns_hdr_t hdr; +} __attribute__((packed)) dns_msg_t; + +#ifdef NO_TCP_QUERIES +# define dnsmsghdroffset 0 +#else +# define dnsmsghdroffset 2 +#endif + + +/* Structure for storing EDNS (Extension mechanisms for DNS) information. */ +typedef struct { + unsigned short udpsize; + unsigned short rcode; + unsigned short version; + unsigned char do_flg; +} edns_info_t; + + +/* Macros to retrieve or store integer data that is not necessarily aligned. + Also takes care of network to host byte order. + The pointer cp is advanced and should be of type void* or char*. + These are actually adapted versions of the NS_GET16 and NS_GET32 + macros in the arpa/nameser.h include file in the BIND 9 source. +*/ + +#define GETINT16(s,cp) do { \ + register uint16_t t_s; \ + register const unsigned char *t_cp = (const unsigned char *)(cp); \ + t_s = (uint16_t)*t_cp++ << 8; \ + t_s |= (uint16_t)*t_cp++; \ + (s) = t_s; \ + (cp) = (void *)t_cp; \ +} while (0) + +#define GETINT32(l,cp) do { \ + register uint32_t t_l; \ + register const unsigned char *t_cp = (const unsigned char *)(cp); \ + t_l = (uint32_t)*t_cp++ << 24; \ + t_l |= (uint32_t)*t_cp++ << 16; \ + t_l |= (uint32_t)*t_cp++ << 8; \ + t_l |= (uint32_t)*t_cp++; \ + (l) = t_l; \ + (cp) = (void *)t_cp; \ +} while (0) + +#define PUTINT16(s,cp) do { \ + register uint16_t t_s = (uint16_t)(s); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp++ = t_s; \ + (cp) = (void *)t_cp; \ +} while (0) + +#define PUTINT32(l,cp) do { \ + register uint32_t t_l = (uint32_t)(l); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp++ = t_l; \ + (cp) = (void *)t_cp; \ +} while (0) + + +/* Size (number of bytes) of buffers used to hold domain names. */ +#define DNSNAMEBUFSIZE 256 + +/* Recursion depth. */ +#define MAX_HOPS 20 + +/* + * Types for compression buffers. + */ +typedef struct { + unsigned int index; + unsigned char s[0]; +} compel_t; + + + +int decompress_name(unsigned char *msg, size_t msgsz, unsigned char **src, size_t *sz, unsigned char *tgt, unsigned int *len); +/* int domain_name_match(const unsigned char *ms, const unsigned char *md, int *os, int *od); */ +unsigned int domain_match(const unsigned char *ms, const unsigned char *md, unsigned int *os, unsigned int *od); +unsigned int compress_name(unsigned char *in, unsigned char *out, unsigned int offs, dlist *cb); +int a2ptrstr(pdnsd_ca *a, int tp, unsigned char *buf); +int read_hosts(const char *fn, unsigned char *rns, time_t ttl, unsigned flags, int aliases, char **errstr); + +const char *getrrtpname(int tp); +#if DEBUG>0 +const char *get_cname(int id); +const char *get_tname(int id); +const char *get_ename(int id); +#define DNSFLAGSMAXSTRSIZE (7*3+1) +char *dnsflags2str(dns_hdr_t *hdr, char *buf); +#endif + +#if DEBUG>=9 +void debug_dump_dns_msg(void *data, size_t len); +#define DEBUG_DUMP_DNS_MSG(d,l) {if(debug_p && global.verbosity>=9) debug_dump_dns_msg(d,l);} +#else +#define DEBUG_DUMP_DNS_MSG(d,l) +#endif + +#endif diff --git a/jni/pdnsd/src/dns_answer.c b/jni/pdnsd/src/dns_answer.c new file mode 100644 index 00000000..6a2a5b50 --- /dev/null +++ b/jni/pdnsd/src/dns_answer.c @@ -0,0 +1,2170 @@ +/* dns_answer.c - Receive and process incoming dns queries. + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +/* + * STANDARD CONFORMITY + * + * There are several standard conformity issues noted in the comments. + * Some additional comments: + * + * I always set RA but I ignore RD largely (in everything but CNAME recursion), + * not because it is not supported, but because I _always_ do a recursive + * resolve in order to be able to cache the results. + */ + +#include +#include "ipvers.h" +#include +#include +#include +#ifdef HAVE_SYS_POLL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thread.h" +#include "list.h" +#include "dns.h" +#include "dns_answer.h" +#include "dns_query.h" +#include "helpers.h" +#include "cache.h" +#include "error.h" +#include "debug.h" + + +/* + * This is for error handling to prevent spewing the log files. + * Maximums of different message types are set. + * Races do not really matter here, so no locks. + */ +#define TCP_MAX_ERRS 10 +#define UDP_MAX_ERRS 10 +#define MEM_MAX_ERRS 10 +#define THRD_MAX_ERRS 10 +#define MISC_MAX_ERRS 10 +static volatile unsigned long da_tcp_errs=0; +static volatile unsigned long da_udp_errs=0; +static volatile unsigned long da_mem_errs=0; +static volatile unsigned long da_thrd_errs=0; +#if DEBUG>0 +static volatile unsigned long da_misc_errs=0; +#endif +static volatile int procs=0; /* active query processes */ +static volatile int qprocs=0; /* queued query processes */ +static volatile unsigned long dropped=0,spawned=0; +static volatile unsigned thrid_cnt=0; +static pthread_mutex_t proc_lock = PTHREAD_MUTEX_INITIALIZER; + +#ifdef SOCKET_LOCKING +static pthread_mutex_t s_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +typedef union { +#ifdef ENABLE_IPV4 +# if (TARGET==TARGET_LINUX) + struct in_pktinfo pi4; +# else + struct in_addr ai4; +# endif +#endif +#ifdef ENABLE_IPV6 + struct in6_pktinfo pi6; +#endif +} pkt_info_t; + + +typedef struct { + union { +#ifdef ENABLE_IPV4 + struct sockaddr_in sin4; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sin6; +#endif + } addr; + + pkt_info_t pi; + + int sock; + int proto; + size_t len; + unsigned char buf[0]; /* Actual size determined by global.udpbufsize */ +} udp_buf_t; + + +/* ALLOCINITIALSIZE should be at least sizeof(dns_msg_t) = 2+12 */ +#define ALLOCINITIALSIZE 256 +/* This mask corresponds to a chunk size of 128 bytes. */ +#define ALLOCCHUNKSIZEMASK ((size_t)0x7f) + +typedef struct { + unsigned short qtype; + unsigned short qclass; + unsigned char query[0]; +} dns_queryel_t; + + +#define S_ANSWER 1 +#define S_AUTHORITY 2 +#define S_ADDITIONAL 3 + +typedef struct { + unsigned short tp,dlen; + unsigned char nm[0]; + /* unsigned char data[0]; */ +} sva_t; + + +/* + * Mark an additional record as added to avoid double records. + */ +static int sva_add(dlist *sva, const unsigned char *rhn, unsigned short tp, unsigned short dlen, void* data) +{ + if (sva) { + size_t rlen=rhnlen(rhn); + sva_t *st; + if (!(*sva=dlist_grow(*sva,sizeof(sva_t)+rlen+dlen))) { + return 0; + } + st=dlist_last(*sva); + st->tp=tp; + st->dlen=dlen; + memcpy(mempcpy(st->nm,rhn,rlen),data,dlen); + } + return 1; +} + +/* ans_ttl computes the ttl value to return to the client. + This is the ttl value stored in the cache entry minus the time + the cache entry has lived in the cache. + Local cache entries are an exception, they never "age". +*/ +inline static time_t ans_ttl(rr_set_t *rrset, time_t queryts) +{ + time_t ttl= rrset->ttl; + + if (!(rrset->flags&CF_LOCAL)) { + time_t tpassed= queryts - rrset->ts; + if(tpassed<0) tpassed=0; + ttl -= tpassed; + if(ttl<0) ttl=0; + } + return ttl; +} + +/* follow_cname_chain takes a cache entry and a buffer (must be at least DNSNAMEBUFSIZE bytes), + and copies the name indicated by the first cname record in the cache entry. + The name is returned in length-byte string notation. + follow_cname_chain returns 1 if a cname record is found, otherwise 0. +*/ +inline static int follow_cname_chain(dns_cent_t *c, unsigned char *name) +{ + rr_set_t *rrset=getrrset_CNAME(c); + rr_bucket_t *rr; + if (!rrset || !(rr=rrset->rrs)) + return 0; + PDNSD_ASSERT(rr->rdlen <= DNSNAMEBUFSIZE, "follow_cname_chain: record too long"); + memcpy(name,rr->data,rr->rdlen); + return 1; +} + + +/* + * Add data from a rr_bucket_t (as in cache) into a dns message in ans. Ans is grown + * to fit, sz is the old size of the packet (it is modified so at the end of the procedure + * it is the new size), type is the rr type and ltime is the time in seconds the record is + * old. + * cb is the buffer used for message compression. *cb should be NULL when you call compress_name + * or add_to_response the first time. + * It gets filled with a pointer to compression information that can be reused in subsequent calls + * to add_to_response. + * sect is the section (S_ANSWER, S_AUTHORITY or S_ADDITIONAL) in which the record + * belongs logically. Note that you still have to add the rrs in the right order (answer rrs first, + * then authority and last additional). + */ +static int add_rr(dns_msg_t **ans, size_t *sz, size_t *allocsz, + unsigned char *rrn, unsigned short type, uint32_t ttl, + unsigned int dlen, void *data, char section, unsigned *udp, dlist *cb) +{ + size_t osz= *sz; + unsigned int ilen,blen,rdlen; + unsigned char *rrht; + + { + unsigned int nlen; + unsigned char nbuf[DNSNAMEBUFSIZE]; + + if (!(nlen=compress_name(rrn,nbuf,*sz,cb))) + return 0; + + /* This buffer is usually over-allocated due to compression. + Never mind, just a few bytes, and the buffer is freed soon. */ + { + size_t newsz= dnsmsghdroffset + *sz + nlen + sizeof_rr_hdr_t + dlen; + if(newsz > *allocsz) { + /* Need to allocate more space. + To avoid frequent reallocs, we allocate + a multiple of a certain chunk size. */ + size_t newallocsz= (newsz+ALLOCCHUNKSIZEMASK)&(~ALLOCCHUNKSIZEMASK); + dns_msg_t *newans=(dns_msg_t *)pdnsd_realloc(*ans,newallocsz); + if (!newans) + return 0; + *ans=newans; + *allocsz=newallocsz; + } + } + memcpy((unsigned char *)(&(*ans)->hdr)+ *sz, nbuf, nlen); + *sz += nlen; + } + + /* the rr header will be filled in later. Just reserve some space for it. */ + rrht= ((unsigned char *)(&(*ans)->hdr)) + *sz; + *sz += sizeof_rr_hdr_t; + + switch (type) { + case T_CNAME: + case T_MB: + case T_MD: + case T_MF: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + if (!(rdlen=compress_name(((unsigned char *)data), ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + PDNSD_ASSERT(rdlen <= dlen, "T_CNAME/T_MB/...: got longer"); + *sz+=rdlen; + break; +#if IS_CACHED_MINFO || IS_CACHED_RP +#if IS_CACHED_MINFO + case T_MINFO: +#endif +#if IS_CACHED_RP + case T_RP: +#endif + if (!(rdlen=compress_name(((unsigned char *)data), ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + *sz+=rdlen; + ilen=rhnlen((unsigned char *)data); + PDNSD_ASSERT(rdlen <= ilen, "T_MINFO/T_RP: got longer"); + if (!(blen=compress_name(((unsigned char *)data)+ilen, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen+=blen; + PDNSD_ASSERT(rdlen <= dlen, "T_MINFO/T_RP: got longer"); + *sz+=blen; + break; +#endif + case T_MX: +#if IS_CACHED_AFSDB + case T_AFSDB: +#endif +#if IS_CACHED_RT + case T_RT: +#endif +#if IS_CACHED_KX + case T_KX: +#endif + PDNSD_ASSERT(dlen > 2, "T_MX/T_AFSDB/...: rr botch"); + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),(unsigned char *)data,2); + *sz+=2; + if (!(blen=compress_name(((unsigned char *)data)+2, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen=2+blen; + PDNSD_ASSERT(rdlen <= dlen, "T_MX/T_AFSDB/...: got longer"); + *sz+=blen; + break; + case T_SOA: + if (!(rdlen=compress_name(((unsigned char *)data), ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + *sz+=rdlen; + ilen=rhnlen((unsigned char *)data); + PDNSD_ASSERT(rdlen <= ilen, "T_SOA: got longer"); + if (!(blen=compress_name(((unsigned char *)data)+ilen, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen+=blen; + *sz+=blen; + ilen+=rhnlen(((unsigned char *)data)+ilen); + PDNSD_ASSERT(rdlen <= ilen, "T_SOA: got longer"); + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),((unsigned char *)data)+ilen,20); + rdlen+=20; + PDNSD_ASSERT(rdlen <= dlen, "T_SOA: rr botch"); + *sz+=20; + break; +#if IS_CACHED_PX + case T_PX: + PDNSD_ASSERT(dlen > 2, "T_PX: rr botch"); + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),(unsigned char *)data,2); + *sz+=2; + ilen=2; + if (!(blen=compress_name(((unsigned char *)data)+ilen, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen=2+blen; + *sz+=blen; + ilen+=rhnlen(((unsigned char *)data)+ilen); + PDNSD_ASSERT(rdlen <= ilen, "T_PX: got longer"); + if (!(blen=compress_name(((unsigned char *)data)+ilen, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen+=blen; + PDNSD_ASSERT(rdlen <= dlen, "T_PX: got longer"); + *sz+=blen; + break; +#endif +#if IS_CACHED_SRV + case T_SRV: + PDNSD_ASSERT(dlen > 6, "T_SRV: rr botch"); + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),(unsigned char *)data,6); + *sz+=6; + if (!(blen=compress_name(((unsigned char *)data)+6, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen=6+blen; + PDNSD_ASSERT(rdlen <= dlen, "T_SRV: got longer"); + *sz+=blen; + break; +#endif +#if IS_CACHED_NXT + case T_NXT: + if (!(blen=compress_name(((unsigned char *)data), ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen=blen; + *sz+=blen; + ilen=rhnlen((unsigned char *)data); + PDNSD_ASSERT(rdlen <= ilen, "T_NXT: got longer"); + PDNSD_ASSERT(dlen >= ilen, "T_NXT: rr botch"); + if (dlen > ilen) { + unsigned int wlen = dlen - ilen; + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),((unsigned char *)data)+ilen,wlen); + *sz+=wlen; + rdlen+=wlen; + } + break; +#endif +#if IS_CACHED_NAPTR + case T_NAPTR: + PDNSD_ASSERT(dlen > 4, "T_NAPTR: rr botch"); + ilen=4; + { + int j; + for (j=0;j<3;j++) { + ilen += ((unsigned)*(((unsigned char *)data)+ilen)) + 1; + PDNSD_ASSERT(dlen > ilen, "T_NAPTR: rr botch 2"); + } + } + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),((unsigned char *)data),ilen); + (*sz)+=ilen; + + if (!(blen=compress_name(((unsigned char *)data)+ilen, ((unsigned char *)(&(*ans)->hdr))+(*sz),*sz,cb))) + return 0; + rdlen=ilen+blen; + PDNSD_ASSERT(rdlen <= dlen, "T_NAPTR: got longer"); + *sz+=blen; + break; +#endif + default: + memcpy(((unsigned char *)(&(*ans)->hdr))+(*sz),((unsigned char *)data),dlen); + rdlen=dlen; + *sz+=dlen; + } + + if (udp && *sz>*udp && section==S_ADDITIONAL) /* only add the record if we do not increase the length over 512 */ + *sz=osz; /* (or possibly more if the request used EDNS) in additionals for udp answer. */ + else { + PUTINT16(type,rrht); + PUTINT16(C_IN,rrht); + PUTINT32(ttl,rrht); + PUTINT16(rdlen,rrht); + + switch (section) { + case S_ANSWER: + (*ans)->hdr.ancount=htons(ntohs((*ans)->hdr.ancount)+1); + break; + case S_AUTHORITY: + (*ans)->hdr.nscount=htons(ntohs((*ans)->hdr.nscount)+1); + break; + case S_ADDITIONAL: + (*ans)->hdr.arcount=htons(ntohs((*ans)->hdr.arcount)+1); + break; + } + } + + return 1; +} + +/* Add an OPT pseudo RR containing EDNS info. + Can only be added to the additional section! +*/ +int add_opt_pseudo_rr(dns_msg_t **ans, size_t *sz, size_t *allocsz, + unsigned short udpsize, unsigned short rcode, + unsigned short ednsver, unsigned short Zflags) +{ + unsigned char *ptr; + size_t newsz= dnsmsghdroffset + *sz + sizeof_opt_pseudo_rr; + if(newsz > *allocsz) { + /* Need to allocate more space. + To avoid frequent reallocs, we allocate + a multiple of a certain chunk size. */ + size_t newallocsz= (newsz+ALLOCCHUNKSIZEMASK)&(~ALLOCCHUNKSIZEMASK); + dns_msg_t *newans=(dns_msg_t *)pdnsd_realloc(*ans,newallocsz); + if (!newans) + return 0; + *ans=newans; + *allocsz=newallocsz; + } + + ptr= ((unsigned char *)(&(*ans)->hdr)) + *sz; + *ptr++ = 0; /* Empty name */ + PUTINT16(T_OPT,ptr); /* type field */ + PUTINT16(udpsize,ptr); /* class field */ + *ptr++ = rcode>>4; /* 4 byte TTL field */ + *ptr++ = ednsver; + PUTINT16(Zflags,ptr); + PUTINT16(0,ptr); /* rdlen field */ + /* Empty RDATA. */ + + *sz += sizeof_opt_pseudo_rr; + /* Increment arcount field in dns header. */ + (*ans)->hdr.arcount = htons(ntohs((*ans)->hdr.arcount)+1); + return 1; +} + +/* Remove the last entry in the additional section, + assuming it is an OPT pseudo RR of fixed size. + Returns the new message size if successful, or + zero if an inconsistency is detected. +*/ +size_t remove_opt_pseudo_rr(dns_msg_t *ans, size_t sz) +{ + uint16_t acnt=ntohs(ans->hdr.arcount), type; + unsigned char *ptr; + /* First do some sanity checks. */ + if(!(acnt>0 && sz >= sizeof(dns_hdr_t)+sizeof_opt_pseudo_rr)) + return 0; + sz -= sizeof_opt_pseudo_rr; + ptr= ((unsigned char *)(&ans->hdr)) + sz; + if(*ptr++) + return 0; /* Name must be empty. */ + GETINT16(type,ptr); + if(type!=T_OPT) + return 0; /* RR type must be OPT. */ + /* Decrement arcount field in dns header. */ + ans->hdr.arcount = htons(acnt-1); + return sz; +} + +typedef struct rre_s { + unsigned short tp; + unsigned short tsz; /* Size of tnm field */ + uint32_t ttl; /* ttl of the record in the answer (if tp==T_NS or T_SOA) */ + unsigned char tnm[0]; /* Name for the domain a record refers to */ + /* unsigned char nm[0]; */ /* Name of the domain the record is for (if tp==T_NS or T_SOA) */ +} rr_ext_t; + + +/* types for the tp field */ +/* #define RRETP_NS T_NS */ /* For name server: add to authority, add address to additional. */ +/* #define RRETP_SOA T_SOA */ /* For SOA record: add to authority. */ +#define RRETP_ADD 0 /* For other records: add the address of buf to additional */ + +static int add_ar(dlist *ar,unsigned short tp, unsigned short tsz,void *tnm,unsigned char *nm, uint32_t ttl) +{ + rr_ext_t *re; + unsigned char *p; + size_t nmsz=0,size=sizeof(rr_ext_t)+tsz; + if(tp==T_NS || tp==T_SOA) { + nmsz=rhnlen(nm); + size += nmsz; + } + if (!(*ar=dlist_grow(*ar,size))) + return 0; + re=dlist_last(*ar); + re->tp=tp; + re->tsz=tsz; + re->ttl=ttl; + p=mempcpy(re->tnm,tnm,tsz); + if(tp==T_NS || tp==T_SOA) { + memcpy(p,nm,nmsz); + } + return 1; +} + + +/* Select a random rr record from a list. */ +inline static rr_bucket_t *randrr(rr_bucket_t *rrb) +{ + rr_bucket_t *rr; + unsigned cnt=0; + + /* In order to have an equal chance for each record to be selected, we have to count first. */ + for(rr=rrb; rr; rr=rr->next) ++cnt; + + /* We do not use the pdnsd random functions (these might use /dev/urandom if the user is paranoid, + * and we do not need any good PRNG here). */ + if(cnt) for(cnt=random()%cnt; cnt; --cnt) rrb=rrb->next; + + return rrb; +} + +#if IS_CACHED_SRV +#define AR_NUM 6 +#else +#define AR_NUM 5 +#endif +static const int ar_recs[AR_NUM]={T_NS, T_MD, T_MF, T_MB, T_MX +#if IS_CACHED_SRV + ,T_SRV +#endif +}; +/* offsets from record data start to server name */ +static const int ar_offs[AR_NUM]={0,0,0,0,2 +#if IS_CACHED_SRV + ,6 +#endif +}; + +/* This adds an rrset, optionally randomizing the first element it adds. + * if that is done, all rrs after the randomized one appear in order, starting from + * that one and wrapping over if needed. */ +static int add_rrset(dns_msg_t **ans, size_t *sz, size_t *allocsz, + unsigned char *rrn, unsigned tp, time_t queryts, + dns_cent_t *cached, unsigned *udp, dlist *cb, dlist *sva, dlist *ar) +{ + rr_set_t *crrset=getrrset(cached,tp); + + if (crrset && crrset->rrs) { + rr_bucket_t *b; + rr_bucket_t *first=NULL; /* Initialized to inhibit compiler warning */ + int i; + short rnd_recs=global.rnd_recs; + + b=crrset->rrs; + if (rnd_recs) b=first=randrr(crrset->rrs); + + while (b) { + if (!add_rr(ans, sz, allocsz, rrn, tp, ans_ttl(crrset,queryts), + b->rdlen, b->data, S_ANSWER, udp, cb)) + return 0; + if (tp==T_NS || tp==T_A || tp==T_AAAA) { + /* mark it as added */ + if (!sva_add(sva,rrn,tp,b->rdlen,b->data)) + return 0; + } + /* Mark for additional address records. XXX: this should be a more effective algorithm; at least the list is small */ + for (i=0;irdlen-ar_offs[i],((unsigned char *)(b->data))+ar_offs[i], + ucharp "", 0)) + return 0; + break; + } + } + b=b->next; + if (rnd_recs) { + if(!b) b=crrset->rrs; /* wraparound */ + if(b==first) break; + } + } + } + return 1; +} + +/* + * Add the fitting elements of the cached record to the message in ans, where ans + * is grown to fit, sz is the size of the packet and is modified to be the new size. + * The query is in qe. + * cb is the buffer used for message compression. *cb should be NULL if you call add_to_response + * the first time. It gets filled with a pointer to compression information that can be + * reused in subsequent calls to add_to_response. + */ +static int add_to_response(dns_msg_t **ans, size_t *sz, size_t *allocsz, + unsigned char *rrn, unsigned qtype, time_t queryts, + dns_cent_t *cached, unsigned *udp, dlist *cb, dlist *sva, dlist *ar) +{ + /* First of all, unless we have records of qtype, add cnames. + Well, actually, there should be at max one cname. */ + if (qtype!=T_CNAME && qtype!=QT_ALL && !(qtype>=T_MIN && qtype<=T_MAX && have_rr(cached,qtype))) + if (!add_rrset(ans, sz, allocsz, rrn, T_CNAME, queryts, cached, udp, cb, sva, ar)) + return 0; + + /* We need no switch for qclass, since we already have filtered packets we cannot understand */ + if (qtype==QT_AXFR || qtype==QT_IXFR) { + /* I do not know what to do in this case. Since we do not maintain zones (and since we are + no master server, so it is not our task), I just return an error message. If anyone + knows how to do this better, please notify me. + Anyway, this feature is rarely used in client communication, and there is no need for + other name servers to ask pdnsd. Btw: many bind servers reject an ?XFR query for security + reasons. */ + return 0; + } else if (qtype==QT_MAILB) { + if (!add_rrset(ans, sz, allocsz, rrn, T_MB, queryts, cached, udp, cb, sva, ar)) + return 0; + if (!add_rrset(ans, sz, allocsz, rrn, T_MG, queryts, cached, udp, cb, sva, ar)) + return 0; + if (!add_rrset(ans, sz, allocsz, rrn, T_MR, queryts, cached, udp, cb, sva, ar)) + return 0; + } else if (qtype==QT_MAILA) { + if (!add_rrset(ans, sz, allocsz, rrn, T_MD, queryts, cached, udp, cb, sva, ar)) + return 0; + if (!add_rrset(ans, sz, allocsz, rrn, T_MF, queryts, cached, udp, cb, sva, ar)) + return 0; + } else if (qtype==QT_ALL) { + int i, n= NRRITERLIST(cached); + const unsigned short *iterlist= RRITERLIST(cached); + for (i=0; i=T_MIN && qtype<=T_MAX) { + if (!add_rrset(ans, sz, allocsz, rrn, qtype, queryts, cached, udp, cb, sva, ar)) + return 0; + } else /* Shouldn't get here. */ + return 0; +#if 0 + if (!ntohs((*ans)->hdr.ancount)) { + /* Add a SOA if we have one and no other records are present in the answer. + * This is to aid caches so that they have a ttl. */ + if (!add_rrset(ans, sz, allocsz, rrn, T_SOA , queryts, cached, udp, cb, sva, ar)) + return 0; + } +#endif + return 1; +} + +/* + * Add an additional + */ +static int add_additional_rr(dns_msg_t **ans, size_t *rlen, size_t *allocsz, + unsigned char *rhn, unsigned tp, time_t ttl, + unsigned dlen, void *data, int sect, unsigned *udp, dlist *cb, dlist *sva) +{ + sva_t *st; + + /* Check if already added; no double additionals */ + for (st=dlist_first(*sva); st; st=dlist_next(st)) { + if (st->tp==tp && rhnicmp(st->nm,rhn) && st->dlen==dlen && + (memcmp(skiprhn(st->nm),data, dlen)==0)) + { + return 1; + } + } + /* add_rr will do nothing when udp!=NULL and sz>*udp. */ + if(!add_rr(ans, rlen, allocsz, rhn, tp, ttl, dlen, data, sect, udp, cb)) + return 0; + /* mark it as added */ + if (!sva_add(sva,rhn,tp,dlen,data)) + return 0; + + return 1; +} + +/* + * Add one or more additionals from an rr bucket. + */ +static int add_additional_rrs(dns_msg_t **ans, size_t *rlen, size_t *allocsz, + unsigned char *rhn, unsigned tp, time_t ttl, + rr_bucket_t *rrb, int sect, unsigned *udp, dlist *cb, dlist *sva) +{ + rr_bucket_t *rr; + rr_bucket_t *first=NULL; /* Initialized to inhibit compiler warning */ + short rnd_recs=global.rnd_recs; + + rr=rrb; + if (rnd_recs) rr=first=randrr(rrb); + + while(rr) { + if (!add_additional_rr(ans, rlen, allocsz, rhn, tp, ttl, rr->rdlen,rr->data, sect, udp, cb, sva)) + return 0; + rr=rr->next; + if (rnd_recs) { + if(!rr) rr=rrb; /* wraparound */ + if(rr==first) break; + } + } + return 1; +} + +/* + * The code below actually handles A and AAAA additionals. + */ +static int add_additional_a(dns_msg_t **ans, size_t *rlen, size_t *allocsz, + unsigned char *rhn, time_t queryts, + unsigned *udp, dlist *cb, dlist *sva) +{ + dns_cent_t *ae; + int retval = 1; + + if ((ae=lookup_cache(rhn,NULL))) { + rr_set_t *rrset; rr_bucket_t *rr; + rrset=getrrset_A(ae); + if (rrset && (rr=rrset->rrs)) + if (!add_additional_rrs(ans, rlen, allocsz, + rhn, T_A, ans_ttl(rrset,queryts), + rr, S_ADDITIONAL, udp, cb, sva)) + retval = 0; + +#if IS_CACHED_AAAA + if(retval) { + rrset=getrrset_AAAA(ae); + if (rrset && (rr=rrset->rrs)) + if (!add_additional_rrs(ans, rlen, allocsz, + rhn, T_AAAA, ans_ttl(rrset,queryts), + rr, S_ADDITIONAL, udp, cb, sva)) + retval = 0; + } +#endif + free_cent(ae DBG1); + pdnsd_free(ae); + } + return retval; +} + +/* + * Compose an answer message for the decoded query in ql, hdr is the header of the dns request + * rlen is set to be the answer length. + * If udp is not NULL, *udp indicates the max length the dns response may have. + */ +static dns_msg_t *compose_answer(llist *ql, dns_hdr_t *hdr, size_t *rlen, edns_info_t *ednsinfo, unsigned *udp, int *rcodep) +{ + unsigned short rcode=RC_OK, aa=1; + dlist cb=NULL; + dlist sva=NULL; + dlist ar=NULL; + time_t queryts=time(NULL); + dns_queryel_t *qe; + dns_msg_t *ans; + size_t allocsz= ALLOCINITIALSIZE; + dns_cent_t *cached; + + ans=(dns_msg_t *)pdnsd_malloc(allocsz); + if (!ans) + goto return_ans; + ans->hdr.id=hdr->id; + ans->hdr.qr=QR_RESP; + ans->hdr.opcode=OP_QUERY; + ans->hdr.aa=0; + ans->hdr.tc=0; /* If tc is needed, it is set when the response is sent in udp_answer_thread. */ + ans->hdr.rd=hdr->rd; + ans->hdr.ra=1; + ans->hdr.z=0; + ans->hdr.ad=0; + ans->hdr.cd=0; + ans->hdr.rcode=rcode; + ans->hdr.qdcount=0; /* this is first filled in and will be modified */ + ans->hdr.ancount=0; + ans->hdr.nscount=0; + ans->hdr.arcount=0; + + *rlen=sizeof(dns_hdr_t); + /* first, add the query to the response */ + for (qe=llist_first(ql); qe; qe=llist_next(qe)) { + unsigned int qclen; + size_t newsz= dnsmsghdroffset + *rlen + rhnlen(qe->query) + 4; + if(newsz > allocsz) { + /* Need to allocate more space. + To avoid frequent reallocs, we allocate + a multiple of a certain chunk size. */ + size_t newallocsz= (newsz+ALLOCCHUNKSIZEMASK)&(~ALLOCCHUNKSIZEMASK); + dns_msg_t *newans=(dns_msg_t *)pdnsd_realloc(ans,newallocsz); + if (!newans) + goto error_ans; + ans=newans; + allocsz=newallocsz; + } + + { + unsigned char *p = ((unsigned char *)&ans->hdr) + *rlen; + /* the first name occurrence will not be compressed, + but the offset needs to be stored for future compressions */ + if (!(qclen=compress_name(qe->query,p,*rlen,&cb))) + goto error_ans; + p += qclen; + PUTINT16(qe->qtype,p); + PUTINT16(qe->qclass,p); + } + *rlen += qclen+4; + ans->hdr.qdcount=htons(ntohs(ans->hdr.qdcount)+1); + } + + /* Barf if we get a query we cannot answer */ + for (qe=llist_first(ql); qe; qe=llist_next(qe)) { + if ((PDNSD_NOT_CACHED_TYPE(qe->qtype) && + (qe->qtype!=QT_MAILB && qe->qtype!=QT_MAILA && qe->qtype!=QT_ALL)) || + (qe->qclass!=C_IN && qe->qclass!=QC_ALL)) + { + DEBUG_MSG("Unsupported QTYPE or QCLASS.\n"); + ans->hdr.rcode=rcode=RC_NOTSUPP; + goto cleanup_return; + } + } + + /* second, the answer section */ + for (qe=llist_first(ql); qe; qe=llist_next(qe)) { + int hops; + unsigned char qname[DNSNAMEBUFSIZE]; + + rhncpy(qname,qe->query); + /* look if we have a cached copy. otherwise, perform a nameserver query. Same with timeout */ + hops=MAX_HOPS; + do { + int rc; + unsigned char c_soa=cundef; + if ((rc=dns_cached_resolve(qname,qe->qtype, &cached, MAX_HOPS,queryts,&c_soa))!=RC_OK) { + ans->hdr.rcode=rcode=rc; + if(rc==RC_NAMEERR) { + if(c_soa!=cundef) { + /* Try to add a SOA record to the authority section. */ + unsigned scnt=rhnsegcnt(qname); + if(c_soaflags&CF_NEGATIVE)) { + rr_bucket_t *rr; + for(rr=rrset->rrs; rr; rr=rr->next) { + if (!add_rr(&ans,rlen,&allocsz,cached->qname,T_SOA,ans_ttl(rrset,queryts), + rr->rdlen,rr->data,S_AUTHORITY,udp,&cb)) + goto error_cached; + } + } + free_cent(cached DBG1); + pdnsd_free(cached); + } + } + + /* Possibly add an OPT pseudo-RR to the additional section. */ + if(ednsinfo) { + if(!add_opt_pseudo_rr(&ans, rlen, &allocsz, global.udpbufsize, rcode, 0,0)) + goto error_ans; + } + } + goto cleanup_return; + } + if(!(cached->flags&DF_LOCAL)) + aa=0; + + if (!add_to_response(&ans,rlen,&allocsz,qname,qe->qtype,queryts,cached,udp,&cb,&sva,&ar)) + goto error_cached; + if (hdr->rd && qe->qtype!=T_CNAME && qe->qtype!=QT_ALL && + !(qe->qtype>=T_MIN && qe->qtype<=T_MAX && have_rr(cached,qe->qtype)) && + follow_cname_chain(cached,qname)) + /* The rd bit is set and the response does not contain records of the requested type, + * but the response does contain a cname, so repeat the inquiry with the cname. + * add_to_response() has already added the cname to the response. + * Because of follow_cname_chain(), qname now contains the last cname in the chain. */ + ; + else { + /* maintain a list (ar) for authority records: We will add every name server that was + listed as authoritative in a reply we received (and only those) to this list. + This list will be used to fill the authority and additional sections of our own reply. + We only do this for the last record in a cname chain, to prevent answer bloat. */ + rr_set_t *rrset; + int rretp=T_NS; + if((qe->qtype>=T_MIN && qe->qtype<=T_MAX && !have_rr(cached,qe->qtype)) || + (qe->qtype==QT_MAILB && !have_rr_MB(cached) && !have_rr_MG(cached) && !have_rr_MR(cached)) || + (qe->qtype==QT_MAILA && !have_rr_MD(cached) && !have_rr_MF(cached))) + { + /* no record of requested type in the answer section. */ + rretp=T_SOA; + } + rrset=getrrset(cached,rretp); + if(rrset && (rrset->flags&CF_NEGATIVE)) + rrset=NULL; + if(!rrset) { + /* Try to find a name server higher up the hierarchy . + */ + dns_cent_t *prev=cached; + unsigned scnt=rhnsegcnt(prev->qname); + unsigned tcnt=(rretp==T_NS?prev->c_ns:prev->c_soa); + if((cached=lookup_cache((tcnt!=cundef && tcntqname,scnt-tcnt):prev->qname,NULL))) { + rrset=getrrset(cached,rretp); + if(rrset && (rrset->flags&CF_NEGATIVE)) + rrset=NULL; + } + if(!rrset && (prev->flags&DF_LOCAL)) { + unsigned char *nm=getlocalowner(prev->qname,rretp); + if(nm) { + if(cached) { + free_cent(cached DBG1); + pdnsd_free(cached); + } + if((cached=lookup_cache(nm,NULL))) + rrset=getrrset(cached,rretp); + } + } + free_cent(prev DBG1); + pdnsd_free(prev); + } + if (rrset) { + rr_bucket_t *rr; + for (rr=rrset->rrs; rr; rr=rr->next) { + if (!add_ar(&ar, rretp, rr->rdlen,rr->data, cached->qname, + ans_ttl(rrset,queryts))) + goto error_cached; + } + } + hops=0; /* this will break the loop */ + } + if(cached) { + free_cent(cached DBG1); + pdnsd_free(cached); + } + } while (--hops>=0); + } + + { + rr_ext_t *rre; + /* Add the authority section */ + for (rre=dlist_first(ar); rre; rre=dlist_next(rre)) { + if (rre->tp == T_NS || rre->tp == T_SOA) { + unsigned char *nm = rre->tnm + rre->tsz; + if (!add_additional_rr(&ans, rlen, &allocsz, + nm, rre->tp, rre->ttl, rre->tsz, rre->tnm, + S_AUTHORITY, udp, &cb, &sva)) + { + goto error_ans; + } + } + } + + /* Add the additional section, but only if we stay within the UDP buffer limit. */ + /* If a pseudo RR doesn't fit, nothing else will. */ + if(!(udp && *rlen+sizeof_opt_pseudo_rr>*udp)) { + + /* Possibly add an OPT pseudo-RR to the additional section. */ + if(ednsinfo) { + if(!add_opt_pseudo_rr(&ans, rlen, &allocsz, global.udpbufsize, rcode, 0,0)) + goto error_ans; + } + + /* now add the name server addresses */ + for (rre=dlist_first(ar); rre; rre=dlist_next(rre)) { + if (rre->tp == T_NS || rre->tp == RRETP_ADD) { + if (!add_additional_a(&ans, rlen, &allocsz, + rre->tnm, queryts, udp, &cb, &sva)) + goto error_ans; + } + } + } + } + if (aa) + ans->hdr.aa=1; + goto cleanup_return; + + /* You may not like goto's, but here we avoid lots of code duplication. */ +error_cached: + free_cent(cached DBG1); + pdnsd_free(cached); +error_ans: + pdnsd_free(ans); + ans=NULL; +cleanup_return: + dlist_free(ar); + dlist_free(sva); + dlist_free(cb); +return_ans: + if(rcodep) *rcodep=rcode; + return ans; +} + +/* + * Decode the query (the query messgage is in data and rlen bytes long) into a dlist. + * XXX: data needs to be aligned. + * The return value can be RC_OK or RC_TRUNC, in which case the (partially) constructed list is + * returned in qp, or something else (RC_FORMAT or RC_SERVFAIL), in which case no list is returned. + * + * *ptrrem will be assigned the address just after the questions sections in the message, and *lenrem + * the remaining message length after the questions section. These values are only meaningful if the + * return value is RC_OK. + */ +static int decode_query(unsigned char *data, size_t rlen, unsigned char **ptrrem, size_t *lenrem, llist *qp) +{ + int i,res=RC_OK; + dns_hdr_t *hdr=(dns_hdr_t *)data; /* aligned, so no prob. */ + unsigned char *ptr=(unsigned char *)(hdr+1); + size_t sz= rlen - sizeof(dns_hdr_t); + uint16_t qdcount=ntohs(hdr->qdcount); + + llist_init(qp); + for (i=0; iqtype,ptr); + GETINT16(qe->qclass,ptr); + sz-=4; + memcpy(qe->query,qbuf,qlen); + } + + if(ptrrem) *ptrrem=ptr; + if(lenrem) *lenrem=sz; + return res; +} + + +/* Scan the additional section of a query message for an OPT pseudo RR. + data and rlen are as in decode_query(). Note in particular that data needs to be aligned! + ptr should point the beginning of the additional section, sz should contain the + length of this remaining part of the message and numrr the number of resource records in the section. + *numopt is incremented with the number of OPT RRs found (should be at most one). + + Note that a return value of RC_OK means the additional section was parsed without errors, not that + an OPT pseudo RR was found! Check the value of *numopt for the latter. + + The structure pointed to by ep is filled with the information of the first OPT pseudo RR found, + but only if *numopt was set to zero before the call. +*/ +static int decode_query_additional(unsigned char *data, size_t rlen, unsigned char *ptr, size_t sz, int numrr, + int *numopt, edns_info_t *ep) +{ + int i, res; + + for (i=0; i0 + if(nmbuf[0]!=0) { + DEBUG_MSG("decode_query_additional: name in OPT record not empty!\n"); + } +#endif + ep->udpsize= class; + ep->rcode= ((uint16_t)ttlp[0]<<4) | ((dns_hdr_t *)data)->rcode; + ep->version= ttlp[1]; + ep->do_flg= (ttlp[2]>>7)&1; +#if DEBUG>0 + if(debug_p) { + unsigned int Zflags= ((uint16_t)ttlp[2]<<8) | ttlp[3]; + if(Zflags & 0x7fff) { + DEBUG_MSG("decode_query_additional: Z field contains unknown nonzero bits (%04x).\n", + Zflags); + } + if(rdlen) { + DEBUG_MSG("decode_query_additional: RDATA field in OPT record not empty!\n"); + } + } +#endif + } + else { + DEBUG_MSG("decode_query_additional: ingnoring surplus OPT record.\n"); + } + } + else { + DEBUG_MSG("decode_query_additional: ignoring record of type %s (%d).\n", + getrrtpname(type), type); + } + + /* Skip RDATA field. */ + sz -= rdlen; + ptr += rdlen; + } + + return RC_OK; +} + +/* Make a dns error reply message + * Id is the query id and still in network order. + * op is the opcode to fill in, rescode - name says it all. + */ +static void mk_error_reply(unsigned short id, unsigned short opcode,unsigned short rescode,dns_hdr_t *rep) +{ + rep->id=id; + rep->qr=QR_RESP; + rep->opcode=opcode; + rep->aa=0; + rep->tc=0; + rep->rd=0; + rep->ra=1; + rep->z=0; + rep->ad=0; + rep->cd=0; + rep->rcode=rescode; + rep->qdcount=0; + rep->ancount=0; + rep->nscount=0; + rep->arcount=0; +} + +/* + * Analyze and answer the query in data. The answer is returned. rlen is at call the query length and at + * return the length of the answer. You have to free the answer after sending it. + */ +static dns_msg_t *process_query(unsigned char *data, size_t *rlenp, unsigned *udp, int *rcodep) +{ + size_t rlen= *rlenp; + int res; + dns_hdr_t *hdr; + llist ql; + dns_msg_t *ans; + edns_info_t ednsinfo= {0}, *ednsinfop= NULL; + + DEBUG_MSG("Received query (msg len=%u).\n", (unsigned int)rlen); + DEBUG_DUMP_DNS_MSG(data, rlen); + + /* + * We will ignore all records that come with a query, except for the actual query records, + * and possible OPT pseudo RRs in the addtional section. + * We will send back the query in the response. We will reject all non-queries, and + * some not supported thingies. + * If anyone notices behaviour that is not in standard conformance, please notify me! + */ + hdr=(dns_hdr_t *)data; + if (rlen<2) { + DEBUG_MSG("Message too short.\n"); + return NULL; /* message too short: no id provided. */ + } + if (rlenqr!=QR_QUERY) { + DEBUG_MSG("The QR bit indicates this is a response, not a query.\n"); + return NULL; /* RFC says: discard */ + } + if (hdr->opcode!=OP_QUERY) { + DEBUG_MSG("Not a standard query (opcode=%u).\n",hdr->opcode); + res=RC_NOTSUPP; + goto error_reply; + } +#if DEBUG>0 + if(debug_p) { + char flgsbuf[DNSFLAGSMAXSTRSIZE]; + dnsflags2str(hdr, flgsbuf); + if(flgsbuf[0]) { + DEBUG_MSG("Flags:%s\n", flgsbuf); + } + } +#endif + if (hdr->z!=0) { + DEBUG_MSG("Malformed query (nonzero Z bit).\n"); + res=RC_FORMAT; + goto error_reply; + } + if (hdr->rcode!=RC_OK) { + DEBUG_MSG("Bad rcode(%u).\n",hdr->rcode); + return NULL; /* discard (may cause error storms) */ + } + + if (hdr->ancount) { + DEBUG_MSG("Query has a non-empty answer section!\n"); + res=RC_FORMAT; + goto error_reply; + } + + if (hdr->nscount) { + DEBUG_MSG("Query has a non-empty authority section!\n"); + res=RC_FORMAT; + goto error_reply; + } + +#if 0 + /* The following only makes sense if we completely disallow + Extension Mechanisms for DNS (RFC 2671). */ + if (hdr->arcount) { + DEBUG_MSG("Query has a non-empty additional section!\n"); + res=RC_FORMAT; + goto error_reply; + } +#endif + { + unsigned char *ptr; + size_t sz; + uint16_t arcount; + res=decode_query(data,rlen,&ptr,&sz,&ql); + if(res!=RC_OK) { + if(res==RC_TRUNC) { + if(!hdr->tc || llist_isempty(&ql)) { + res=RC_FORMAT; + goto free_ql_error_reply; + } + } + else + goto error_reply; + } + + if ((arcount=ntohs(hdr->arcount))) { + int numoptrr= 0; + DEBUG_MSG("Query has a non-empty additional section: " + "checking for OPT pseudo-RR.\n"); + if(res==RC_TRUNC) { + DEBUG_MSG("Additional section cannot be read due to truncation!\n"); + res=RC_FORMAT; + goto free_ql_error_reply; + } + res=decode_query_additional(data,rlen,ptr,sz,arcount, &numoptrr, &ednsinfo); + if(!(res==RC_OK || (res==RC_TRUNC && hdr->tc))) { + res=RC_FORMAT; + goto free_ql_error_reply; + } + if(numoptrr) { +#if DEBUG>0 + if(numoptrr!=1) { + DEBUG_MSG("Additional section in query contains %d OPT pseudo-RRs!\n", numoptrr); + } +#endif + if(ednsinfo.version!=0) { + DEBUG_MSG("Query contains unsupported EDNS version %d!\n", ednsinfo.version); + res=RC_BADVERS; + goto free_ql_error_reply; + } + if(ednsinfo.rcode!=0) { + DEBUG_MSG("Query contains non-zero EDNS rcode (%d)!\n", ednsinfo.rcode); + res=RC_FORMAT; + goto free_ql_error_reply; + } + DEBUG_MSG("Query contains OPT pseudosection: EDNS udp size = %u, flag DO=%u\n", + ednsinfo.udpsize, ednsinfo.do_flg); + ednsinfop = &ednsinfo; + if(udp && ednsinfo.udpsize>UDP_BUFSIZE) { + unsigned udpbufsize = global.udpbufsize; + if(udpbufsize > ednsinfo.udpsize) + udpbufsize = ednsinfo.udpsize; + *udp = udpbufsize; + } + } + } + } + +#if DEBUG>0 + if (debug_p) { + if(!llist_isempty(&ql)) { + dns_queryel_t *qe; + DEBUG_MSG("Questions are:\n"); + for (qe=llist_first(&ql); qe; qe=llist_next(qe)) { + DEBUG_RHN_MSG("\tqc=%s (%u), qt=%s (%u), query=\"%s\"\n", + get_cname(qe->qclass),qe->qclass,get_tname(qe->qtype),qe->qtype,RHN2STR(qe->query)); + } + } + else { + DEBUG_MSG("Query contains no questions.\n"); + } + } +#endif + + if (llist_isempty(&ql)) { + res=RC_FORMAT; + goto error_reply; + } + if (!(ans=compose_answer(&ql, hdr, rlenp, ednsinfop, udp, rcodep))) { + /* An out of memory condition or similar could cause NULL output. Send failure notification */ + res=RC_SERVFAIL; + goto free_ql_error_reply; + } + llist_free(&ql); + return ans; + + free_ql_error_reply: + llist_free(&ql); + error_reply: + *rlenp=sizeof(dns_hdr_t); + { + size_t allocsz = sizeof(dns_msg_t); + if(res&~0xf) + allocsz += sizeof_opt_pseudo_rr; + ans= (dns_msg_t *)pdnsd_malloc(allocsz); + if (ans) { + mk_error_reply(hdr->id,rlen>=3?hdr->opcode:OP_QUERY,res,&ans->hdr); + if(res&~0xf) + add_opt_pseudo_rr(&ans,rlenp,&allocsz, + global.udpbufsize,res,0,0); + } + else if (++da_mem_errs<=MEM_MAX_ERRS) { + log_error("Out of memory in query processing."); + } + } + if(rcodep) *rcodep= res; + return ans; +} + +/* + * Called by *_answer_thread exit handler to clean up process count. + */ +inline static void decrease_procs() +{ + + pthread_mutex_lock(&proc_lock); + procs--; + qprocs--; + pthread_mutex_unlock(&proc_lock); +} + +static void udp_answer_thread_cleanup(void *data) +{ + pdnsd_free(data); + decrease_procs(); +} + +/* + * A thread opened to answer a query transmitted via udp. Data is a pointer to the structure udp_buf_t that + * contains the received data and various other parameters. + * After the query is answered, the thread terminates + * XXX: data must point to a correctly aligned buffer + */ +static void *udp_answer_thread(void *data) +{ + struct msghdr msg; + struct iovec v; + struct cmsghdr *cmsg; +#if defined(SRC_ADDR_DISC) + char ctrl[CMSG_SPACE(sizeof(pkt_info_t))]; +#endif + size_t rlen=((udp_buf_t *)data)->len; + unsigned udpmaxrespsize = UDP_BUFSIZE; + /* XXX: process_query is assigned to this, this mallocs, so this points to aligned memory */ + dns_msg_t *resp; + int rcode; + unsigned thrid; + pthread_cleanup_push(udp_answer_thread_cleanup, data); + THREAD_SIGINIT; + + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + pdnsd_exit(); + } + } + + for(;;) { + pthread_mutex_lock(&proc_lock); + if (procs0 + if(debug_p) { + int err; + if ((err=pthread_setspecific(thrid_key, &thrid)) != 0) { + if(++da_misc_errs<=MISC_MAX_ERRS) + log_error("pthread_setspecific failed: %s",strerror(err)); + /* pdnsd_exit(); */ + } + } +#endif + + if (!(resp=process_query(((udp_buf_t *)data)->buf,&rlen,&udpmaxrespsize,&rcode))) { + /* + * A return value of NULL is a fatal error that prohibits even the sending of an error message. + * logging is already done. Just exit the thread now. + */ + pthread_exit(NULL); /* data freed by cleanup handler */ + } + pthread_cleanup_push(free, resp); + if (rlen>udpmaxrespsize) { + rlen=udpmaxrespsize; + resp->hdr.tc=1; /*set truncated bit*/ + } + DEBUG_MSG("Outbound msg len %li, tc=%u, rc=\"%s\"\n",(long)rlen,resp->hdr.tc,get_ename(rcode)); + + v.iov_base=(char *)&resp->hdr; + v.iov_len=rlen; + msg.msg_iov=&v; + msg.msg_iovlen=1; +#if (TARGET!=TARGET_CYGWIN) +#if defined(SRC_ADDR_DISC) + msg.msg_control=ctrl; + msg.msg_controllen=sizeof(ctrl); +#else + msg.msg_control=NULL; + msg.msg_controllen=0; +#endif + msg.msg_flags=0; /* to avoid warning message by Valgrind */ +#endif + +#ifdef ENABLE_IPV4 + if (run_ipv4) { + + msg.msg_name=&((udp_buf_t *)data)->addr.sin4; + msg.msg_namelen=sizeof(struct sockaddr_in); +# if defined(SRC_ADDR_DISC) +# if (TARGET==TARGET_LINUX) + ((udp_buf_t *)data)->pi.pi4.ipi_spec_dst=((udp_buf_t *)data)->pi.pi4.ipi_addr; + cmsg=CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len=CMSG_LEN(sizeof(struct in_pktinfo)); + cmsg->cmsg_level=SOL_IP; + cmsg->cmsg_type=IP_PKTINFO; + memcpy(CMSG_DATA(cmsg),&((udp_buf_t *)data)->pi.pi4,sizeof(struct in_pktinfo)); + msg.msg_controllen=CMSG_SPACE(sizeof(struct in_pktinfo)); +# else + cmsg=CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len=CMSG_LEN(sizeof(struct in_addr)); + cmsg->cmsg_level=IPPROTO_IP; + cmsg->cmsg_type=IP_RECVDSTADDR; + memcpy(CMSG_DATA(cmsg),&((udp_buf_t *)data)->pi.ai4,sizeof(struct in_addr)); + msg.msg_controllen=CMSG_SPACE(sizeof(struct in_addr)); +# endif +# endif +# if DEBUG>0 + { + char buf[ADDRSTR_MAXLEN]; + + DEBUG_MSG("Answering to: %s", inet_ntop(AF_INET,&((udp_buf_t *)data)->addr.sin4.sin_addr,buf,ADDRSTR_MAXLEN)); +# if defined(SRC_ADDR_DISC) +# if (TARGET==TARGET_LINUX) + DEBUG_MSGC(", source address: %s\n", inet_ntop(AF_INET,&((udp_buf_t *)data)->pi.pi4.ipi_spec_dst,buf,ADDRSTR_MAXLEN)); +# else + DEBUG_MSGC(", source address: %s\n", inet_ntop(AF_INET,&((udp_buf_t *)data)->pi.ai4,buf,ADDRSTR_MAXLEN)); +# endif +# else + DEBUG_MSGC("\n"); +# endif + } +# endif /* DEBUG */ + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + + msg.msg_name=&((udp_buf_t *)data)->addr.sin6; + msg.msg_namelen=sizeof(struct sockaddr_in6); +# if defined(SRC_ADDR_DISC) + cmsg=CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len=CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsg->cmsg_level=SOL_IPV6; + cmsg->cmsg_type=IPV6_PKTINFO; + memcpy(CMSG_DATA(cmsg),&((udp_buf_t *)data)->pi.pi6,sizeof(struct in6_pktinfo)); + msg.msg_controllen=CMSG_SPACE(sizeof(struct in6_pktinfo)); +# endif +# if DEBUG>0 + { + char buf[ADDRSTR_MAXLEN]; + + DEBUG_MSG("Answering to: %s", inet_ntop(AF_INET6,&((udp_buf_t *)data)->addr.sin6.sin6_addr,buf,ADDRSTR_MAXLEN)); +# if defined(SRC_ADDR_DISC) + DEBUG_MSGC(", source address: %s\n", inet_ntop(AF_INET6,&((udp_buf_t *)data)->pi.pi6.ipi6_addr,buf,ADDRSTR_MAXLEN)); +# else + DEBUG_MSGC("\n"); +# endif + } +# endif /* DEBUG */ + } +#endif + + /* Lock the socket, and clear the error flag before dropping the lock */ +#ifdef SOCKET_LOCKING + pthread_mutex_lock(&s_lock); +#endif + if (sendmsg(((udp_buf_t *)data)->sock,&msg,0)<0) { +#ifdef SOCKET_LOCKING + pthread_mutex_unlock(&s_lock); +#endif + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("Error in udp send: %s",strerror(errno)); + } + } else { + int tmp; + socklen_t sl=sizeof(tmp); + getsockopt(((udp_buf_t *)data)->sock, SOL_SOCKET, SO_ERROR, &tmp, &sl); +#ifdef SOCKET_LOCKING + pthread_mutex_unlock(&s_lock); +#endif + } + + pthread_cleanup_pop(1); /* free(resp) */ + pthread_cleanup_pop(1); /* free(data) */ + return NULL; +} + +int init_udp_socket() +{ + int sock; + int so=1; + union { +#ifdef ENABLE_IPV4 + struct sockaddr_in sin4; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sin6; +#endif + } sin; + socklen_t sinl; + +#ifdef ENABLE_IPV4 + if (run_ipv4) { + if ((sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) { + log_error("Could not open udp socket: %s",strerror(errno)); + return -1; + } + memset(&sin.sin4,0,sizeof(struct sockaddr_in)); + sin.sin4.sin_family=AF_INET; + sin.sin4.sin_port=htons(global.port); + sin.sin4.sin_addr=global.a.ipv4; + SET_SOCKA_LEN4(sin.sin4); + sinl=sizeof(struct sockaddr_in); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + if ((sock=socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP))==-1) { + log_error("Could not open udp socket: %s",strerror(errno)); + return -1; + } + memset(&sin.sin6,0,sizeof(struct sockaddr_in6)); + sin.sin6.sin6_family=AF_INET6; + sin.sin6.sin6_port=htons(global.port); + sin.sin6.sin6_flowinfo=IPV6_FLOWINFO; + sin.sin6.sin6_addr=global.a.ipv6; + SET_SOCKA_LEN6(sin.sin6); + sinl=sizeof(struct sockaddr_in6); + } +#endif + +#ifdef SRC_ADDR_DISC +# if (TARGET!=TARGET_LINUX) + if (run_ipv4) { +# endif + /* The following must be set on any case because it also applies for IPv4 packets sent to + * ipv6 addresses. */ +# if (TARGET==TARGET_LINUX ) + if (setsockopt(sock,SOL_IP,IP_PKTINFO,&so,sizeof(so))!=0) { +# else + if (setsockopt(sock,IPPROTO_IP,IP_RECVDSTADDR,&so,sizeof(so))!=0) { +# endif + log_error("Could not set options on udp socket: %s",strerror(errno)); + close(sock); + return -1; + } +# if (TARGET!=TARGET_LINUX) + } +# endif + +# ifdef ENABLE_IPV6 + if (!run_ipv4) { + if (setsockopt(sock,SOL_IPV6,IPV6_RECVPKTINFO,&so,sizeof(so))!=0) { + log_error("Could not set options on udp socket: %s",strerror(errno)); + close(sock); + return -1; + } + } +# endif +#endif + if (bind(sock,(struct sockaddr *)&sin,sinl)!=0) { + log_error("Could not bind to udp socket: %s",strerror(errno)); + close(sock); + return -1; + } + return sock; +} + +/* + * Listen on the specified port for udp packets and answer them (each in a new thread to be nonblocking) + * This was changed to support sending UDP packets with exactly the same source address as they were coming + * to us, as required by rfc2181. Although this is a sensible requirement, it is slightly more difficult + * and may introduce portability issues. + */ +void *udp_server_thread(void *dummy) +{ + int sock; + ssize_t qlen; + pthread_t pt; + udp_buf_t *buf; + struct msghdr msg; + struct iovec v; + struct cmsghdr *cmsg; + char ctrl[512]; +#if defined(ENABLE_IPV6) && (TARGET==TARGET_LINUX) + struct in_pktinfo sip; +#endif + /* (void)dummy; */ /* To inhibit "unused variable" warning */ + + THREAD_SIGINIT; + + + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + pdnsd_exit(); + } + } + + sock=udp_socket; + + while (1) { + int udpbufsize= global.udpbufsize; + if (!(buf=(udp_buf_t *)pdnsd_calloc(1,sizeof(udp_buf_t)+udpbufsize))) { + if (++da_mem_errs<=MEM_MAX_ERRS) { + log_error("Out of memory in request handling."); + } + break; + } + + buf->sock=sock; + + v.iov_base=(char *)buf->buf; + v.iov_len=udpbufsize; + msg.msg_iov=&v; + msg.msg_iovlen=1; +#if (TARGET!=TARGET_CYGWIN) + msg.msg_control=ctrl; + msg.msg_controllen=sizeof(ctrl); +#endif + +#if defined(SRC_ADDR_DISC) +# ifdef ENABLE_IPV4 + if (run_ipv4) { + msg.msg_name=&buf->addr.sin4; + msg.msg_namelen=sizeof(struct sockaddr_in); + if ((qlen=recvmsg(sock,&msg,0))>=0) { + cmsg=CMSG_FIRSTHDR(&msg); + while(cmsg) { +# if (TARGET==TARGET_LINUX) + if (cmsg->cmsg_level==SOL_IP && cmsg->cmsg_type==IP_PKTINFO) { + memcpy(&buf->pi.pi4,CMSG_DATA(cmsg),sizeof(struct in_pktinfo)); + break; + } +# else + if (cmsg->cmsg_level==IPPROTO_IP && cmsg->cmsg_type==IP_RECVDSTADDR) { + memcpy(&buf->pi.ai4,CMSG_DATA(cmsg),sizeof(buf->pi.ai4)); + break; + } +# endif + cmsg=CMSG_NXTHDR(&msg,cmsg); + } + if (!cmsg) { + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("Could not discover udp destination address"); + } + goto free_buf_continue; + } + } else if (errno!=EINTR) { + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("error in UDP recv: %s", strerror(errno)); + } + } + } +# endif +# ifdef ENABLE_IPV6 + ELSE_IPV6 { + msg.msg_name=&buf->addr.sin6; + msg.msg_namelen=sizeof(struct sockaddr_in6); + if ((qlen=recvmsg(sock,&msg,0))>=0) { + cmsg=CMSG_FIRSTHDR(&msg); + while(cmsg) { + if (cmsg->cmsg_level==SOL_IPV6 && cmsg->cmsg_type==IPV6_PKTINFO) { + memcpy(&buf->pi.pi6,CMSG_DATA(cmsg),sizeof(struct in6_pktinfo)); + break; + } + cmsg=CMSG_NXTHDR(&msg,cmsg); + } + if (!cmsg) { + /* We might have an IPv4 Packet incoming on our IPv6 port, so we also have to + * check for IPv4 sender addresses */ + cmsg=CMSG_FIRSTHDR(&msg); + while(cmsg) { +# if (TARGET==TARGET_LINUX) + if (cmsg->cmsg_level==SOL_IP && cmsg->cmsg_type==IP_PKTINFO) { + memcpy(&sip,CMSG_DATA(cmsg),sizeof(sip)); + IPV6_MAPIPV4(&sip.ipi_addr,&buf->pi.pi6.ipi6_addr); + buf->pi.pi6.ipi6_ifindex=sip.ipi_ifindex; + break; + } + /* FIXME: What about BSD? probably ok, but... */ +# endif + cmsg=CMSG_NXTHDR(&msg,cmsg); + } + if (!cmsg) { + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("Could not discover udp destination address"); + } + goto free_buf_continue; + } + } + } else if (errno!=EINTR) { + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("error in UDP recv: %s", strerror(errno)); + } + } + } +# endif +#else /* !SRC_ADDR_DISC */ +# ifdef ENABLE_IPV4 + if (run_ipv4) { + msg.msg_name=&buf->addr.sin4; + msg.msg_namelen=sizeof(struct sockaddr_in); + } +# endif +# ifdef ENABLE_IPV6 + ELSE_IPV6 { + msg.msg_name=&buf->addr.sin6; + msg.msg_namelen=sizeof(struct sockaddr_in6); + } +# endif + qlen=recvmsg(sock,&msg,0); + if (qlen<0 && errno!=EINTR) { + if (++da_udp_errs<=UDP_MAX_ERRS) { + log_error("error in UDP recv: %s", strerror(errno)); + } + } +#endif /* SRC_ADDR_DISC */ + + if (qlen>=0) { + pthread_mutex_lock(&proc_lock); + if (qprocslen=qlen; + err=pthread_create(&pt,&attr_detached,udp_answer_thread,(void *)buf); + if(err==0) + continue; + if(++da_thrd_errs<=THRD_MAX_ERRS) + log_warn("pthread_create failed: %s",strerror(err)); + /* If thread creation failed, free resources associated with it. */ + pthread_mutex_lock(&proc_lock); + --qprocs; --spawned; + } + ++dropped; + pthread_mutex_unlock(&proc_lock); + } + free_buf_continue: + pdnsd_free(buf); + usleep_r(50000); + } + + udp_socket=-1; + close(sock); + udps_thrid=main_thrid; + if (tcp_socket==-1) + pdnsd_exit(); + return NULL; +} + +#ifndef NO_TCP_SERVER + +static void tcp_answer_thread_cleanup(void *csock) +{ + close(*((int *)csock)); + pdnsd_free(csock); + decrease_procs(); +} + +/* + * Process a dns query via tcp. The argument is a pointer to the socket. + */ +static void *tcp_answer_thread(void *csock) +{ + /* XXX: This should be OK, the original must be (and is) aligned */ + int sock=*((int *)csock); + unsigned thrid; + + pthread_cleanup_push(tcp_answer_thread_cleanup, csock); + THREAD_SIGINIT; + + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + pdnsd_exit(); + } + } + + for(;;) { + pthread_mutex_lock(&proc_lock); + if (procs0 + if(debug_p) { + int err; + if ((err=pthread_setspecific(thrid_key, &thrid)) != 0) { + if(++da_misc_errs<=MISC_MAX_ERRS) + log_error("pthread_setspecific failed: %s",strerror(err)); + /* pdnsd_exit(); */ + } + } +#endif +#ifdef TCP_SUBSEQ + + /* rfc1035 says we should process multiple queries in succession, so we are looping until + * the socket is closed by the other side or by tcp timeout. + * This in fact makes DoSing easier. If that is your concern, you should disable pdnsd's + * TCP server.*/ + for(;;) +#endif + { + int rlen,olen; + size_t nlen; + unsigned char *buf; + dns_msg_t *resp; + +#ifdef NO_POLL + fd_set fds; + struct timeval tv; + FD_ZERO(&fds); + PDNSD_ASSERT(sock=2) { /* We need the id to send a valid reply. */ + dns_msg_t err; + mk_error_reply(((dns_hdr_t*)buf)->id, + olen>=3?((dns_hdr_t*)buf)->opcode:OP_QUERY, + RC_FORMAT, + &err.hdr); + err.len=htons(sizeof(dns_hdr_t)); + write_all(sock,&err,sizeof(err)); /* error anyway. */ + } + pthread_exit(NULL); /* buf freed and socket closed by cleanup handlers */ + } + olen += rv; + } + nlen=rlen; + if (!(resp=process_query(buf,&nlen,NULL,NULL))) { + /* + * A return value of NULL is a fatal error that prohibits even the sending of an error message. + * logging is already done. Just exit the thread now. + */ + pthread_exit(NULL); + } + pthread_cleanup_pop(1); /* free(buf) */ + pthread_cleanup_push(free,resp); + { + int err; size_t rsize; + resp->len=htons(nlen); + rsize=dnsmsghdroffset+nlen; + if ((err=write_all(sock,resp,rsize))!=rsize) { + DEBUG_MSG("Error while writing to TCP client: %s\n",err==-1?strerror(errno):"unknown error"); + pthread_exit(NULL); /* resp is freed and socket is closed by cleanup handlers */ + } + } + pthread_cleanup_pop(1); /* free(resp) */ + } + + /* socket is closed by cleanup handler */ + pthread_cleanup_pop(1); + return NULL; +} + +int init_tcp_socket() +{ + int sock; + union { +#ifdef ENABLE_IPV4 + struct sockaddr_in sin4; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sin6; +#endif + } sin; + socklen_t sinl; + +#ifdef ENABLE_IPV4 + if (run_ipv4) { + if ((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) { + log_error("Could not open tcp socket: %s",strerror(errno)); + return -1; + } + memset(&sin.sin4,0,sizeof(struct sockaddr_in)); + sin.sin4.sin_family=AF_INET; + sin.sin4.sin_port=htons(global.port); + sin.sin4.sin_addr=global.a.ipv4; + SET_SOCKA_LEN4(sin.sin4); + sinl=sizeof(struct sockaddr_in); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + if ((sock=socket(PF_INET6,SOCK_STREAM,IPPROTO_TCP))==-1) { + log_error("Could not open tcp socket: %s",strerror(errno)); + return -1; + } + memset(&sin.sin6,0,sizeof(struct sockaddr_in6)); + sin.sin6.sin6_family=AF_INET6; + sin.sin6.sin6_port=htons(global.port); + sin.sin6.sin6_flowinfo=IPV6_FLOWINFO; + sin.sin6.sin6_addr=global.a.ipv6; + SET_SOCKA_LEN6(sin.sin6); + sinl=sizeof(struct sockaddr_in6); + } +#endif + { + int so=1; + /* The SO_REUSEADDR socket option tells the kernel that even if this port + is busy (in the TIME_WAIT state), go ahead and reuse it anyway. If it + is busy, but with another state, we should get an address already in + use error. It is useful if pdnsd is shut down, and then restarted right + away while sockets are still active on its port. There is a slight risk + though. If unexpected data comes in, it may confuse pdnsd, but while + this is possible, it is not likely. + */ + if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&so,sizeof(so))) + log_warn("Could not set options on tcp socket: %s",strerror(errno)); + } + if (bind(sock,(struct sockaddr *)&sin,sinl)) { + log_error("Could not bind tcp socket: %s",strerror(errno)); + close(sock); + return -1; + } + return sock; +} + +/* + * Listen on the specified port for tcp connects and answer them (each in a new thread to be nonblocking) + */ +void *tcp_server_thread(void *p) +{ + int sock; + pthread_t pt; + int *csock; + + /* (void)p; */ /* To inhibit "unused variable" warning */ + + THREAD_SIGINIT; + + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + pdnsd_exit(); + } + } + + sock=tcp_socket; + + if (listen(sock,5)) { + if (++da_tcp_errs<=TCP_MAX_ERRS) { + log_error("Could not listen on tcp socket: %s",strerror(errno)); + } + goto close_sock_return; + } + + while (1) { + if (!(csock=(int *)pdnsd_malloc(sizeof(int)))) { + if (++da_mem_errs<=MEM_MAX_ERRS) { + log_error("Out of memory in request handling."); + } + break; + } + if ((*csock=accept(sock,NULL,0))==-1) { + if (errno!=EINTR && ++da_tcp_errs<=TCP_MAX_ERRS) { + log_error("tcp accept failed: %s",strerror(errno)); + } + } else { + /* + * With creating a new thread, we follow recommendations + * in rfc1035 not to block + */ + pthread_mutex_lock(&proc_lock); + if (qprocs. +*/ + + +#ifndef DNS_ANSWER_H +#define DNS_ANSWER_H + +#include + +/* --- from main.c */ +extern pthread_t main_thrid,servstat_thrid,statsock_thrid,tcps_thrid,udps_thrid; +extern volatile int tcp_socket; +extern volatile int udp_socket; +/* --- */ + +int init_udp_socket(void); +int init_tcp_socket(void); +void start_dns_servers(void); +int report_thread_stat(int f); + +#endif diff --git a/jni/pdnsd/src/dns_query.c b/jni/pdnsd/src/dns_query.c new file mode 100644 index 00000000..0b6c9c04 --- /dev/null +++ b/jni/pdnsd/src/dns_query.c @@ -0,0 +1,3798 @@ +/* dns_query.c - Execute outgoing dns queries and write entries to cache + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#ifdef HAVE_SYS_POLL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "list.h" +#include "consts.h" +#include "ipvers.h" +#include "dns_query.h" +#include "cache.h" +#include "dns.h" +#include "conff.h" +#include "servers.h" +#include "helpers.h" +#include "netdev.h" +#include "error.h" +#include "debug.h" + + +#if defined(NO_TCP_QUERIES) && M_PRESET!=UDP_ONLY +# error "You may not define NO_TCP_QUERIES when M_PRESET is not set to UDP_ONLY" +#endif +#if defined(NO_UDP_QUERIES) && M_PRESET!=TCP_ONLY +# error "You may not define NO_UDP_QUERIES when M_PRESET is not set to TCP_ONLY" +#endif + +/* data type to hold lists of IP addresses (both v4 and v6) + The allocated size should be: + sizeof(rejectlist_t) + na4*sizeof(addr4maskpair_t) + na6*sizeof(addr6maskpair_t) +*/ +typedef struct rejectlist_s { + struct rejectlist_s *next; + short policy; + short inherit; + int na4; +#if ALLOW_LOCAL_AAAA + int na6; + addr6maskpair_t rdata[0]; /* dummy array for alignment */ +#else + addr4maskpair_t rdata[0]; +#endif +} rejectlist_t; + +/* --- structures and state constants for parallel query */ +typedef struct { + union { +#ifdef ENABLE_IPV4 + struct sockaddr_in sin4; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sin6; +#endif + } a; +#ifdef ENABLE_IPV6 + struct in_addr a4fallback; +#endif + time_t timeout; + unsigned short flags; + short state; + short qm; + char nocache; + char auth_serv; + char lean_query; + char edns_query; + char needs_testing; + char trusted; + char aa; + char tc; + char ra; + char failed; + const unsigned char *nsdomain; + rejectlist_t *rejectlist; + /* internal state for p_exec_query */ + int sock; +#if 0 + dns_cent_t nent; + dns_cent_t servent; +#endif + unsigned short transl; + unsigned short recvl; +#ifndef NO_TCP_QUERIES + int iolen; /* number of bytes written or read up to now */ +#endif + dns_msg_t *msg; + dns_hdr_t *recvbuf; + unsigned short myrid; + int s_errno; +} query_stat_t; +typedef DYNAMIC_ARRAY(query_stat_t) *query_stat_array; + +/* Some macros for handling data in reject lists + Perhaps we should use inline functions instead of macros. +*/ +#define have_rejectlist(st) ((st)->rejectlist!=NULL) +#define inherit_rejectlist(st) ((st)->rejectlist && (st)->rejectlist->inherit) +#define reject_policy(st) ((st)->rejectlist->policy) +#define nreject_a4(st) ((st)->rejectlist->na4) +#if ALLOW_LOCAL_AAAA +#define nreject_a6(st) ((st)->rejectlist->na6) +#define rejectlist_a6(st) ((addr6maskpair_t *)(st)->rejectlist->rdata) +#define rejectlist_a4(st) ((addr4maskpair_t *)(rejectlist_a6(st)+nreject_a6(st))) +#else +#define rejectlist_a4(st) ((addr4maskpair_t *)(st)->rejectlist->rdata) +#endif + +#define QS_INITIAL 0 /* This is the initial state. Set this before starting. */ + +#define QS_TCPINITIAL 1 /* Start a TCP query. */ +#define QS_TCPWRITE 2 /* Waiting to write data. */ +#define QS_TCPREAD 3 /* Waiting to read data. */ + +#define QS_UDPINITIAL 4 /* Start a UDP query */ +#define QS_UDPRECEIVE 5 /* UDP query transmitted, waiting for response. */ + +#define QS_QUERY_CASES case QS_TCPINITIAL: case QS_TCPWRITE: case QS_TCPREAD: case QS_UDPINITIAL: case QS_UDPRECEIVE + +#define QS_CANCELED 7 /* query was started, but canceled before completion */ +#define QS_DONE 8 /* done, resources freed, result is in stat_t */ + + +/* Events to be polled/selected for */ +#define QS_WRITE_CASES case QS_TCPWRITE +#define QS_READ_CASES case QS_TCPREAD: case QS_UDPRECEIVE + +/* + * This is for error handling to prevent spewing the log files. + * Races do not really matter here, so no locks. + */ +#define MAXPOLLERRS 10 +static volatile unsigned long poll_errs=0; + +#define SOCK_ADDR(p) ((struct sockaddr *) &(p)->a) + +#ifdef SIN_LEN +#undef SIN_LEN +#endif + +#define SIN_LEN SEL_IPVER(sizeof(struct sockaddr_in),sizeof(struct sockaddr_in6)) +#define PDNSD_A(p) SEL_IPVER(((pdnsd_a *) &(p)->a.sin4.sin_addr),((pdnsd_a *) &(p)->a.sin6.sin6_addr)) + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN +#endif + +typedef DYNAMIC_ARRAY(dns_cent_t) *dns_cent_array; + + +/* + * Take the data from an RR and add it to an array of cache entries. + * The return value will be RC_OK in case of success, + * RC_SERVFAIL in case there is a problem with inconsistent ttl timestamps + * or RC_FATALERR in case of a memory allocation failure. + */ +static int rr_to_cache(dns_cent_array *centa, unsigned char *oname, int tp, time_t ttl, + unsigned dlen, void *data, unsigned flags, time_t queryts) +{ + int i,n; + dns_cent_t *cent; + + n=DA_NEL(*centa); + for(i=0;iqname,oname)) { + int retval=RC_OK; + /* We already have an entry in the array for this name. add_cent_rr is sufficient. + However, make sure there are no double records. This is done by add_cent_rr */ +#ifdef RFC2181_ME_HARDER + rr_set_t *rrset= getrrset(cent,tp); + if (rrset && rrset->ttl!=ttl) + retval= RC_SERVFAIL; +#endif + return add_cent_rr(cent,tp,ttl,queryts,flags,dlen,data DBG1)? retval: RC_FATALERR; + } + } + + /* Add a new entry to the array for this name. */ + if (!(*centa=DA_GROW1_F(*centa,free_cent0))) + return RC_FATALERR; + cent=&DA_LAST(*centa); + if (!init_cent(cent,oname, 0, 0, 0 DBG1)) { + *centa=DA_RESIZE(*centa,n); + return RC_FATALERR; + } + return add_cent_rr(cent,tp,ttl,queryts,flags,dlen,data DBG1)? RC_OK: RC_FATALERR; +} + +/* + * Takes a pointer (ptr) to a buffer with recnum rrs,decodes them and enters + * them into an array of cache entries. *ptr is modified to point after the last + * rr, and *lcnt is decremented by the size of the rrs. + * + * *numopt is incremented with the number of OPT pseudo RRs found (should be at most one). + * The structure pointed to by ep is filled with the information of the first OPT pseudo RR found, + * but only if *numopt was set to zero before the call. + * + * The return value will be either RC_OK (which indicates success), + * or one of the failure codes RC_FORMAT, RC_TRUNC, RC_SERVFAIL or RC_FATALERR + * (the latter indicates a memory allocation failure). +*/ +static int rrs2cent(unsigned char *msg, size_t msgsz, unsigned char **ptr, size_t *lcnt, int recnum, + unsigned flags, time_t queryts, dns_cent_array *centa, int *numopt, edns_info_t *ep) +{ + int rc, retval=RC_OK; + int i; + uint16_t type,class; uint32_t ttl; uint16_t rdlength; + + for (i=0;i0 + if(oname[0]!=0) { + DEBUG_MSG("rrs2cent: name in OPT record not empty!\n"); + } +#endif + ep->udpsize= class; + ep->rcode= ((uint16_t)ttlp[0]<<4) | ((dns_hdr_t *)msg)->rcode; + ep->version= ttlp[1]; + ep->do_flg= (ttlp[2]>>7)&1; +#if DEBUG>0 + if(debug_p) { + unsigned int Zflags= ((uint16_t)ttlp[2]<<8) | ttlp[3]; + if(Zflags & 0x7fff) { + DEBUG_MSG("rrs2cent: Z field contains unknown nonzero bits (%04x).\n", + Zflags); + } + } + if(rdlength) { + DEBUG_MSG("rrs2cent: RDATA field in OPT record not empty!\n"); + } +#endif + } + else { + DEBUG_MSG("rrs2cent: ingnoring surplus OPT record.\n"); + } + } + else if (!(PDNSD_NOT_CACHED_TYPE(type) || class!=C_IN)) { + /* Some types contain names that may be compressed, so these need to be processed. + * The other records are taken as they are. */ + + size_t blcnt=rdlength; + unsigned char *bptr=*ptr; /* make backup for decompression, because rdlength is the + authoritative record length and pointer and size will be + modified by decompress_name. */ + unsigned char *nptr; + unsigned int slen; + + switch (type) { + case T_A: + /* Validate types we use internally */ + if(rdlength!=4) goto invalid_length; + goto default_case; + + case T_CNAME: + case T_MB: + case T_MD: + case T_MF: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + { + unsigned char db[DNSNAMEBUFSIZE]; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, db, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, len, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; + +#if IS_CACHED_MINFO || IS_CACHED_RP +#if IS_CACHED_MINFO + case T_MINFO: +#endif +#if IS_CACHED_RP + case T_RP: +#endif + { + unsigned char db[DNSNAMEBUFSIZE+DNSNAMEBUFSIZE]; + nptr=db; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /* PDNSD_ASSERT(len + DNSNAMEBUFSIZE <= sizeof(db), "T_MINFO/T_RP: buffer limit reached"); */ + nptr+=len; + slen=len; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /*nptr+=len;*/ + slen+=len; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif + case T_MX: +#if IS_CACHED_AFSDB + case T_AFSDB: +#endif +#if IS_CACHED_RT + case T_RT: +#endif +#if IS_CACHED_KX + case T_KX: +#endif + { + unsigned char db[2+DNSNAMEBUFSIZE]; + if (blcnt<2) + goto record_too_short; + memcpy(db,bptr,2); /* copy the preference field*/ + blcnt-=2; + bptr+=2; + nptr=db+2; + slen=2; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /*nptr+=len;*/ + slen+=len; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; + + case T_SOA: + { + unsigned char db[DNSNAMEBUFSIZE+DNSNAMEBUFSIZE+20]; + nptr=db; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /* PDNSD_ASSERT(len + DNSNAMEBUFSIZE <= sizeof(db), "T_SOA: buffer limit reached"); */ + nptr+=len; + slen=len; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + nptr+=len; + slen+=len; + /* PDNSD_ASSERT(slen + 20 <= sizeof(db), "T_SOA: buffer limit reached"); */ + if (blcnt<20) + goto record_too_short; + memcpy(nptr,bptr,20); /*copy the rest of the SOA record*/ + blcnt-=20; + slen+=20; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#if IS_CACHED_AAAA + case T_AAAA: + /* Validate types we use internally */ + if(rdlength!=16) goto invalid_length; + goto default_case; +#endif +#if IS_CACHED_PX + case T_PX: + { + unsigned char db[2+DNSNAMEBUFSIZE+DNSNAMEBUFSIZE]; + if (blcnt<2) + goto record_too_short; + memcpy(db,bptr,2); /* copy the preference field*/ + blcnt-=2; + bptr+=2; + nptr=db+2; + slen=2; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /* PDNSD_ASSERT(len + DNSNAMEBUFSIZE <= sizeof(db), "T_PX: buffer limit reached"); */ + nptr+=len; + slen+=len; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /* nptr+=len; */ + slen+=len; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif +#if IS_CACHED_SRV + case T_SRV: + { + unsigned char db[6+DNSNAMEBUFSIZE]; + if (blcnt<6) + goto record_too_short; + memcpy(db,bptr,6); + blcnt-=6; + bptr+=6; + nptr=db+6; + slen=6; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /*nptr+=len;*/ + slen+=len; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif +#if IS_CACHED_NXT + case T_NXT: + { + unsigned char db[1040]; + nptr=db; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + nptr+=len; + slen=len+blcnt; + if (slen > sizeof(db)) + goto buffer_overflow; + memcpy(nptr,bptr,blcnt); + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif +#if IS_CACHED_NAPTR + case T_NAPTR: + { + int j; + unsigned char db[4 + 3*256 + DNSNAMEBUFSIZE]; + nptr=db; + /* + * After the preference field, three text strings follow, the maximum length being 255 + * characters for each (this is ensured by the type of *bptr), plus one length byte for + * each, so 3 * 256 = 786 in total. In addition, the name below is up to DNSNAMEBUFSIZE characters + * in size, and the preference field is another 4 bytes in size, so the total length + * that can be taken up is 1028 characters. This means that the whole record will always + * fit into db. + */ + len=4; /* also copy the preference field*/ + for (j=0;j<3;j++) { + if (len>=blcnt) + goto record_too_short; + len += ((unsigned)bptr[len])+1; + } + if(len>blcnt) + goto record_too_short; + memcpy(nptr,bptr,len); + blcnt-=len; + bptr+=len; + nptr+=len; + slen=len; + + /* PDNSD_ASSERT(slen+DNSNAMEBUFSIZE <= sizeof(db), "T_NAPTR: buffer limit reached (name)"); */ + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nptr, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + /*nptr+=len;*/ + slen+=len; + if (blcnt!=0) + goto trailing_junk; + if ((rc=rr_to_cache(centa, oname, type, ttl, slen, db, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif +#if IS_CACHED_IPSECKEY + case T_IPSECKEY: + { + unsigned gwtp; + /* An IPSECKEY record can contain a domain name, so we do some sanity checks just to be sure. */ + if(blcnt<3) goto record_too_short; + gwtp= bptr[1]; + blcnt -= 3; + bptr += 3; + switch(gwtp) { + case 0: goto default_case; + case 1: /* There should be enough room for IPv4 address. */ + if(blcnt<4) goto record_too_short; + goto default_case; + case 2: /* There should be enough room for IPv6 address. */ + if(blcnt<16) goto record_too_short; + goto default_case; + case 3: /* Check that domain name is not compressed. */ + if(isnormalencdomname(bptr,blcnt)) goto default_case; + /* It appears the name is compressed even though RFC 4025 + says it shouldn't be. For the sake of flexibility, we + try to decompress it anyway. */ + { + unsigned char *rbuf, nmbuf[DNSNAMEBUFSIZE]; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nmbuf, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + slen=3+len+blcnt; + rbuf=malloc(slen); + if(!rbuf) return RC_FATALERR; + nptr=mempcpy(rbuf,*ptr,3); + nptr=mempcpy(nptr,nmbuf,len); + memcpy(nptr,bptr,blcnt); + rc=rr_to_cache(centa, oname, type, ttl, slen, rbuf, flags,queryts); + free(rbuf); + if(rc!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; + default: + DEBUG_MSG("rrs2cent: %s record contains unsupported gateway type (%u).\n",getrrtpname(type),gwtp); + return RC_FORMAT; + } + } + break; +#endif +#if IS_CACHED_RRSIG + case T_RRSIG: + /* An RRSIG record contains a domain name, so we do some sanity checks just to be sure. */ + if(blcnt<18) goto record_too_short; + blcnt -= 18; + bptr += 18; + if(isnormalencdomname(bptr,blcnt)) goto default_case; + /* It appears the name is compressed even though RFC 4034 + says it shouldn't be. For the sake of flexibility, we + try to decompress it anyway. */ + { + unsigned char *rbuf, nmbuf[DNSNAMEBUFSIZE]; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nmbuf, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + slen=18+len+blcnt; + rbuf=malloc(slen); + if(!rbuf) return RC_FATALERR; + nptr=mempcpy(rbuf,*ptr,18); + nptr=mempcpy(nptr,nmbuf,len); + memcpy(nptr,bptr,blcnt); + rc=rr_to_cache(centa, oname, type, ttl, slen, rbuf, flags,queryts); + free(rbuf); + if(rc!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif +#if IS_CACHED_NSEC + case T_NSEC: + /* An NSEC record contains a domain name, so we do some sanity checks just to be sure. */ + if(isnormalencdomname(bptr,blcnt)) goto default_case; + /* It appears the name is compressed even though RFC 4034 + says it shouldn't be. For the sake of flexibility, we + try to decompress it anyway. */ + { + unsigned char *rbuf, nmbuf[DNSNAMEBUFSIZE]; + if ((rc=decompress_name(msg, msgsz, &bptr, &blcnt, nmbuf, &len))!=RC_OK) + return rc==RC_TRUNC?RC_FORMAT:rc; + slen=len+blcnt; + rbuf=malloc(slen); + if(!rbuf) return RC_FATALERR; + nptr=mempcpy(rbuf,nmbuf,len); + memcpy(nptr,bptr,blcnt); + rc=rr_to_cache(centa, oname, type, ttl, slen, rbuf, flags,queryts); + free(rbuf); + if(rc!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + break; +#endif + default: + default_case: + if ((rc=rr_to_cache(centa, oname, type, ttl, rdlength, *ptr, flags,queryts))!=RC_OK) { + if(rc==RC_FATALERR) + return rc; + retval=rc; + } + } + } + else { + /* skip otherwise */ + DEBUG_MSG("rrs2cent: ignoring record of type %s (%d), class %s (%d).\n", + getrrtpname(type), type, + class==C_IN?"IN":"[unknown]", class); + } + + *lcnt -= rdlength; + *ptr += rdlength; + } + return retval; + + trailing_junk: + DEBUG_MSG("rrs2cent: %s record has trailing junk.\n",getrrtpname(type)); + return RC_FORMAT; + + record_too_short: + DEBUG_MSG("rrs2cent: %s record too short.\n",getrrtpname(type)); + return RC_FORMAT; + + buffer_overflow: + DEBUG_MSG("rrs2cent: buffer too small to process %s record.\n",getrrtpname(type)); + return RC_FORMAT; + + invalid_length: + DEBUG_MSG("rrs2cent: %s record has length %u.\n",getrrtpname(type),rdlength); + return RC_FORMAT; +} + +/* + * Try to bind the socket to a port in the given port range. Returns 1 on success, or 0 on failure. + */ +static int bind_socket(int s) +{ + int query_port_start=global.query_port_start,query_port_end=global.query_port_end; + + /* + * -1, as a special value for query_port_start, denotes that we let the kernel select + * a port when we first use the socket, which used to be the default. + */ + if (query_port_start >= 0) { + union { +#ifdef ENABLE_IPV4 + struct sockaddr_in sin4; +#endif +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sin6; +#endif + } sin; + socklen_t sinl; + int prt, pstart, range = query_port_end-query_port_start+1, m=0xffff; + unsigned try1,try2, maxtry2; + + if (range<=0 || range>0x10000) { + log_warn("Illegal port range in %s line %d, dropping query!\n",__FILE__,__LINE__); + return 0; + } + if(range<=0x8000) { + /* Find the smallest power of 2 >= range. */ + for(m=1; m= range. */ + for(try1=0;;) { + prt= get_rand16()&m; + if(prt=0x10000) { + log_warn("Cannot get random number < range" + " after %d tries in %s line %d," + " bad random number generator?\n", + try1,__FILE__,__LINE__); + return 0; + } + } + prt += query_port_start; + + for(pstart=prt;;) { +#ifdef ENABLE_IPV4 + if (run_ipv4) { + memset(&sin.sin4,0,sizeof(struct sockaddr_in)); + sin.sin4.sin_family=AF_INET; + sin.sin4.sin_port=htons(prt); + sin.sin4.sin_addr=global.out_a.ipv4; + SET_SOCKA_LEN4(sin.sin4); + sinl=sizeof(struct sockaddr_in); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + memset(&sin.sin6,0,sizeof(struct sockaddr_in6)); + sin.sin6.sin6_family=AF_INET6; + sin.sin6.sin6_port=htons(prt); + sin.sin6.sin6_flowinfo=IPV6_FLOWINFO; + sin.sin6.sin6_addr=global.out_a.ipv6; + SET_SOCKA_LEN6(sin.sin6); + sinl=sizeof(struct sockaddr_in6); + } +#endif + if (bind(s,(struct sockaddr *)&sin,sinl)==-1) { + if (errno!=EADDRINUSE && + errno!=EADDRNOTAVAIL) { /* EADDRNOTAVAIL should not happen here... */ + log_warn("Could not bind to socket: %s\n", strerror(errno)); + return 0; + } + /* If the address is in use, we continue. */ + } else + goto done; + + if(++try2>=maxtry2) { + /* It is possible we missed the free ports by chance, + try scanning the whole range. */ + if (++prt>query_port_end) + prt=query_port_start; + if (prt==pstart) { + /* Wrapped around, scanned the whole range. Give up. */ + log_warn("Out of ports in the range" + " %d-%d, dropping query!\n", + query_port_start,query_port_end); + return 0; + } + } + else /* Try new random number */ + break; + } + } + } +done: + return 1; +} + + +inline static void *realloc_or_cleanup(void *ptr,size_t size) +{ + void *retval=pdnsd_realloc(ptr,size); + if(!retval) + pdnsd_free(ptr); + return retval; +} + +#if defined(NO_TCP_QUERIES) +# define USE_UDP(st) 1 +#elif defined(NO_UDP_QUERIES) +# define USE_UDP(st) 0 +#else /* !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) */ +# define USE_UDP(st) ((st)->qm==UDP_ONLY || (st)->qm==UDP_TCP) + +/* These functions will be used in case a TCP query might fail and we want to try again using UDP. */ + +# define tentative_tcp_query(st) ((st)->qm==TCP_UDP && ((st)->state==QS_TCPWRITE || ((st)->state==QS_TCPREAD && (st)->iolen==0))) + +inline static void switch_to_udp(query_stat_t *st) +{ + st->qm=UDP_ONLY; + st->myrid=get_rand16(); + st->msg->hdr.id=htons(st->myrid); + st->state=QS_UDPINITIAL; + /* st->failed=0; */ +} + +/* This function will be used in case a UDP reply was truncated and we want to try again using TCP. */ + +inline static void switch_to_tcp(query_stat_t *st) +{ + /* PDNSD_ASSERT(st->state==QS_INITIAL || st->state==QS_DONE || st->state==QS_CANCELED, + "Attempt to switch to TCP while a query is in progress."); */ + st->qm=TCP_ONLY; + st->state=QS_INITIAL; + st->failed=0; +} +#endif + + +/* ------ following is the parallel query code. + * It has been observed that a whole lot of name servers are just damn lame, with response time + * of about 1 min. If that slow one is by chance the first server we try, serializing the tries is quite + * sub-optimal. Also when doing serial queries, the timeout values given in the config will add up, which + * is not the Right Thing. Now that serial queries are in place, this is still true for CNAME recursion, + * and for recursion in quest for the holy AA, but not totally for querying multiple servers. + * The impact on network bandwith should be only marginal (given todays bandwith). + * + * The actual strategy is to do (max) PAR_QUERIES parallel queries, and, if these time out or fail, do again + * that number of queries, until we are successful or there are no more servers to query. + * Since the memory footprint of a thread is considerably large on some systems, and because we have better + * control, we will do the parallel queries multiplexed in one thread. + */ + +/* The query state machine that is called from p_exec_query. This is called once for initialization (state + * QS_TCPINITIAL or QS_UDPINITIAL is preset), and the state that it gives back may either be state QS_DONE, + * in which case it must return a return code other than -1 and is called no more for this server + * (except perhaps in UDP mode if TCP failed). If p_query_sm returns -1, then the state machine is in a read + * or write state, and a function higher up the calling chain can setup a poll() or select() together with st->sock. + * If that poll/select is succesful for that socket, p_exec_query is called again and will hand over to p_query_sm. + * So, you can assume that read(), write() and recvfrom() will not block at the start of a state handling when you + * have returned -1 (which means "call again") as last step of the last state handling. */ +static int p_query_sm(query_stat_t *st) +{ + int retval=RC_SERVFAIL,rv; + +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + tryagain: +#endif + switch (st->state){ + /* TCP query code */ +#ifndef NO_TCP_QUERIES + case QS_TCPINITIAL: + if ((st->sock=socket(PDNSD_PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) { + DEBUG_MSG("Could not open socket: %s\n", strerror(errno)); + break; + } + /* sin4 or sin6 is intialized, hopefully. */ + + /* maybe bind */ + if (!bind_socket(st->sock)) { + close(st->sock); + break; + } + + /* transmit query by tcp*/ + /* make the socket non-blocking */ + { + int oldflags = fcntl(st->sock, F_GETFL, 0); + if (oldflags == -1 || fcntl(st->sock,F_SETFL,oldflags|O_NONBLOCK)==-1) { + DEBUG_PDNSDA_MSG("fcntl error while trying to make socket to %s non-blocking: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(errno)); + close(st->sock); + break; + } + } + st->iolen=0; +#ifdef ENABLE_IPV6 + retry_tcp_connect: +#endif + if (connect(st->sock,SOCK_ADDR(st),SIN_LEN)==-1) { + if (errno==EINPROGRESS || errno==EPIPE) { + st->state=QS_TCPWRITE; + /* st->event=QEV_WRITE; */ /* wait for writability; the connect is then done */ + return -1; + } else if (errno==ECONNREFUSED) { + st->s_errno=errno; + DEBUG_PDNSDA_MSG("TCP connection refused by %s\n", PDNSDA2STR(PDNSD_A(st))); + close(st->sock); + goto tcp_failed; /* We may want to try again using UDP */ + } else { + /* Since immediate connect() errors do not cost any time, we do not try to switch the + * server status to offline */ +#ifdef ENABLE_IPV6 + /* if IPv6 connectivity is for some reason unavailable, perhaps the + IPv4 fallback address can still be reached. */ + if(!run_ipv4 && (errno==ENETUNREACH || errno==ENETDOWN) + && st->a4fallback.s_addr!=INADDR_ANY) + { +#if DEBUG>0 + char abuf[ADDRSTR_MAXLEN]; + DEBUG_PDNSDA_MSG("Connecting to %s failed: %s, retrying with IPv4 address %s\n", + PDNSDA2STR(PDNSD_A(st)),strerror(errno), + inet_ntop(AF_INET,&st->a4fallback,abuf,sizeof(abuf))); +#endif + IPV6_MAPIPV4(&st->a4fallback,&st->a.sin6.sin6_addr); + st->a4fallback.s_addr=INADDR_ANY; + goto retry_tcp_connect; + } +#endif + DEBUG_PDNSDA_MSG("Error while connecting to %s: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(errno)); + close(st->sock); + break; + } + } + st->state=QS_TCPWRITE; + /* st->event=QEV_WRITE; */ + /* fall through in case of not EINPROGRESS */ + case QS_TCPWRITE: + { + int rem= dnsmsghdroffset + st->transl - st->iolen; + if(rem>0) { + rv=write(st->sock,((unsigned char*)st->msg)+st->iolen,rem); + if(rv==-1) { + if(errno==EWOULDBLOCK) + return -1; + st->s_errno=errno; + close(st->sock); + if (st->iolen==0 && + (st->s_errno==ECONNREFUSED || st->s_errno==ECONNRESET || + st->s_errno==EPIPE)) + { + /* This error may be delayed from connect() */ + DEBUG_PDNSDA_MSG("TCP connection to %s failed: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(st->s_errno)); + goto tcp_failed; /* We may want to try again using UDP */ + } + DEBUG_PDNSDA_MSG("Error while sending data to %s: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(st->s_errno)); + break; + } + st->iolen += rv; + if(rvstate=QS_TCPREAD; + st->iolen=0; + /* st->event=QEV_READ; */ + /* fall through */ + case QS_TCPREAD: + if(st->iolen==0) { + uint16_t recvl_net; + rv=read(st->sock,&recvl_net,sizeof(recvl_net)); + if(rv==-1 && errno==EWOULDBLOCK) + return -1; + if(rv!=sizeof(recvl_net)) + goto error_receiv_data; + st->iolen=rv; + st->recvl=ntohs(recvl_net); + if(!(st->recvbuf=(dns_hdr_t *)realloc_or_cleanup(st->recvbuf,st->recvl))) { + close(st->sock); + DEBUG_MSG("Out of memory in query.\n"); + retval=RC_FATALERR; + break; + } + } + { + int offset=st->iolen-sizeof(uint16_t); + int rem=st->recvl-offset; + if(rem>0) { + rv=read(st->sock,((unsigned char*)st->recvbuf)+offset,rem); + if(rv==-1) { + if(errno==EWOULDBLOCK) + return -1; + goto error_receiv_data; + } + if(rv==0) + goto error_receiv_data; /* unexpected EOF */ + st->iolen += rv; + if(rvsock); + st->state=QS_DONE; + return RC_OK; + error_receiv_data: + if(rv==-1) st->s_errno=errno; + DEBUG_PDNSDA_MSG("Error while receiving data from %s: %s\n", PDNSDA2STR(PDNSD_A(st)), + rv==-1?strerror(errno):(rv==0 && st->iolen==0)?"no data":"incomplete data"); + close(st->sock); + tcp_failed: +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + if(st->qm==TCP_UDP) { + switch_to_udp(st); + DEBUG_PDNSDA_MSG("TCP query to %s failed. Trying to use UDP.\n", PDNSDA2STR(PDNSD_A(st))); + goto tryagain; + } +#endif + break; +#endif + +#ifndef NO_UDP_QUERIES + /* UDP query code */ + case QS_UDPINITIAL: + if ((st->sock=socket(PDNSD_PF_INET,SOCK_DGRAM,IPPROTO_UDP))==-1) { + DEBUG_MSG("Could not open socket: %s\n", strerror(errno)); + break; + } + + /* maybe bind */ + if (!bind_socket(st->sock)) { + close(st->sock); + break; + } + + /* connect */ +#ifdef ENABLE_IPV6 + retry_udp_connect: +#endif + if (connect(st->sock,SOCK_ADDR(st),SIN_LEN)==-1) { + if (errno==ECONNREFUSED) st->s_errno=errno; +#ifdef ENABLE_IPV6 + /* if IPv6 connectivity is for some reason unavailable, perhaps the + IPv4 fallback address can still be reached. */ + else if(!run_ipv4 && (errno==ENETUNREACH || errno==ENETDOWN) + && st->a4fallback.s_addr!=INADDR_ANY) + { +#if DEBUG>0 + char abuf[ADDRSTR_MAXLEN]; + DEBUG_PDNSDA_MSG("Connecting to %s failed: %s, retrying with IPv4 address %s\n", + PDNSDA2STR(PDNSD_A(st)),strerror(errno), + inet_ntop(AF_INET,&st->a4fallback,abuf,sizeof(abuf))); +#endif + IPV6_MAPIPV4(&st->a4fallback,&st->a.sin6.sin6_addr); + st->a4fallback.s_addr=INADDR_ANY; + goto retry_udp_connect; + } +#endif + DEBUG_PDNSDA_MSG("Error while connecting to %s: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(errno)); + close(st->sock); + break; + } + + /* transmit query by udp*/ + /* send will hopefully not block on a freshly opened socket (the buffer + * must be empty) */ + if (send(st->sock,&st->msg->hdr,st->transl,0)==-1) { + st->s_errno=errno; + DEBUG_PDNSDA_MSG("Error while sending data to %s: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(errno)); + close(st->sock); + break; + } + st->state=QS_UDPRECEIVE; + /* st->event=QEV_READ; */ + return -1; + case QS_UDPRECEIVE: + { + int udpbufsize= (st->edns_query?global.udpbufsize:UDP_BUFSIZE); + if(!(st->recvbuf=(dns_hdr_t *)realloc_or_cleanup(st->recvbuf,udpbufsize))) { + close(st->sock); + DEBUG_MSG("Out of memory in query.\n"); + retval=RC_FATALERR; + break; + } + if ((rv=recv(st->sock,st->recvbuf,udpbufsize,0))==-1) { + st->s_errno=errno; + DEBUG_PDNSDA_MSG("Error while receiving data from %s: %s\n", PDNSDA2STR(PDNSD_A(st)),strerror(errno)); + close(st->sock); + break; + } + st->recvl=rv; + if (st->recvlrecvbuf->id)!=st->myrid) { + DEBUG_MSG("Bad answer received. Ignoring it.\n"); + /* no need to care about timeouts here. That is done at an upper layer. */ + st->state=QS_UDPRECEIVE; + /* st->event=QEV_READ; */ + return -1; + } + close(st->sock); + st->state=QS_DONE; + return RC_OK; + } +#endif + } + + /* If we get here, something has gone wrong. */ + st->state=QS_DONE; + return retval; /* should be either RC_SERVFAIL or RC_FATALERR */ +} + +static dns_cent_t *lookup_cent_array(dns_cent_array ca, const unsigned char *nm) +{ + int i,n=DA_NEL(ca); + for(i=0;iqname,nm)) + return ce; + } + return NULL; +} + +/* Extract the minimum ttl field from the SOA record stored in an rr bucket. */ +static time_t soa_minimum(rr_bucket_t *rrs) +{ + uint32_t minimum; + unsigned char *p=(unsigned char *)(rrs->data); + + /* Skip owner and maintainer. Lengths are validated in cache. */ + p=skiprhn(skiprhn(p)); + /* Skip serial, refresh, retry, expire fields. */ + p += 4*sizeof(uint32_t); + GETINT32(minimum,p); + return minimum; +} + +/* + * The function that will actually execute a query. It takes a state structure in st. + * st->state must be set to QS_INITIAL before calling. + * This may return one of the RC_* codes, where RC_OK indicates success, the other + * RC codes indicate the appropriate errors. -1 is the return value that indicates that + * you should call p_exec_query again with the same state for the result until you get + * a return value >0. Alternatively, call p_cancel_query to cancel it. + * Timeouts are already handled by this function. + * Any records that the query has yielded and that are not a direct answer to the query + * (i.e. are records for other domains) are added to the cache, while the direct answers + * are returned in ent. + * All ns records, to whomever they might belong, are additionally returned in the ns list. + * Free it when done. + * This function calls another query state machine function that supports TCP and UDP. + * + * If you want to tell me that this function has a truly ugly coding style, ah, well... + * You are right, somehow, but I feel it is conceptually elegant ;-) + */ +static int p_exec_query(dns_cent_t **entp, const unsigned char *name, int thint, + query_stat_t *st, dlist *ns, unsigned char *c_soa) +{ + int rv,rcode; + unsigned short rd; + + switch (st->state){ + case QS_INITIAL: { + size_t transl,allocsz; + unsigned int rrnlen=0; + + allocsz= sizeof(dns_msg_t); + if(name) { + rrnlen=rhnlen(name); + allocsz += rrnlen+4; + if(st->edns_query) + allocsz += sizeof_opt_pseudo_rr; + } + st->msg=(dns_msg_t *)pdnsd_malloc(allocsz); + if (!st->msg) { + st->state=QS_DONE; + return RC_FATALERR; /* unrecoverable error */ + } + st->myrid=get_rand16(); + st->msg->hdr.id=htons(st->myrid); + st->msg->hdr.qr=QR_QUERY; + st->msg->hdr.opcode=OP_QUERY; + st->msg->hdr.aa=0; + st->msg->hdr.tc=0; + st->msg->hdr.rd=(name && st->trusted); + st->msg->hdr.ra=0; + st->msg->hdr.z=0; + st->msg->hdr.ad=0; + st->msg->hdr.cd=0; + st->msg->hdr.rcode=RC_OK; + st->msg->hdr.qdcount=htons(name!=NULL); + st->msg->hdr.ancount=0; + st->msg->hdr.nscount=0; + st->msg->hdr.arcount=0; + + transl= sizeof(dns_hdr_t); + if(name) { + unsigned char *p = mempcpy((unsigned char *)(&st->msg->hdr+1),name,rrnlen); + unsigned short qtype=(st->lean_query?thint:QT_ALL); + PUTINT16(qtype,p); + PUTINT16(C_IN,p); + transl += rrnlen+4; + if(st->edns_query) + add_opt_pseudo_rr(&st->msg,&transl,&allocsz, + global.udpbufsize,RC_OK,0,0); + } + st->transl=transl; +#ifndef NO_TCP_QUERIES + st->msg->len=htons(st->transl); +#endif + st->recvbuf=NULL; + st->state=(USE_UDP(st)?QS_UDPINITIAL:QS_TCPINITIAL); + /* fall through */ + } + QS_QUERY_CASES: + tryagain: + rv=p_query_sm(st); + if (rv==-1) { + return -1; + } + if (rv!=RC_OK) { + pdnsd_free(st->msg); + pdnsd_free(st->recvbuf); + st->state=QS_DONE; + if(st->needs_testing) { + switch(st->s_errno) { + case ENETUNREACH: /* network unreachable */ + case EHOSTUNREACH: /* host unreachable */ + case ENOPROTOOPT: /* protocol unreachable */ + case ECONNREFUSED: /* port unreachable */ + case ENETDOWN: /* network down */ + case EHOSTDOWN: /* host down */ +#ifdef ENONET + case ENONET: /* machine not on the network */ +#endif + /* Mark this server as down for a period of time */ + sched_server_test(PDNSD_A(st),1,0); + st->needs_testing=0; + } + } + return rv; + } + /* rv==RC_OK */ + DEBUG_PDNSDA_MSG("Received reply from %s (msg len=%u).\n", PDNSDA2STR(PDNSD_A(st)), st->recvl); + DEBUG_DUMP_DNS_MSG(st->recvbuf, st->recvl); + + /* Basic sanity checks */ + if (st->recvlrecvbuf->id); + if (recvid!=st->myrid) { + DEBUG_MSG("ID mismatch: expected %04x, got %04x!\n", st->myrid, recvid); + goto discard_reply; + } + } + if (st->recvbuf->qr!=QR_RESP) { + DEBUG_MSG("The QR bit indicates this is a query, not a response!\n"); + goto discard_reply; + } + if (st->recvbuf->opcode!=OP_QUERY) { + DEBUG_MSG("Not a reply to a standard query (opcode=%u).\n",st->recvbuf->opcode); + goto discard_reply; + } + + rcode=st->recvbuf->rcode; +#if DEBUG>0 + { + char flgsbuf[DNSFLAGSMAXSTRSIZE]; + DEBUG_MSG("rcode=%u (%s), flags:%s\n", rcode, get_ename(rcode), dnsflags2str(st->recvbuf, flgsbuf)); + } +#endif + if (st->recvbuf->z!=0) { + DEBUG_MSG("Malformed response (nonzero Z bit).\n"); + goto discard_reply; + } + + if(st->needs_testing) { + /* We got an answer from this server, so don't bother with up tests for a while. */ + sched_server_test(PDNSD_A(st),1,1); + st->needs_testing=0; + } + + rv=rcode; + if(rcode==RC_OK || rcode==RC_NAMEERR) { + /* success or at least no requery is needed */ + st->state=QS_DONE; + break; + } + else if (entp) { + if(rcode==RC_SERVFAIL || rcode==RC_NOTSUPP || rcode==RC_REFUSED) { + if (st->msg->hdr.rd && !st->recvbuf->ra) { + /* seems as if we have got no recursion available. + We will have to do it by ourselves (sigh...) */ + DEBUG_PDNSDA_MSG("Server %s returned error code: %s." + " Maybe does not support recursive query?" + " Querying non-recursively.\n", + PDNSDA2STR(PDNSD_A(st)),get_ename(rcode)); + st->msg->hdr.rd=0; + goto resetstate_tryagain; + } + else if(rcode!=RC_SERVFAIL && st->edns_query && st->msg->hdr.arcount) + goto try_withoutedns; + else if (st->recvbuf->ancount && st->auth_serv==2) { + /* The name server returned a failure code, + but the answer section is not empty, + and the answer is from a server lower down the call chain. + Use this answer tentatively (it may be the + best we can get), but remember the failure. */ + DEBUG_PDNSDA_MSG("Server %s returned error code: %s," + " but the answer section is not empty." + " Using the answer tentatively.\n", + PDNSDA2STR(PDNSD_A(st)),get_ename(rcode)); + st->failed=3; + st->state=QS_DONE; + break; + } + } + else if(rcode==RC_FORMAT && st->edns_query && st->msg->hdr.arcount) + try_withoutedns: { + size_t transl; + /* Perhaps the remote server barfs when the query + contains an OPT RR in the additional section. + Try again with an empty addtional section. */ + DEBUG_PDNSDA_MSG("Server %s returned error code: %s." + " Maybe cannot handle EDNS?" + " Querying with empty additional section.\n", + PDNSDA2STR(PDNSD_A(st)),get_ename(rcode)); + transl=remove_opt_pseudo_rr(st->msg,st->transl); + if(transl!=0 && st->msg->hdr.arcount==0) { + st->transl=transl; +#ifndef NO_TCP_QUERIES + st->msg->len=htons(st->transl); +#endif + st->edns_query=0; + resetstate_tryagain: + st->myrid=get_rand16(); + st->msg->hdr.id=htons(st->myrid); + st->state=(USE_UDP(st)?QS_UDPINITIAL:QS_TCPINITIAL); + goto tryagain; + } + else { + DEBUG_PDNSDA_MSG("Internal error: could not remove additional section from query" + " to server %s\n", PDNSDA2STR(PDNSD_A(st))); + } + } + } + + discard_reply: + /* report failure */ + pdnsd_free(st->msg); + pdnsd_free(st->recvbuf); + /*close(st->sock);*/ + st->state=QS_DONE; +#if DEBUG>0 + if(entp) { + DEBUG_PDNSDA_MSG("Discarding reply from server %s\n", PDNSDA2STR(PDNSD_A(st))); + } +#endif + if (rv!=RC_OK) + return rv; + + return RC_SERVFAIL; /* mock error code */ + + default: /* we shouldn't get here */ + st->state=QS_DONE; + return RC_SERVFAIL; /* mock error code */ + } + + /* If we reach this code, we have successfully received an answer, + * because we have returned error codes on errors or -1 on AGAIN conditions. + * So we *should* have a usable dns record in recvbuf by now. + */ + rd= st->msg->hdr.rd; /* Save the 'Recursion Desired' bit of the query. */ + pdnsd_free(st->msg); + if(entp) { + time_t queryts=time(NULL); + size_t lcnt= ((size_t)st->recvl) - sizeof(dns_hdr_t); + unsigned char *rrp=(unsigned char *)(st->recvbuf+1); + dns_cent_array secs[3]={NULL,NULL,NULL}; +# define ans_sec secs[0] +# define auth_sec secs[1] +# define add_sec secs[2] + unsigned short qtype,flags,aa,neg_ans=0,reject_ans=0,num_ns=0; + int numoptrr; + edns_info_t ednsinfo= {0}; + + if (ntohs(st->recvbuf->qdcount)!=1) { + DEBUG_PDNSDA_MSG("Bad number of query records in answer from %s\n", + PDNSDA2STR(PDNSD_A(st))); + rv=RC_SERVFAIL; + goto free_recvbuf_return; + } + /* check & skip the query record. */ + { + unsigned char nbuf[DNSNAMEBUFSIZE]; + if ((rv=decompress_name((unsigned char *)st->recvbuf, st->recvl, &rrp, &lcnt, nbuf, NULL))!=RC_OK) { + DEBUG_PDNSDA_MSG("Cannot decompress QNAME in answer from %s\n", + PDNSDA2STR(PDNSD_A(st))); + rv=RC_SERVFAIL; + goto free_recvbuf_return; + } + if(!rhnicmp(nbuf,name)) { + DEBUG_PDNSDA_MSG("Answer from %s does not match query.\n", + PDNSDA2STR(PDNSD_A(st))); + rv=RC_SERVFAIL; + goto free_recvbuf_return; + } + } + + qtype=(st->lean_query?thint:QT_ALL); + if (lcnt<4) { + DEBUG_PDNSDA_MSG("Format error in reply from %s (message truncated in qtype or qclass).\n", + PDNSDA2STR(PDNSD_A(st))); + rv=RC_SERVFAIL; /* mock error code */ + goto free_recvbuf_return; + } + { + unsigned short qt,qc; + GETINT16(qt,rrp); + GETINT16(qc,rrp); + if(qt!=qtype) { + DEBUG_PDNSDA_MSG("qtype in answer (%u) from %s does not match expected qtype (%u).\n", + qt,PDNSDA2STR(PDNSD_A(st)),qtype); + rv=RC_SERVFAIL; + goto free_recvbuf_return; + } + } + lcnt-=4; + + st->aa= (st->recvbuf->aa && !st->failed); + st->tc= st->recvbuf->tc; + st->ra= (rd && st->recvbuf->ra); + + /* Don't flag cache entries from a truncated reply as authoritative. */ + aa= (st->aa && !st->tc); + flags=st->flags; + if (aa) flags|=CF_AUTH; + + + /* Initialize a dns_cent_t in the array for the answer section */ + if (!(ans_sec=DA_GROW1(ans_sec))) { + rv=RC_FATALERR; /* unrecoverable error */ + goto free_recvbuf_return; + } + /* By marking DF_AUTH, we mean authoritative AND complete. */ + if (!init_cent(&DA_INDEX(ans_sec,0), name, 0, 0, (aa && qtype==QT_ALL)?DF_AUTH:0 DBG1)) { + rv=RC_FATALERR; /* unrecoverable error */ + goto free_centarrays_recvbuf_return; + } + + /* Now read the answer, authority and additional sections, + storing the results in the arrays ans_sec,auth_sec and add_sec. + */ + numoptrr=0; + rv=rrs2cent((unsigned char *)st->recvbuf, st->recvl, &rrp, &lcnt, ntohs(st->recvbuf->ancount), + flags, queryts, &ans_sec, &numoptrr, &ednsinfo); +#if DEBUG>0 + if(numoptrr!=0) { + DEBUG_MSG("Answer section in reply contains %d OPT pseudo-RRs!\n", numoptrr); + } +#endif + numoptrr=0; + if(rv==RC_OK) { + uint16_t nscount=ntohs(st->recvbuf->nscount); + if (nscount) { + rv=rrs2cent((unsigned char *)st->recvbuf, st->recvl, &rrp, &lcnt, nscount, + flags|CF_ADDITIONAL, queryts, &auth_sec, &numoptrr, &ednsinfo); +#if DEBUG>0 + if(numoptrr!=0) { + DEBUG_MSG("Authority section in reply contains %d OPT pseudo-RRs!\n", numoptrr); + } +#endif + } + } + + numoptrr=0; + if(rv==RC_OK) { + uint16_t arcount=ntohs(st->recvbuf->arcount); + if (arcount) { + rv=rrs2cent((unsigned char *)st->recvbuf, st->recvl, &rrp, &lcnt, arcount, + flags|CF_ADDITIONAL, queryts, &add_sec, &numoptrr, &ednsinfo); + if(numoptrr!=0) { +#if DEBUG>0 + if(numoptrr!=1) { + DEBUG_MSG("Additional section in reply contains %d OPT pseudo-RRs!\n", numoptrr); + } + DEBUG_PDNSDA_MSG("Reply from %s contains OPT pseudosection: EDNS version = %u, udp size = %u, flag DO=%u\n", + PDNSDA2STR(PDNSD_A(st)), ednsinfo.version, ednsinfo.udpsize, ednsinfo.do_flg); +#endif + if(rcode!=ednsinfo.rcode) { + DEBUG_PDNSDA_MSG("Reply from %s contains unexpected EDNS rcode %u (%s)!\n", + PDNSDA2STR(PDNSD_A(st)), ednsinfo.rcode, get_ename(ednsinfo.rcode)); + rcode=ednsinfo.rcode; + /* Mark as failed, but use answer tentatively. */ + if(!st->failed) st->failed=1; + } + } + } + } + + if(!(rv==RC_OK || (rv==RC_TRUNC && st->recvbuf->tc))) { + DEBUG_PDNSDA_MSG(rv==RC_FORMAT?"Format error in reply from %s.\n": + rv==RC_TRUNC?"Format error in reply from %s (message unexpectedly truncated).\n": + rv==RC_SERVFAIL?"Inconsistent timestamps in reply from %s.\n": + "Out of memory while processing reply from %s.\n", + PDNSDA2STR(PDNSD_A(st))); + if(rv==RC_SERVFAIL) { + /* Inconsistent ttl timestamps and we are + enforcing strict RFC 2181 compliance. + Mark as failed, but use answer tentatively. */ + if(!st->failed) st->failed=1; + } + else { + if(rv!=RC_FATALERR) rv=RC_SERVFAIL; + goto free_ent_centarrays_recvbuf_return; + } + } + + { + /* Remember references to NS and SOA records in the answer or authority section + so that we can add this information to our own reply. */ + int i,n=DA_NEL(ans_sec); + for(i=0;iqname); + + if(getrrset_NS(cent)) + cent->c_ns=scnt; + if(getrrset_SOA(cent)) + cent->c_soa=scnt; + + if((qtype>=QT_MIN && qtype<=QT_MAX) || + (/* (qtype>=T_MIN && qtype<=T_MAX) && */ getrrset(cent,qtype)) || + (n==1 && cent->num_rrs==0)) + { + /* Match this name with names in the authority section */ + int j,m=DA_NEL(auth_sec); + for(j=0;jqname,cent->qname, &rem, NULL); + if(rem==0 && + /* Don't accept records for the root domain from name servers + that were not listed in the configuration file. */ + (ml || st->auth_serv!=2)) { + if(getrrset_NS(ce)) { + if(cent->c_ns==cundef || cent->c_nsc_ns=ml; + } + if(getrrset_SOA(ce)) { + if(cent->c_soa==cundef || cent->c_soac_soa=ml; + } + } + } + } + } + } + + /* Check whether the answer contains an IP address that should be rejected. */ + if(have_rejectlist(st)) { + int i; + int na4=nreject_a4(st); + addr4maskpair_t *a4arr=rejectlist_a4(st); +#if ALLOW_LOCAL_AAAA + int na6=nreject_a6(st); + addr6maskpair_t *a6arr=rejectlist_a6(st); +#endif + /* Check addresses in the answer, authority and additional sections. */ + for(i=0;i<3;++i) { + dns_cent_array sec=secs[i]; + int j,nce=DA_NEL(sec); + for(j=0;jrrs; rr; rr=rr->next) { + struct in_addr *a=(struct in_addr *)(rr->data); + int k; + for(k=0;ka,&am->mask)) { +#if DEBUG>0 + unsigned char nmbuf[DNSNAMEBUFSIZE]; char abuf[ADDRSTR_MAXLEN]; + DEBUG_PDNSDA_MSG("Rejecting answer from server %s because it contains an A record" + " for \"%s\" with an address in the reject list: %s\n", + PDNSDA2STR(PDNSD_A(st)), + rhn2str(cent->qname,nmbuf,sizeof(nmbuf)), + inet_ntop(AF_INET,a,abuf,sizeof(abuf))); +#endif + reject_ans=1; goto rejectlist_scan_done; + } + } + } + } +#if ALLOW_LOCAL_AAAA + rrset=getrrset_AAAA(cent); + if(rrset && na6) { + rr_bucket_t *rr; + for(rr=rrset->rrs; rr; rr=rr->next) { + struct in6_addr *a=(struct in6_addr *)(rr->data); + int k; + for(k=0;ka,&am->mask)) { +#if DEBUG>0 + unsigned char nmbuf[DNSNAMEBUFSIZE]; char abuf[INET6_ADDRSTRLEN]; + DEBUG_PDNSDA_MSG("Rejecting answer from server %s because it contains an AAAA record" + " for \"%s\" with an address in the reject list: %s\n", + PDNSDA2STR(PDNSD_A(st)), + rhn2str(cent->qname,nmbuf,sizeof(nmbuf)), + inet_ntop(AF_INET6,a,abuf,sizeof(abuf))); +#endif + reject_ans=1; goto rejectlist_scan_done; + } + } + } + } +#endif + } + } + rejectlist_scan_done:; + } + + /* negative caching for domains */ + if (rcode==RC_NAMEERR) { + DEBUG_PDNSDA_MSG("Server %s returned error code: %s\n", PDNSDA2STR(PDNSD_A(st)),get_ename(rcode)); + name_error: + neg_ans=1; + { + /* We did not get what we wanted. Cache according to policy */ + dns_cent_t *ent=&DA_INDEX(ans_sec,0); + int neg_domain_pol=global.neg_domain_pol; + if (neg_domain_pol==C_ON || (neg_domain_pol==C_AUTH && st->aa)) { + time_t ttl=global.neg_ttl; + + /* Try to find a SOA record that came with the reply. + */ + if(ent->c_soa!=cundef) { + unsigned scnt=rhnsegcnt(name); + dns_cent_t *cent; + if(ent->c_soac_soa)))) { + rr_set_t *rrset=getrrset_SOA(cent); + if (rrset && rrset->rrs) { + time_t min=soa_minimum(rrset->rrs); + ttl=rrset->ttl; + if(ttl>min) + ttl=min; + } + } + } + DEBUG_RHN_MSG("Caching domain %s negative with ttl %li\n",RHN2STR(name),(long)ttl); + negate_cent(ent,ttl,queryts); + if(st->nocache) ent->flags |= DF_NOCACHE; + goto cleanup_return_OK; + } else { + if(c_soa) *c_soa=ent->c_soa; + free_cent(ent DBG1); + rv=RC_NAMEERR; + goto add_additional; + } + } + } + + if(reject_ans) { + if(reject_policy(st)==C_NEGATE && st->failed<=1) + goto name_error; + else { + rv=RC_SERVFAIL; + goto free_ent_centarrays_recvbuf_return; + } + } + + if(global.deleg_only_zones && st->auth_serv<3) { /* st->auth_serv==3 means this server is a root-server. */ + int missingdelegation,authcnt; + /* The deleg_only_zones data may change due to runtime reconfiguration, + therefore use locks. */ + lock_server_data(); + missingdelegation=0; authcnt=0; + { + int i,n=DA_NEL(global.deleg_only_zones); unsigned rem,zrem; + for(i=0;iqname,DA_INDEX(global.deleg_only_zones,l),&rem,&zrem) && zrem==0) { + if(rem) break; + else goto try_next_auth; + } + } + goto delegation_OK; + } + try_next_auth:; + } + } +#if DEBUG>0 + { + unsigned char nmbuf[DNSNAMEBUFSIZE],zbuf[DNSNAMEBUFSIZE]; + DEBUG_PDNSDA_MSG(authcnt?"%s is in %s zone, but no delegation found in answer returned by server %s\n" + :"%s is in %s zone, but no authority information provided by server %s\n", + rhn2str(name,nmbuf,sizeof(nmbuf)), rhn2str(DA_INDEX(global.deleg_only_zones,i),zbuf,sizeof(zbuf)), + PDNSDA2STR(PDNSD_A(st))); + } +#endif + missingdelegation=1; + } + delegation_OK:; + } + unlock_server_data(); + + if(missingdelegation) { + if(authcnt && st->failed<=1) { + /* Treat this as a nonexistant name. */ + goto name_error; + } + else if(st->auth_serv<2) { + /* If this is one of the servers obtained from the list + pdnsd was configured with, treat this as a failure. + Hopefully one of the other servers in the list will + return a non-empty authority section. + */ + rv=RC_SERVFAIL; + goto free_ent_centarrays_recvbuf_return; + } + } + } + + { + /* Negative caching of rr sets */ + dns_cent_t *ent=&DA_INDEX(ans_sec,0); + + if(!ent->num_rrs) neg_ans=1; + + if (thint>=T_MIN && thint<=T_MAX && !getrrset(ent,thint) && !st->tc && st->failed<=1) { + /* We did not get what we wanted. Cache according to policy */ + int neg_rrs_pol=global.neg_rrs_pol; + if (neg_rrs_pol==C_ON || (neg_rrs_pol==C_AUTH && aa) || + (neg_rrs_pol==C_DEFAULT && (aa || st->ra))) + { + time_t ttl=global.neg_ttl; + rr_set_t *rrset=getrrset_SOA(ent); + dns_cent_t *cent; + unsigned scnt; + /* If we received a SOA, we should take the ttl of that record. */ + if ((rrset && rrset->rrs) || + /* Try to find a SOA record higher up the hierarchy that came with the reply. */ + ((cent=lookup_cent_array(auth_sec, + (ent->c_soa!=cundef && ent->c_soa<(scnt=rhnsegcnt(name)))? + skipsegs(name,scnt-ent->c_soa): + name)) && + (rrset=getrrset_SOA(cent)) && rrset->rrs)) + { + time_t min=soa_minimum(rrset->rrs); + ttl=rrset->ttl; + if(ttl>min) + ttl=min; + } + DEBUG_RHN_MSG("Caching type %s for domain %s negative with ttl %li\n",getrrtpname(thint),RHN2STR(name),(long)ttl); + if (!add_cent_rrset_by_type(ent, thint, ttl, queryts, CF_NEGATIVE|flags DBG1)) { + rv=RC_FATALERR; + goto free_ent_centarrays_recvbuf_return; + } + } + } + } + + if (st->failed<=1) { + /* The domain names of all name servers found in the answer and authority sections are placed in *ns, + which is automatically grown. */ + /* dns_cent_array secs[2]={ans_sec,auth_sec}; */ + int i; + for(i=0;i<2;++i) { + dns_cent_array sec=secs[i]; + int j,n=DA_NEL(sec); + for(j=0;jqname) || st->auth_serv!=2) && + /* Don't accept possibly poisoning nameserver entries in paranoid mode */ + (st->trusted || !st->nsdomain || (domain_match(st->nsdomain, cent->qname, &rem,NULL),rem==0)) && + /* The following test is actually redundant and should never fail. */ + *(cent->qname)!=0xff) + { + /* Some nameservers obviously choose to send SOA records instead of NS ones. + * Although I think that this is poor behaviour, we'll have to work around that. */ + static const unsigned short nstypes[2]={T_NS,T_SOA}; + int k; + for(k=0;k<2;++k) { + rr_set_t *rrset=getrrset(cent,nstypes[k]); + if(rrset) { + rr_bucket_t *rr; + unsigned short first=1; + for(rr=rrset->rrs; rr; rr=rr->next) { + size_t sz1,sz2; + unsigned char *p; + /* Skip duplicate records */ + for(p=dlist_first(*ns); p; p=dlist_next(p)) { + if(rhnicmp(*p==0xff?p+1:skiprhn(p),(unsigned char *)(rr->data))) + goto next_nsr; + } + /* add to the nameserver list. + Here we use a little compression trick: if + the first byte of a name is 0xff, this means + repeat the previous name. + */ + sz1= (first?rhnlen(cent->qname):1); + sz2=rhnlen((unsigned char *)(rr->data)); + if (!(*ns=dlist_grow(*ns,sz1+sz2))) { + rv=RC_FATALERR; + goto free_ent_centarrays_recvbuf_return; + } + p=dlist_last(*ns); + if(first) { + first=0; + p=mempcpy(p,cent->qname,sz1); + } + else + *p++ = 0xff; /* 0xff means 'idem' */ + /* This will only copy the first name, which is the NS */ + memcpy(p,(unsigned char *)(rr->data),sz2); + ++num_ns; + next_nsr:; + } + } + } + } + } + } + } + cleanup_return_OK: + if(st->failed && neg_ans && num_ns==0) { + DEBUG_PDNSDA_MSG("Answer from server %s does not contain usable records.\n", + PDNSDA2STR(PDNSD_A(st))); + rv=RC_SERVFAIL; + goto free_ns_ent_centarrays_recvbuf_return; + } + if(!(*entp=malloc(sizeof(dns_cent_t)))) { + rv=RC_FATALERR; + goto free_ns_ent_centarrays_recvbuf_return; + } + **entp=DA_INDEX(ans_sec,0); + rv=RC_OK; + add_additional: + if (!st->failed && !reject_ans) { + /* Add the additional RRs to the cache. */ + /* dns_cent_array secs[3]={ans_sec,auth_sec,add_sec}; */ + int i; +#if DEBUG>0 + if(debug_p && neg_ans) { + int j,n=DA_NEL(ans_sec); + for(j=1; jqname) || st->auth_serv!=2) { + unsigned int rem; + if(st->trusted || !st->nsdomain || (domain_match(st->nsdomain, cent->qname, &rem, NULL),rem==0)) + add_cache(cent); + else { +#if DEBUG>0 + unsigned char nmbuf[DNSNAMEBUFSIZE],nsbuf[DNSNAMEBUFSIZE]; + DEBUG_MSG("Record for %s not in nsdomain %s; dropped.\n", + rhn2str(cent->qname,nmbuf,sizeof(nmbuf)),rhn2str(st->nsdomain,nsbuf,sizeof(nsbuf))); +#endif + } + } + else { +#if DEBUG>0 + static const char *const secname[3]={"answer","authority","additional"}; + DEBUG_PDNSDA_MSG("Record(s) for root domain in %s section from %s dropped.\n", secname[i],PDNSDA2STR(PDNSD_A(st))); +#endif + } + } + } + } + goto free_centarrays_recvbuf_return; + + free_ns_ent_centarrays_recvbuf_return: + dlist_free(*ns); *ns=NULL; + free_ent_centarrays_recvbuf_return: + if(DA_NEL(ans_sec)>=1) free_cent(&DA_INDEX(ans_sec,0) DBG1); + free_centarrays_recvbuf_return: + { + /* dns_cent_array secs[3]={ans_sec,auth_sec,add_sec}; */ + int i; + for(i=0;i<3;++i) { + dns_cent_array sec=secs[i]; + int j,n=DA_NEL(sec); + /* The first entry in the answer section is treated separately, so skip that one. */ + for(j= !i; jrecvbuf); + return rv; +} + +/* + * Cancel a query, freeing all resources. Any query state is valid as input (this may even be called + * if a call to p_exec_query already returned error or success) + */ +static void p_cancel_query(query_stat_t *st) +{ + switch (st->state) { + QS_WRITE_CASES: + QS_READ_CASES: + close(st->sock); + /* fall through */ + case QS_TCPINITIAL: + case QS_UDPINITIAL: + pdnsd_free(st->recvbuf); + pdnsd_free(st->msg); + } + if(st->state!=QS_INITIAL && st->state!=QS_DONE) + st->state=QS_CANCELED; +} + +#if 0 +/* + * Initialize a query_serv_t (server list for parallel query) + * This is there for historical reasons only. + */ +inline static void init_qserv(query_stat_array *q) +{ + *q=NULL; +} +#endif + +/* + * Add a server entry to a query_serv_t + * Note: only a reference to nsdomain is copied, not the name itself. + * Be sure to free the q-list before freeing the name. + */ +static int add_qserv(query_stat_array *q, pdnsd_a2 *a, int port, time_t timeout, unsigned flags, + char nocache, char lean_query, char edns_query, char auth_s, char needs_testing, char trusted, + const unsigned char *nsdomain, rejectlist_t *rejectlist) +{ + query_stat_t *qs; + + if ((*q=DA_GROW1(*q))==NULL) { + DEBUG_MSG("Out of memory in add_qserv()\n"); + return 0; + } + + qs=&DA_LAST(*q); +#ifdef ENABLE_IPV4 + if (run_ipv4) { + memset(&qs->a.sin4,0,sizeof(qs->a.sin4)); + qs->a.sin4.sin_family=AF_INET; + qs->a.sin4.sin_port=htons(port); + qs->a.sin4.sin_addr=a->ipv4; + SET_SOCKA_LEN4(qs->a.sin4); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + memset(&qs->a.sin6,0,sizeof(qs->a.sin6)); + qs->a.sin6.sin6_family=AF_INET6; + qs->a.sin6.sin6_port=htons(port); + qs->a.sin6.sin6_flowinfo=IPV6_FLOWINFO; + qs->a.sin6.sin6_addr=a->ipv6; + SET_SOCKA_LEN6(qs->a.sin6); + + qs->a4fallback=a->ipv4; + } +#endif + qs->timeout=timeout; + qs->flags=flags; + qs->nocache=nocache; + qs->auth_serv=auth_s; + qs->lean_query=lean_query; + qs->edns_query=edns_query; + qs->needs_testing=needs_testing; + qs->trusted=trusted; + qs->aa=0; + qs->tc=0; + qs->ra=0; + qs->failed=0; + qs->nsdomain=nsdomain; /* Note: only a reference is copied, not the name itself! */ + qs->rejectlist=rejectlist; + + qs->state=QS_INITIAL; + qs->qm=global.query_method; + qs->s_errno=0; + return 1; +} + +/* Test whether two pdnsd_a2 addresses are the same. */ +inline __attribute__((always_inline)) +static int same_inaddr2_2(pdnsd_a2 *a, pdnsd_a2 *b) +{ + return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr, + IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) && + a->ipv4.s_addr==b->ipv4.s_addr ); +} + +/* This can be used to check whether a server address was already used in a + previous query_stat_t entry. */ +inline static int query_stat_same_inaddr2(query_stat_t *qs, pdnsd_a2 *b) +{ + return SEL_IPVER( qs->a.sin4.sin_addr.s_addr==b->ipv4.s_addr, + IN6_ARE_ADDR_EQUAL(&qs->a.sin6.sin6_addr,&b->ipv6) && + qs->a4fallback.s_addr==b->ipv4.s_addr ); +} + + +/* + * Free resources used by a query_serv_t + * There for historical reasons only. + */ +inline static void del_qserv(query_stat_array q) +{ + da_free(q); +} + +struct qstatnode_s { + query_stat_array qa; + struct qstatnode_s *next; +}; +typedef struct qstatnode_s qstatnode_t; + +struct qhintnode_s { + const unsigned char *nm; + int tp; + struct qhintnode_s *next; +}; +/* typedef struct qhintnode_s qhintnode_t; */ /* Already defined in dns_query.h */ + +static int auth_ok(query_stat_array q, const unsigned char *name, int thint, dns_cent_t *ent, + int hops, qstatnode_t *qslist, qhintnode_t *qhlist, + query_stat_t *qse, dlist ns, query_stat_array *serv); +static int p_dns_cached_resolve(query_stat_array q, const unsigned char *name, int thint, dns_cent_t **cachedp, + int hops, qstatnode_t *qslist, qhintnode_t *qhlist, time_t queryts, + unsigned char *c_soa); +static int simple_dns_cached_resolve(atup_array atup_a, int port, char edns_query, time_t timeout, + const unsigned char *name, int thint, dns_cent_t **cachedp); + + +/* + * Performs a semi-parallel query on the servers in q. PAR_QUERIES are executed parallel at a time. + * name is the query name in dns protocol format (number.string etc), + * ent is the dns_cent_t that will be filled. + * hops is the number of recursions left. + * qslist should refer to a list of server arrays used higher up in the calling chain. This way we can + * avoid name servers that have already been tried for this name. + * qhlist should refer to a list of names that we are trying to resolve higher up in the calling chain. + * These names should be avoided further down the chain, or we risk getting caught in a wasteful cycle. + * thint is a hint on the requested query type used to decide whether an aa record must be fetched + * or a non-authoritative answer will be enough. + * + * nocache is needed because we add AA records to the cache. If the nocache flag is set, we do not + * take the original values for the record, but flags=0 and ttl=0 (but only if we do not already have + * a cached record for that set). These settings cause the record be purged on the next cache addition. + * It will also not be used again. + * + * The return value of p_recursive_query() has the same meaning as that of p_dns_cached_resolve() + * (see below). + */ +static int p_recursive_query(query_stat_array q, const unsigned char *name, int thint, dns_cent_t **entp, + int *nocache, int hops, qstatnode_t *qslist, qhintnode_t *qhlist, + unsigned char *c_soa) +{ + dns_cent_t *ent,*entsave=NULL; + int i,j,k; + int rv=RC_SERVFAIL; + int qualval=0; + query_stat_t *qse=NULL; /* Initialized to inhibit compiler warning */ + dlist ns=NULL,nssave=NULL; + query_stat_array serv=NULL,servsave=NULL; + +# define W_AUTHOK 8 +# define W_NOTFAILED 2 +# define W_NOTTRUNC 1 +# define NOTFAILMASK 6 +# define GOODQUAL (W_AUTHOK+3*W_NOTFAILED) +# define save_query_result(ent,qs,ns,serv,authok) \ + { \ + int qval = authok*W_AUTHOK + (3-qs->failed)*W_NOTFAILED + (!qs->tc)*W_NOTTRUNC; \ + if(entsave && qval>qualval) { \ + /* Free the old copy, because the new result is better. */ \ + free_cent(entsave DBG1); \ + pdnsd_free(entsave); \ + entsave=NULL; \ + del_qserv(servsave); \ + dlist_free(nssave); \ + } \ + if(!entsave) { \ + entsave=ent; \ + servsave=serv; \ + /* The serv array contains references to data within the ns list, \ + so we need to save a copy of the ns list as well! */ \ + if(DA_NEL(serv)>0) nssave=ns; else {nssave=NULL;dlist_free(ns);} \ + qualval=qval; \ + qse=qs; \ + } \ + else { \ + /* We already have a copy, free the present one. */ \ + free_cent(ent DBG1); \ + pdnsd_free(ent); \ + del_qserv(serv); \ + dlist_free(ns); \ + } \ + serv=NULL; \ + ns=NULL; \ + } + + { + time_t ts0=time(NULL),global_timeout=global.timeout; + int dc=0,mc=0,nq=DA_NEL(q),parqueries=global.par_queries; + + for (j=0; jnq) mc=nq; + + /* First, call p_exec_query once for each parallel set to initialize. + * Then, as long as not all have the state QS_DONE or we have a timeout, + * build a poll/select set for all active queries and call them accordingly. */ + for (i=dc;i=j) { + /* The below should not happen any more, but may once again + * (immediate success) */ + DEBUG_PDNSDA_MSG("Sending query to %s\n", PDNSDA2STR(PDNSD_A(qs))); + retryquery: + rv=p_exec_query(&ent, name, thint, qs,&ns,c_soa); + if (rv==RC_OK) { + int authok; + DEBUG_PDNSDA_MSG("Query to %s succeeded.\n", PDNSDA2STR(PDNSD_A(qs))); + if((authok=auth_ok(q, name, thint, ent, hops, qslist, qhlist, qs, ns, &serv))) { + if(authok>=0) { + if(!qs->failed +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + && !(qs->qm==UDP_TCP && qs->tc) +#endif + ) + { + qse=qs; + mc=i; /* No need to cancel queries beyond i */ + goto done; + } + } + else { + mc=i; /* No need to cancel queries beyond i */ + goto free_ent_return_failed; + } + } + /* We do not have a satisfactory answer. + However, we will save a copy in case none of the other + servers in the q list give a satisfactory answer either. + */ + save_query_result(ent,qs,ns,serv,authok); +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + if(qs->qm==UDP_TCP && qs->tc) { + switch_to_tcp(qs); + DEBUG_PDNSDA_MSG("Reply from %s was truncated. Trying again using TCP.\n", + PDNSDA2STR(PDNSD_A(qs))); + goto retryquery; + } +#endif + } + else if (rv==RC_NAMEERR || rv==RC_FATALERR) { + mc=i; /* No need to cancel queries beyond i */ + goto done; + } + } + if (qs->state==QS_DONE && i==dc) + dc++; + } + if (dcstate!=QS_DONE) { + if (i>=j && qs->timeout>maxto) + maxto=qs->timeout; +#ifdef NO_POLL + if (qs->sock>maxfd) { + maxfd=qs->sock; + PDNSD_ASSERT(maxfdstate) { + QS_READ_CASES: + FD_SET(qs->sock,&reads); + break; + QS_WRITE_CASES: + FD_SET(qs->sock,&writes); + break; + } +#else + polls[pc].fd=qs->sock; + switch (qs->state) { + QS_READ_CASES: + polls[pc].events=POLLIN; + break; + QS_WRITE_CASES: + polls[pc].events=POLLOUT; + break; + default: + polls[pc].events=0; + } +#endif + pc++; + } + } + if (pc==0) { + /* In this case, ALL are done and we do not need to cancel any + * query. */ + dc=mc; + break; + } + now=time(NULL); + maxto -= now-ts; + if (mc==nq) { +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + /* Don't use the global timeout if there are TCP queries + we might want to retry using UDP. */ + for (i=j;imaxto) maxto=globto; + } +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + skip_globto:; +#endif + } +#ifdef NO_POLL + tv.tv_sec=(maxto>0)?maxto:0; + tv.tv_usec=0; + nevents=select(maxfd+1,&reads,&writes,NULL,&tv); +#else + nevents=poll(polls,pc,(maxto>0)?(maxto*1000):0); +#endif + if (nevents<0) { + /* if(errno==EINTR) + continue; */ + log_warn("poll/select failed: %s",strerror(errno)); + goto done; + } + if (nevents==0) { + /* We have timed out. Mark the unresponsive servers so that we can consider + them for retesting later on. We will continue to listen for replies from + these servers as long as we have additional servers to try. */ + for (i=j;istate!=QS_DONE && qs->needs_testing) + qs->needs_testing=2; +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + if (tentative_tcp_query(qs)) { + /* We timed out while waiting for a TCP connection. + Try again using UDP. + */ + close(qs->sock); + switch_to_udp(qs); + DEBUG_PDNSDA_MSG("TCP connection to %s timed out. Trying to use UDP.\n", + PDNSDA2STR(PDNSD_A(qs))); + + rv=p_exec_query(&ent, name, thint, qs,&ns,c_soa); + /* In the unlikely case of immediate success */ + if (rv==RC_OK) { + int authok; + DEBUG_PDNSDA_MSG("Query to %s succeeded.\n", PDNSDA2STR(PDNSD_A(qs))); + if((authok=auth_ok(q, name, thint, ent, hops, qslist, qhlist, qs, ns, &serv))) { + if(authok>=0) { + if(!qs->failed) { + qse=qs; + goto done; + } + } + else + goto free_ent_return_failed; + } + save_query_result(ent,qs,ns,serv,authok); + } + else if (rv==RC_NAMEERR || rv==RC_FATALERR) { + goto done; + } + ++nevents; + } +#endif + } +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + if (mc==nq) { + /* We will not try additional servers, but we might want to try again + using UDP instead of TCP + */ + if(nevents && (time(NULL)-ts0)state!=QS_DONE) { + int srv_event=0; + /* This detection may seem suboptimal, but normally, we have at most 2-3 parallel + * queries, and anything else would be higher overhead, */ +#ifdef NO_POLL + switch (qs->state) { + QS_READ_CASES: + srv_event=FD_ISSET(qs->sock,&reads); + break; + QS_WRITE_CASES: + srv_event=FD_ISSET(qs->sock,&writes); + break; + } +#else + do { + PDNSD_ASSERT(icsock); + /* + * In case of an error, reenter the state machine + * to catch it. + */ + switch (qs->state) { + QS_READ_CASES: + srv_event=polls[k].revents&(POLLIN|POLLERR|POLLHUP|POLLNVAL); + break; + QS_WRITE_CASES: + srv_event=polls[k].revents&(POLLOUT|POLLERR|POLLHUP|POLLNVAL); + break; + } +#endif + if (srv_event) { + --nevents; + retryquery2: + rv=p_exec_query(&ent, name, thint, qs,&ns,c_soa); + if (rv==RC_OK) { + int authok; + DEBUG_PDNSDA_MSG("Query to %s succeeded.\n", PDNSDA2STR(PDNSD_A(qs))); + if((authok=auth_ok(q, name, thint, ent, hops, qslist, qhlist, qs, ns, &serv))) { + if(authok>=0) { + if(!qs->failed +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + && !(qs->qm==UDP_TCP && qs->tc) +#endif + ) + { + qse=qs; + goto done; + } + } + else + goto free_ent_return_failed; + } + save_query_result(ent,qs,ns,serv,authok); +#if !defined(NO_TCP_QUERIES) && !defined(NO_UDP_QUERIES) + if(qs->qm==UDP_TCP && qs->tc) { + switch_to_tcp(qs); + DEBUG_PDNSDA_MSG("Reply from %s was truncated. Trying again using TCP.\n", + PDNSDA2STR(PDNSD_A(qs))); + goto retryquery2; + } +#endif + } + else if (rv==RC_NAMEERR || rv==RC_FATALERR) { + goto done; + } + } + } + /* recheck, this might have changed after the last p_exec_query */ + if (qs->state==QS_DONE && i==dc) + dc++; + } + if(nevents>0) { + /* We have not managed to handle all the events reported by poll/select. + Better call it quits, or we risk getting caught in a wasteful cycle. + */ + if(++poll_errs<=MAXPOLLERRS) + log_error("%d unhandled poll/select event(s) in p_recursive_query() at %s, line %d.",nevents,__FILE__,__LINE__); + rv=RC_SERVFAIL; + goto done; + } + } while (dc 1) + ++n; + if(n>0) { + pdnsd_a addrs[n]; /* variable length array */ + k=0; + for (i=0;ineeds_testing > 1) + addrs[k++]= *PDNSD_A(qs); + } + sched_server_test(addrs,n,-1); + } + } + } + + if(entsave) { + /* + * If we didn't get rrs from any of the authoritative servers, or the answers were + * unsatisfactory for another reason, take the one we had. + * However, raise the CF_NOCACHE flag, so that it won't be used again (outside the + * cache latency period). + */ + DEBUG_PDNSDA_MSG("Using %s reply from %s.\n", + !(qualval&NOTFAILMASK)? "reportedly failed": + !(qualval&W_NOTFAILED)? "inconsistent": + !(qualval&W_NOTTRUNC)? "truncated": + !(qualval&W_AUTHOK)? "non-authoritative": "good", + PDNSDA2STR(PDNSD_A(qse))); + ent=entsave; + serv=servsave; + ns=nssave; + if(qualvalflags&DF_NEGATIVE)) { + int jlim= RRARR_LEN(ent); + for (j=0; jflags |= CF_NOCACHE; + } + } + else /* Very unlikely, but not impossible. */ + ent->flags |= DF_NOCACHE; + } + rv=RC_OK; + } + else if (rv!=RC_OK) { + if(rv==RC_FATALERR) { + DEBUG_MSG("Unrecoverable error encountered while processing query.\n"); + rv=RC_SERVFAIL; + } + DEBUG_MSG("%sReturning error code \"%s\"\n", + rv!=RC_NAMEERR? "No query succeeded. ": "", + get_ename(rv)); + goto clean_up_return; + } + + if(nocache) *nocache=qse->nocache; + + if (DA_NEL(serv)>0) { + /* Authority records present. Ask them, because the answer was non-authoritative. */ + qstatnode_t qsn={q,qslist}; + unsigned char save_ns=ent->c_ns,save_soa=ent->c_soa; + + if(qse->aa || qse->ra) { + /* The server claimed to be authoritative or have recursion available, + yet we did not completely trust the answer for some reason. + We will try to ask the servers in the authority records, + but in case we fail, we will save a copy of the answer. */ + entsave=ent; + } + else { + free_cent(ent DBG1); + pdnsd_free(ent); + entsave=NULL; + } + rv=p_dns_cached_resolve(serv, name, thint,&ent,hops-1,&qsn,qhlist,time(NULL),c_soa); + if(rv==RC_OK || rv==RC_CACHED || (rv==RC_STALE && !entsave)) { + if(save_ns!=cundef && (ent->c_ns==cundef || ent->c_nsc_ns=save_ns; + if(save_soa!=cundef && (ent->c_soa==cundef || ent->c_soac_soa=save_soa; + goto free_entsave; + } + else if(rv==RC_NAMEERR) { + if(c_soa && save_soa!=cundef && (*c_soa==cundef || *c_soaaa? "be authoritative": "have recursion available"); + ent=entsave; + rv=RC_OK; + } + } + + clean_up_return: + /* Always free the serv array before freeing the ns list, + because the serv array contains references to data within the ns list! */ + del_qserv(serv); + dlist_free(ns); + + if(rv==RC_OK || rv==RC_CACHED || rv==RC_STALE) *entp=ent; + return rv; +# undef save_query_result +} + +/* auth_ok returns 1 if we don't need an authoritative answer or + if we can find servers to ask for an authoritative answer. + In the latter case these servers will be added to the *serv list. + A return value of 0 means the answer is not satisfactory in the + previous sense. + A return value of -1 indicates an error. +*/ +static int auth_ok(query_stat_array q, const unsigned char *name, int thint, dns_cent_t *ent, + int hops, qstatnode_t *qslist, qhintnode_t *qhlist, + query_stat_t *qse, dlist ns, query_stat_array *serv) +{ + int retval=0; + + /* If the answer was obtained from a name server which returned a failure code, + the answer is never satisfactory. */ + if(qse->failed > 1) return 0; + + /* + Look into the query type hint. If it is a wildcard (QT_*), we need an authoritative answer. + Same if there is no record that answers the query. + This test will also succeed if we have a negative cached record. This is done purposely. + */ +#define aa_needed ((thint>=QT_MIN && thint<=QT_MAX) || \ + ((thint>=T_MIN && thint<=T_MAX) && \ + (!have_rr(ent,thint) && !have_rr_CNAME(ent)))) + + /* We will want to query authoritative servers if all of the following conditions apply: + + 1) The server from which we got the answer was not configured as "proxy only". + 2) The answer is not a negatively cached domain (i.e. the server did not reply with NXDOMAIN). + 3) The query type is a wild card (QT_*), or no record answers the query. + 4) The answer that we have is non-authoritative. + */ + if(!(qse->auth_serv && !(ent->flags&DF_NEGATIVE) && aa_needed)) + return 1; + + if(qse->aa) { + /* The reply we have claims to be authoritative. + However, I have seen cases where name servers raise the authority flag incorrectly (groan...), + so as a work-around, we will check whether the domains for which the servers in the ns + list are responsible, match the queried name better than the domain for which the + last server was responsible. */ + unsigned char *nsdomain; + + if(!qse->nsdomain) + return 1; + + nsdomain=dlist_first(ns); + if(!nsdomain) + return 1; + for(;;) { + unsigned int rem,crem; + domain_match(nsdomain,qse->nsdomain,&rem,&crem); + if(!(rem>0 && crem==0)) + return 1; + domain_match(nsdomain,name,&rem,NULL); + if(rem!=0) + return 1; + do { + nsdomain=dlist_next(nsdomain); + if(!nsdomain) + goto done_checkauth; + } while(*nsdomain==0xff); /* Skip repeats. */ + } + done_checkauth:; + + /* The name servers in the ns list are a better match for the queried name than + the server from which we got the last reply, so ignore the aa flag. + */ +#if DEBUG>0 + if(debug_p) { + unsigned char dbuf[DNSNAMEBUFSIZE],sdbuf[DNSNAMEBUFSIZE]; + nsdomain=dlist_first(ns); + DEBUG_PDNSDA_MSG("The name server %s which is responsible for the %s domain, raised the aa flag, but appears to delegate to the sub-domain %s\n", + PDNSDA2STR(PDNSD_A(qse)), + rhn2str(qse->nsdomain,dbuf,sizeof(dbuf)), + rhn2str(nsdomain,sdbuf,sizeof(sdbuf))); + } +#endif + } + + /* The answer was non-authoritative. Try to build a list of addresses of authoritative servers. */ + if (hops>0) { + unsigned char *nsdomp, *nsdomain=NULL; + rr_set_t *localrrset=NULL; + rr_bucket_t *localrr=NULL; + for (nsdomp=dlist_first(ns);;) { + unsigned char *nsname=NULL; /* Initialize to inhibit compiler warning. */ + int nserva, ia, n; + pdnsd_a2 serva[MAXNAMESERVIPS]; + + /* Get next name server. */ + if(localrr) { + /* Use next locally defined NS record. */ + nsname=(unsigned char *)(localrr->data); + localrr= localrr->next; + } + else { + if(localrrset) { + /* clean up rrset */ + del_rrset(localrrset DBG1); + localrrset=NULL; + } + if(!nsdomp) + break; + else if(*nsdomp!=0xff) { + /* New domain. */ + nsdomain=nsdomp; + if (global.paranoid) { + unsigned int rem; + /* paranoia mode: don't query name servers that are not responsible */ + domain_match(nsdomain,name,&rem,NULL); + if (rem!=0) { +#if DEBUG>0 + unsigned char nmbuf[DNSNAMEBUFSIZE],dbuf[DNSNAMEBUFSIZE],nsbuf[DNSNAMEBUFSIZE]; + DEBUG_MSG("The name server %s is responsible for the %s domain, which does not match %s\n", + rhn2str(nsname,nsbuf,sizeof(nsbuf)), + rhn2str(nsdomain,dbuf,sizeof(dbuf)), + rhn2str(name,nmbuf,sizeof(nmbuf))); +#endif + /* Skip records in ns list for the same domain. */ + do { + nsdomp=dlist_next(nsdomp); + } while (nsdomp && *nsdomp==0xff); + continue; + } + } + /* Check if we have locally defined NS records, because + they will override the ones provided by remote servers. + */ + localrrset=lookup_cache_local_rrset(nsdomain,T_NS); + if(localrrset) { + /* Skip records in ns list for the same domain. */ + do { + nsdomp=dlist_next(nsdomp); + } while (nsdomp && *nsdomp==0xff); + localrr=localrrset->rrs; + if(!localrr) continue; + nsname=(unsigned char *)(localrr->data); + localrr= localrr->next; + } + else { + nsname=skiprhn(nsdomp); + nsdomp=dlist_next(nsdomp); + } + } + else { + /* domain repeated. */ + nsname= nsdomp+1; + nsdomp=dlist_next(nsdomp); + } + } + /* look it up in the cache or resolve it if needed. + The records received should be in the cache now, so it's ok. + */ + nserva=0; + + { + const unsigned char *nm=name; + int tp=thint; + qhintnode_t *ql=qhlist; + + for(;;) { + if(rhnicmp(nm,nsname) && tp==T_A) { + DEBUG_RHN_MSG("Not looking up address for name server \"%s\": " + "risk of infinite recursion.\n",RHN2STR(nsname)); + goto skip_server; + } + if(!ql) break; + nm=ql->nm; + tp=ql->tp; + ql=ql->next; + } + { + qhintnode_t qhn={name,thint,qhlist}; + dns_cent_t *servent; + if (r_dns_cached_resolve(nsname,T_A, &servent, hops-1, &qhn,time(NULL),NULL)==RC_OK) { +#ifdef ENABLE_IPV4 + if (run_ipv4) { + rr_set_t *rrset=getrrset_A(servent); + rr_bucket_t *rrs; + if (rrset) + for(rrs=rrset->rrs; rrs && nservanext) + serva[nserva++].ipv4 = *((struct in_addr *)rrs->data); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + rr_set_t *rrset6=getrrset_AAAA(servent); + rr_bucket_t *rrs6= (rrset6? rrset6->rrs: NULL); + rr_set_t *rrset4=getrrset_A(servent); + rr_bucket_t *rrs4= (rrset4? rrset4->rrs: NULL); + while(nservadata); + rrs6=rrs6->next; + if (rrs4) { + /* Store IPv4 address as fallback. */ + serva[nserva].ipv4 = *((struct in_addr *)rrs4->data); + rrs4=rrs4->next; + } + else + serva[nserva].ipv4.s_addr=INADDR_ANY; + } + else if (rrs4) { + struct in_addr *ina = (struct in_addr *)rrs4->data; + struct in6_addr *in6a = &serva[nserva].ipv6; + IPV6_MAPIPV4(ina,in6a); + serva[nserva].ipv4.s_addr=INADDR_ANY; + rrs4=rrs4->next; + } + else + break; + ++nserva; + } + } +#endif + free_cent(servent DBG1); + pdnsd_free(servent); + } + } + } + +#if DEBUG>0 + if(nserva==0) { + DEBUG_RHN_MSG("Looking up address for name server \"%s\" failed.\n",RHN2STR(nsname)); + } +#endif + n=DA_NEL(*serv); + for(ia=0; iastate==QS_DONE && equiv_inaddr2(PDNSD_A(qs),pserva)) { + DEBUG_PDNSDA_MSG("Not trying name server %s, already queried.\n", PDNSDA2STR(PDNSD_A2_TO_A(pserva))); + goto skip_server_addr; + } + } + if(!ql) break; + qa=ql->qa; + ql=ql->next; + } + } + + /* lean query mode is inherited. CF_AUTH and CF_ADDITIONAL are not (as specified + * in CFF_NOINHERIT). */ + if (!add_qserv(serv, pserva, 53, qse->timeout, qse->flags&~CFF_NOINHERIT, 0, + qse->lean_query,qse->edns_query,2,0,!global.paranoid,nsdomain, + inherit_rejectlist(qse)?qse->rejectlist:NULL)) + { + return -1; + } + retval=1; + skip_server_addr:; + } + skip_server:; + } +#if DEBUG>0 + if(!retval) { + DEBUG_PDNSDA_MSG("No remaining authoritative name servers to try in authority section from %s.\n", PDNSDA2STR(PDNSD_A(qse))); + } +#endif + } + else { + DEBUG_MSG("Maximum hops count reached; not trying any more name servers.\n"); + } + + return retval; + +#undef aa_needed +} + +/* + * This checks the given name to resolve against the access list given for the server using the + * include=, exclude= and policy= parameters. + */ +static int use_server(servparm_t *s, const unsigned char *name) +{ + int i,n=DA_NEL(s->alist); + + for (i=0;ialist,i); + unsigned int nrem,lrem; + domain_match(name,sl->domain,&nrem,&lrem); + if(!lrem && (!sl->exact || !nrem)) + return sl->rule==C_INCLUDED; + } + + if (s->policy==C_SIMPLE_ONLY || s->policy==C_FQDN_ONLY) { + if(rhnsegcnt(name)<=1) + return s->policy==C_SIMPLE_ONLY; + else + return s->policy==C_FQDN_ONLY; + } + + return s->policy==C_INCLUDED; +} + +#if ALLOW_LOCAL_AAAA +#define serv_has_rejectlist(s) ((s)->reject_a4!=NULL || (s)->reject_a6!=NULL) +#else +#define serv_has_rejectlist(s) ((s)->reject_a4!=NULL) +#endif + +/* Take the lists of IP addresses from a server section sp and + convert them into a form that can be used by p_exec_query(). + If successful, add_rejectlist returns a new list which is added to the old list rl, + otherwise the return value is NULL. +*/ +static rejectlist_t *add_rejectlist(rejectlist_t *rl, servparm_t *sp) +{ + int i,na4=DA_NEL(sp->reject_a4); + addr4maskpair_t *a4p; +#if ALLOW_LOCAL_AAAA + int na6=DA_NEL(sp->reject_a6); + addr6maskpair_t *a6p; +#endif + rejectlist_t *rlist = malloc(sizeof(rejectlist_t) + na4*sizeof(addr4maskpair_t) +#if ALLOW_LOCAL_AAAA + + na6*sizeof(addr6maskpair_t) +#endif + ); + + if(rlist) { +#if ALLOW_LOCAL_AAAA + /* Store the larger IPv6 addresses first to avoid possible alignment problems. */ + rlist->na6 = na6; + a6p = (addr6maskpair_t *)rlist->rdata; + for(i=0;ireject_a6,i); +#endif + rlist->na4 = na4; +#if ALLOW_LOCAL_AAAA + a4p = (addr4maskpair_t *)a6p; +#else + a4p = (addr4maskpair_t *)rlist->rdata; +#endif + for(i=0;ireject_a4,i); + + rlist->policy = sp->rejectpolicy; + rlist->inherit = sp->rejectrecursively; + rlist->next = rl; + } + else { + DEBUG_MSG("Out of memory in add_rejectlist()\n"); + } + + return rlist; +} + +inline static void free_rejectlist(rejectlist_t *rl) +{ + while(rl) { + rejectlist_t *next = rl->next; + free(rl); + rl=next; + } +} + +/* Lookup addresses of nameservers provided by root servers for a given domain in the cache. + Returns NULL if unsuccessful (or the cache entries have timed out). +*/ +static addr2_array lookup_ns(const unsigned char *domain) +{ + addr2_array res=NULL; + + dns_cent_t *cent=lookup_cache(domain,NULL); + if(cent) { + rr_set_t *rrset=getrrset_NS(cent); + if(rrset && (rrset->flags&CF_ROOTSERV) && !timedout(rrset)) { + rr_bucket_t *rr; + for(rr=rrset->rrs; rr; rr=rr->next) { + dns_cent_t *servent=lookup_cache((unsigned char*)(rr->data),NULL); + int nserva=0; + pdnsd_a2 serva[MAXNAMESERVIPS]; + if(servent) { +#ifdef ENABLE_IPV4 + if (run_ipv4) { + rr_set_t *rrset=getrrset_A(servent); + rr_bucket_t *rrs; + if (rrset && !timedout(rrset)) + for(rrs=rrset->rrs; rrs && nservanext) + serva[nserva++].ipv4 = *((struct in_addr *)rrs->data); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + rr_set_t *rrset6=getrrset_AAAA(servent); + rr_set_t *rrset4=getrrset_A(servent); + rr_bucket_t *rrs6=NULL, *rrs4=NULL; + if (rrset6 && !(rrset6->flags&CF_NEGATIVE)) { + if(!timedout(rrset6)) { + rrs6= rrset6->rrs; + if (rrs6 && rrset4 && !(rrset4->flags&CF_NEGATIVE)) { + if(timedout(rrset4) || !(rrs4=rrset4->rrs)) + /* Treat this as a failure. */ + rrs6=NULL; + } + } + } + else if (rrset4 && !timedout(rrset4)) + rrs4= rrset4->rrs; + + while(nservadata); + rrs6=rrs6->next; + if (rrs4) { + /* Store IPv4 address as fallback. */ + serva[nserva].ipv4 = *((struct in_addr *)rrs4->data); + rrs4=rrs4->next; + } + else + serva[nserva].ipv4.s_addr=INADDR_ANY; + } + else if (rrs4) { + struct in_addr *ina = (struct in_addr *)rrs4->data; + struct in6_addr *in6a = &serva[nserva].ipv6; + IPV6_MAPIPV4(ina,in6a); + serva[nserva].ipv4.s_addr=INADDR_ANY; + rrs4=rrs4->next; + } + else + break; + ++nserva; + } + } +#endif + free_cent(servent DBG1); + pdnsd_free(servent); + } + if(nserva==0) { + /* Address lookup failed. */ + da_free(res); res=NULL; + break; + } + else { + int i, j, n=DA_NEL(res); + for(i=0; irrs; rr; rr=rr->next) { + dns_cent_t *servent; + int nserva=0; + pdnsd_a2 serva[MAXNAMESERVIPS]; + + rc=simple_dns_cached_resolve(atup_a,port,edns_query,timeout, + (const unsigned char *)(rr->data),T_A,&servent); + if(rc==RC_OK) { +#ifdef ENABLE_IPV4 + if (run_ipv4) { + rr_set_t *rrset=getrrset_A(servent); + rr_bucket_t *rrs; + if (rrset) + for(rrs=rrset->rrs; rrs && nservanext) + serva[nserva++].ipv4 = *((struct in_addr *)rrs->data); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + rr_set_t *rrset6=getrrset_AAAA(servent); + rr_bucket_t *rrs6= (rrset6? rrset6->rrs: NULL); + rr_set_t *rrset4=getrrset_A(servent); + rr_bucket_t *rrs4= (rrset4? rrset4->rrs: NULL); + while(nservadata); + rrs6=rrs6->next; + if (rrs4) { + /* Store IPv4 address as fallback. */ + serva[nserva].ipv4 = *((struct in_addr *)rrs4->data); + rrs4=rrs4->next; + } + else + serva[nserva].ipv4.s_addr=INADDR_ANY; + } + else if (rrs4) { + struct in_addr *ina = (struct in_addr *)rrs4->data; + struct in6_addr *in6a = &serva[nserva].ipv6; + IPV6_MAPIPV4(ina,in6a); + serva[nserva].ipv4.s_addr=INADDR_ANY; + rrs4=rrs4->next; + } + else + break; + ++nserva; + } + } +#endif + free_cent(servent DBG1); + pdnsd_free(servent); + } + else { + DEBUG_RHN_MSG("Simple query for %s type A failed (rc: %s)\n", + RHN2STR((const unsigned char *)(rr->data)),get_ename(rc)); + } + + if(nserva==0) { + /* Address lookup failed. */ + DEBUG_RHN_MSG("Failed to obtain address of root server %s in dns_rootserver_resolv()\n", + RHN2STR((const unsigned char *)(rr->data))); + ++nfail; + } + else { + int i, j, n=DA_NEL(res); + for(i=0; iDA_NEL(res)) { + DEBUG_MSG("Too many root-server resolve failures (%u succeeded, %u failed)," + " rejecting the result.\n", DA_NEL(res),nfail); + da_free(res); res=NULL; + } + } + free_cent_return: + free_cent(cent DBG1); + pdnsd_free(cent); + } + else { + DEBUG_MSG("Simple query for root domain type NS failed (rc: %s)\n",get_ename(rc)); + } + + return res; +} + + +static int p_dns_resolve(const unsigned char *name, int thint, dns_cent_t **cachedp, int hops, qhintnode_t *qhlist, + unsigned char *c_soa) +{ + int i,n,rc; + int one_up=0,seenrootserv=0; + query_stat_array serv=NULL; + rejectlist_t *rejectlist=NULL; + + /* try the servers in the order of their definition */ + lock_server_data(); + n=DA_NEL(servers); + for (i=0;irootserver<=1 && use_server(sp,name)) { + int m=DA_NEL(sp->atup_a); + if(m>0) { + rejectlist_t *rjl=NULL; + int j=0, jstart=0; + if(sp->rand_servers) j=jstart=random()%m; + do { + atup_t *at=&DA_INDEX(sp->atup_a,j); + if (at->is_up) { + if(sp->rootserver) { + if(!seenrootserv) { + int nseg,mseg=1,l=0; + const unsigned char *topdomain=NULL; + addr2_array adrs=NULL; + seenrootserv=1; + nseg=rhnsegcnt(name); + if(nseg>=2) { + static const unsigned char rhn_arpa[6]= {4,'a','r','p','a',0}; + unsigned int rem; + /* Check if the queried name ends in "arpa" */ + domain_match(rhn_arpa, name, &rem,NULL); + if(rem==0) mseg=3; + } + if(nseg<=mseg) { + if(nseg>0) mseg=nseg-1; else mseg=0; + } + for(;mseg>=1; --mseg) { + topdomain=skipsegs(name,nseg-mseg); + adrs=lookup_ns(topdomain); + l=DA_NEL(adrs); + if(l>0) break; + if(adrs) da_free(adrs); + } + if(l>0) { + /* The name servers for this top level domain have been found in the cache. + Instead of asking the root server, we will use this cached information. + */ + int k=0, kstart=0; + if(sp->rand_servers) k=kstart=random()%l; + if(serv_has_rejectlist(sp) && sp->rejectrecursively && !rjl) { + rjl=add_rejectlist(rejectlist,sp); + if(!rjl) {one_up=0; da_free(adrs); goto done;} + rejectlist=rjl; + } + do { + one_up=add_qserv(&serv, &DA_INDEX(adrs,k), 53, sp->timeout, + mk_flag_val(sp)&~CFF_NOINHERIT, sp->nocache, + sp->lean_query, sp->edns_query, 2, 0, + !global.paranoid, topdomain, rjl); + if(!one_up) { + da_free(adrs); + goto done; + } + if(++k==l) k=0; + } while(k!=kstart); + da_free(adrs); + DEBUG_PDNSDA_MSG("Not querying root-server %s, using cached information instead.\n", + PDNSDA2STR(PDNSD_A2_TO_A(&at->a))); + seenrootserv=2; + break; + } + } + else if(seenrootserv==2) + break; + } + if(serv_has_rejectlist(sp) && !rjl) { + rjl=add_rejectlist(rejectlist,sp); + if(!rjl) {one_up=0; goto done;} + rejectlist=rjl; + } + one_up=add_qserv(&serv, &at->a, sp->port, sp->timeout, + mk_flag_val(sp), sp->nocache, sp->lean_query, sp->edns_query, + sp->rootserver?3:(!sp->is_proxy), + needs_testing(sp), 1, NULL, rjl); + if(!one_up) + goto done; + } + if(++j==m) j=0; + } while(j!=jstart); + } + } + } + done: + unlock_server_data(); + if (one_up) { + dns_cent_t *cached; + int nocache; + rc=p_recursive_query(serv, name, thint, &cached, &nocache, hops, NULL, qhlist, c_soa); + if (rc==RC_OK) { + if (!nocache) { + dns_cent_t *tc; + add_cache(cached); + if ((tc=lookup_cache(name,NULL))) { + /* The cache may hold more information than the recent query yielded. + * try to get the merged record. If that fails, revert to the new one. */ + free_cent(cached DBG1); + pdnsd_free(cached); + cached=tc; + /* rc=RC_CACHED; */ + } else + DEBUG_MSG("p_dns_resolve: merging answer with cache failed, using local cent copy.\n"); + } else + DEBUG_MSG("p_dns_resolve: nocache.\n"); + + *cachedp=cached; + } + else if(rc==RC_CACHED || rc==RC_STALE) + *cachedp=cached; + } + else { + DEBUG_MSG("No server is marked up and allowed for this domain.\n"); + rc=RC_SERVFAIL; /* No server up */ + } + del_qserv(serv); + free_rejectlist(rejectlist); + return rc; +} + +static int set_flags_ttl(unsigned short *flags, time_t *ttl, dns_cent_t *cached, int tp) +{ + rr_set_t *rrset=getrrset(cached,tp); + if (rrset) { + time_t t; + *flags|=rrset->flags; + t=rrset->ts+CLAT_ADJ(rrset->ttl); + if (!*ttl || *ttl>t) + *ttl=t; + return 1; + } + return 0; +} + +static void set_all_flags_ttl(unsigned short *flags, time_t *ttl, dns_cent_t *cached) +{ + int i, ilim= RRARR_LEN(cached); + + for(i=0; iflags; + t=rrset->ts+CLAT_ADJ(rrset->ttl); + if (!*ttl || *ttl>t) + *ttl=t; + } + } +} + +/* + Lookup name in the cache, and if records of type thint are found, check whether a requery is needed. + Possible returns values are: + RC_OK: the name is locally defined. + RC_NAMEERR: the name is locally negatively cached. + RC_CACHED: name was found in the cache, requery not needed. + RC_STALE: name was found in the cache, but requery is needed. + RC_NOTCACHED: name was not found in the cache. +*/ +static int lookup_cache_status(const unsigned char *name, int thint, dns_cent_t **cachedp, unsigned short *flagsp, + time_t queryts, unsigned char *c_soa) +{ + dns_cent_t *cached; + int rc=RC_NOTCACHED; + int wild=0; + unsigned short flags=0; + + if ((cached=lookup_cache(name,&wild))) { + short int neg=0,timed=0,need_req=0; + time_t ttl=0; + + if (cached->flags&DF_LOCAL) { +#if DEBUG>0 + { + char dflagstr[DFLAGSTRLEN]; + DEBUG_RHN_MSG("Entry found in cache for '%s' with dflags=%s.\n", + RHN2STR(cached->qname),dflags2str(cached->flags,dflagstr)); + } +#endif + if((cached->flags&DF_NEGATIVE) || wild==w_locnerr) { + if(c_soa) { + if(cached->c_soa!=cundef) + *c_soa=cached->c_soa; + else if(have_rr_SOA(cached)) + *c_soa=rhnsegcnt(cached->qname); + else { + unsigned char *owner=getlocalowner(cached->qname,T_SOA); + if(owner) + *c_soa=rhnsegcnt(owner); + } + } + free_cent(cached DBG1); + pdnsd_free(cached); + rc= RC_NAMEERR; + goto return_rc; + } + else { + rc= RC_OK; + goto return_rc_cent; + } + } + DEBUG_RHN_MSG("Record found in cache for %s\n",RHN2STR(cached->qname)); + if (cached->flags&DF_NEGATIVE) { + if ((ttl=cached->neg.ts+CLAT_ADJ(cached->neg.ttl))>=queryts) + neg=1; + else + timed=1; + } else { + if (thint==QT_ALL) { + set_all_flags_ttl(&flags, &ttl, cached); + } + else if (!set_flags_ttl(&flags, &ttl, cached, T_CNAME) || (getrrset_CNAME(cached)->flags&CF_NEGATIVE)) { + flags=0; ttl=0; + if (thint>=T_MIN && thint<=T_MAX) { + if (set_flags_ttl(&flags, &ttl, cached, thint)) + neg=getrrset(cached,thint)->flags&CF_NEGATIVE && ttl>=queryts; + } + else if (thint==QT_MAILB) { + set_flags_ttl(&flags, &ttl, cached, T_MB); + set_flags_ttl(&flags, &ttl, cached, T_MG); + set_flags_ttl(&flags, &ttl, cached, T_MR); + } + else if (thint==QT_MAILA) { + set_flags_ttl(&flags, &ttl, cached, T_MD); + set_flags_ttl(&flags, &ttl, cached, T_MF); + } + } + if(!(flags&CF_LOCAL)) { + if (thint==QT_ALL) { + if(!(cached->flags&DF_AUTH)) + need_req=1; + } + else if (thint>=QT_MIN && thint<=QT_MAX) { + if(!(flags&CF_AUTH && !(flags&CF_ADDITIONAL))) + need_req=1; + } + if (ttl0 + { + char dflagstr[DFLAGSTRLEN],cflagstr[CFLAGSTRLEN]; + DEBUG_MSG("Requery decision: dflags=%s, cflags=%s, req=%i, neg=%i, timed=%i, %s=%li\n", + dflags2str(cached->flags,dflagstr),cflags2str(flags,cflagstr),need_req,neg,timed, + ttl?"ttl":"timestamp",(long)(ttl?(ttl-queryts):ttl)); + } +#endif + rc = (!neg && (need_req || timed))? RC_STALE: RC_CACHED; + return_rc_cent: + *cachedp=cached; + } + +return_rc: + if(flagsp) *flagsp=flags; + return rc; +} + + +/* + * Resolve records for name into dns_cent_t, type thint. + * q is the set of servers to query from. Set q to NULL if you want to ask the servers registered with pdnsd. + * qslist should refer to a list of server arrays already used higher up the calling chain (may be NULL). + * p_dns_cached_resolve() returns one of the following values: + * RC_OK means that the name was successfully resolved by querying other servers. + * RC_CACHED or RC_STALE means that the name was found in the cache. + * RC_NAMEERR or RC_SERVFAIL indicates a resolve error. + */ +static int p_dns_cached_resolve(query_stat_array q, const unsigned char *name, int thint, dns_cent_t **cachedp, + int hops, qstatnode_t *qslist, qhintnode_t *qhlist, time_t queryts, + unsigned char *c_soa) +{ + dns_cent_t *cached=NULL; + int rc; + unsigned short flags=0; + + DEBUG_RHN_MSG("Starting cached resolve for: %s, query %s\n",RHN2STR(name),get_tname(thint)); + rc= lookup_cache_status(name, thint, &cached, &flags,queryts,c_soa); + if(rc==RC_OK) { + /* Locally defined record. */ + *cachedp=cached; + return RC_CACHED; + } + else if(rc==RC_NAMEERR) /* Locally negated name. */ + return RC_NAMEERR; + + /* update server records set onquery */ + if(global.onquery) test_onquery(); + if (global.lndown_kluge && !(flags&CF_LOCAL)) { + int i,n,linkdown=1; + lock_server_data(); + n=DA_NEL(servers); + for(i=0;irootserver<=1) { + int j,m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j).is_up) { + linkdown=0; + goto done; + } + } + } + } + done: + unlock_server_data(); + if (linkdown) { + DEBUG_MSG("Link is down.\n"); + rc=RC_SERVFAIL; + goto cleanup_return; + } + } + if (rc!=RC_CACHED) { + dns_cent_t *ent; + DEBUG_MSG("Trying name servers.\n"); + if (q) + rc=p_recursive_query(q,name,thint, &ent,NULL,hops,qslist,qhlist,c_soa); + else + rc=p_dns_resolve(name,thint, &ent,hops,qhlist,c_soa); + + if(rc==RC_OK || rc==RC_CACHED || rc==RC_STALE) { + if (cached) { + free_cent(cached DBG1); + pdnsd_free(cached); + } + cached=ent; + } + else if (rc==RC_SERVFAIL && cached && (flags&CF_NOPURGE)) { + /* We could not get a new record, but we have a timed-out cached one + with the nopurge flag set. This means that we shall use it even + if timed out when no new one is available*/ + DEBUG_MSG("Falling back to cached record.\n"); + rc=RC_STALE; + } + else + goto cleanup_return; + } else { + DEBUG_MSG("Using cached record.\n"); + } + *cachedp=cached; + return rc; + + cleanup_return: + if(cached) { + free_cent(cached DBG1); + pdnsd_free(cached); + } + return rc; +} + + +/* r_dns_cached_resolve() is like p_dns_cached_resolve(), except that r_dns_cached_resolve() + will not return negatively cached entries, but returns RC_NAMEERR instead. + It also does not return RC_CACHED or RC_STALE, but RC_OK instead. +*/ +int r_dns_cached_resolve(unsigned char *name, int thint, dns_cent_t **cachedp, + int hops, qhintnode_t *qhlist, time_t queryts, + unsigned char *c_soa) +{ + dns_cent_t *cached; + int rc=p_dns_cached_resolve(NULL,name,thint,&cached,hops,NULL,qhlist,queryts,c_soa); + if(rc==RC_OK || rc==RC_CACHED || rc==RC_STALE) { + if(cached->flags&DF_NEGATIVE) { + if(c_soa) + *c_soa=cached->c_soa; + free_cent(cached DBG1); + pdnsd_free(cached); + return RC_NAMEERR; + } + else { + *cachedp=cached; + return RC_OK; + } + } + return rc; +} + + +static int simple_dns_cached_resolve(atup_array atup_a, int port, char edns_query, time_t timeout, + const unsigned char *name, int thint, dns_cent_t **cachedp) +{ + dns_cent_t *cached=NULL; + int rc; + + DEBUG_RHN_MSG("Starting simple cached resolve for: %s, query %s\n",RHN2STR(name),get_tname(thint)); + rc= lookup_cache_status(name, thint, &cached, NULL, time(NULL), NULL); + if(rc==RC_OK) { + /* Locally defined record. */ + *cachedp=cached; + return RC_OK; + } + else if(rc==RC_NAMEERR) /* Locally negated name. */ + return RC_NAMEERR; + + if (rc!=RC_CACHED) { + query_stat_array qserv; + int j,m; + if (cached) { + free_cent(cached DBG1); + pdnsd_free(cached); + cached=NULL; + } + DEBUG_MSG("Trying name servers.\n"); + qserv=NULL; + m=DA_NEL(atup_a); + for(j=0; jflags&DF_NEGATIVE) { + free_cent(cached DBG1); + pdnsd_free(cached); + return RC_NAMEERR; + } + + *cachedp=cached; + return RC_OK; +} + + +/* Check whether a server is responsive by sending it an (empty) query. + rep is the number of times this is tried in case of no reply. + */ +int query_uptest(pdnsd_a *addr, int port, const unsigned char *name, time_t timeout, int rep) +{ + query_stat_t qs; + int iter=0,rv; + +#ifdef ENABLE_IPV4 + if (run_ipv4) { + memset(&qs.a.sin4,0,sizeof(qs.a.sin4)); + qs.a.sin4.sin_family=AF_INET; + qs.a.sin4.sin_port=htons(port); + qs.a.sin4.sin_addr=addr->ipv4; + SET_SOCKA_LEN4(qs.a.sin4); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + memset(&qs.a.sin6,0,sizeof(qs.a.sin6)); + qs.a.sin6.sin6_family=AF_INET6; + qs.a.sin6.sin6_port=htons(port); + qs.a.sin6.sin6_flowinfo=IPV6_FLOWINFO; + qs.a.sin6.sin6_addr=addr->ipv6; + SET_SOCKA_LEN6(qs.a.sin6); + + qs.a4fallback.s_addr=INADDR_ANY; + } +#endif + qs.timeout=timeout; + qs.flags=0; + qs.nocache=0; + qs.auth_serv=0; + qs.lean_query=1; + qs.edns_query=0; + qs.needs_testing=0; + qs.trusted=1; + qs.aa=0; + qs.tc=0; + qs.ra=0; + qs.failed=0; + qs.nsdomain=NULL; + qs.rejectlist=NULL; + + try_again: + qs.state=QS_INITIAL; + qs.qm=global.query_method; + qs.s_errno=0; + rv=p_exec_query(NULL, name, T_A, &qs, NULL, NULL); + if(rv==-1) { + time_t ts, tpassed; + for(ts=time(NULL), tpassed=0;; tpassed=time(NULL)-ts) { + int event; +#ifdef NO_POLL + fd_set reads; + fd_set writes; + struct timeval tv; + FD_ZERO(&reads); + FD_ZERO(&writes); + PDNSD_ASSERT(qs.socktpassed?timeout-tpassed:0; + tv.tv_usec=0; + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that doing + this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + p_cancel_query(&qs); + return 0; + } + event=select(qs.sock+1,&reads,&writes,NULL,&tv); +#else + struct pollfd pfd; + pfd.fd=qs.sock; + switch (qs.state) { + QS_READ_CASES: + pfd.events=POLLIN; + break; + QS_WRITE_CASES: + pfd.events=POLLOUT; + break; + default: + pfd.events=0; + } + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that doing + this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + p_cancel_query(&qs); + return 0; + } + event=poll(&pfd,1,timeout>tpassed?(timeout-tpassed)*1000:0); +#endif + if (event<0) { + if(errno==EINTR && is_interrupted_servstat_thread()) { + DEBUG_MSG("poll/select interrupted in server status thread.\n"); + } + else + log_warn("poll/select failed: %s",strerror(errno)); + p_cancel_query(&qs); + return 0; + } + if(event==0) { + /* timed out */ + p_cancel_query(&qs); + if(++iter. +*/ + + +#ifndef DNS_QUERY_H +#define DNS_QUERY_H + +#include "cache.h" + +/* Default UDP buffer size (when EDNS is not used). */ +#define UDP_BUFSIZE 512 + + +typedef struct qhintnode_s qhintnode_t; + +/* --- parallel query */ +int r_dns_cached_resolve(unsigned char *name, int thint, dns_cent_t **cachedp, + int hops, qhintnode_t *qhlist, time_t queryts, + unsigned char *c_soa); +#define dns_cached_resolve(name,thint,cachedp,hops,queryts,c_soa) \ + r_dns_cached_resolve(name,thint,cachedp,hops,NULL,queryts,c_soa) + +addr2_array dns_rootserver_resolv(atup_array atup_a, int port, char edns_query, time_t timeout); +int query_uptest(pdnsd_a *addr, int port, const unsigned char *name, time_t timeout, int rep); + +/* --- from dns_answer.c */ +int add_opt_pseudo_rr(dns_msg_t **ans, size_t *sz, size_t *allocsz, + unsigned short udpsize, unsigned short rcode, + unsigned short ednsver, unsigned short Zflags); +size_t remove_opt_pseudo_rr(dns_msg_t *ans, size_t sz); + +#endif diff --git a/jni/pdnsd/src/error.c b/jni/pdnsd/src/error.c new file mode 100644 index 00000000..45848660 --- /dev/null +++ b/jni/pdnsd/src/error.c @@ -0,0 +1,142 @@ +/* error.c - Error handling + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2004, 2005, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "helpers.h" +#include "conff.h" + + +pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER; +volatile short int use_log_lock=0; + +/* + * Initialize a mutex for io-locking in order not to produce gibberish on + * multiple simultaneous errors. + */ +/* This is now defined as an inline function in error.h */ +#if 0 +void init_log_lock(void) +{ + use_log_lock=1; +} +#endif + +/* We crashed? Ooops... */ +void crash_msg(char *msg) +{ + log_error("%s", msg); + log_error("pdnsd probably crashed due to a bug. Please consider sending a bug"); + log_error("report to p.a.rombouts@home.nl or tmoestl@gmx.net"); +} + +/* Log a warning, error or info message. + * If we are a daemon, use the syslog. s is a format string like in printf, + * the optional following arguments are the arguments like in printf */ +void log_message(int prior, const char *s, ...) +{ + int gotlock=0; + va_list va; + FILE *f; + + if (use_log_lock) { + gotlock=softlock_mutex(&loglock); + /* If we failed to get the lock and the type of the + message is "info" or less important, then don't bother. */ + if(!gotlock && prior>=LOG_INFO) + return; + } + if (global.daemon) { + openlog("pdnsd",LOG_PID,LOG_DAEMON); + va_start(va,s); + vsyslog(prior,s,va); + va_end(va); + closelog(); + } + else { + f=stderr; +#if DEBUG > 0 + goto printtofile; + } + if(debug_p) { + f=dbg_file; + printtofile: +#endif + { + char ts[sizeof "* 12/31 23:59:59| "]; + time_t tt = time(NULL); + struct tm tm; + + if(!localtime_r(&tt, &tm) || strftime(ts, sizeof(ts), "* %m/%d %T| ", &tm) <=0) + ts[0]=0; + fprintf(f,"%spdnsd: %s: ", ts, + prior<=LOG_CRIT?"critical": + prior==LOG_ERR?"error": + prior==LOG_WARNING?"warning": + "info"); + } + va_start(va,s); + vfprintf(f,s,va); + va_end(va); + { + const char *p=strchr(s,0); + if(!p || p==s || *(p-1)!='\n') + fputc('\n',f); + } + } + if (gotlock) + pthread_mutex_unlock(&loglock); +} + + +#if DEBUG > 0 +/* XXX: The timestamp generation makes this a little heavy-weight */ +void debug_msg(int c, const char *fmt, ...) +{ + va_list va; + + if (!c) { + char ts[sizeof "12/31 23:59:59"]; + time_t tt = time(NULL); + struct tm tm; + unsigned *id; + + if(localtime_r(&tt, &tm) && strftime(ts, sizeof(ts), "%m/%d %T", &tm) > 0) { + if((id = (unsigned *)pthread_getspecific(thrid_key))) + fprintf(dbg_file,"%u %s| ", *id, ts); + else + fprintf(dbg_file,"- %s| ", ts); + } + } + va_start(va,fmt); + vfprintf(dbg_file,fmt,va); + va_end(va); + fflush(dbg_file); +} +#endif /* DEBUG */ diff --git a/jni/pdnsd/src/error.h b/jni/pdnsd/src/error.h new file mode 100644 index 00000000..1678744e --- /dev/null +++ b/jni/pdnsd/src/error.h @@ -0,0 +1,115 @@ +/* error.h - Error handling + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2004, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef ERROR_H +#define ERROR_H + +#include +#include +#include +#include +#include +#include + +#include "thread.h" +#include "helpers.h" +#include "pdnsd_assert.h" + +/* --- from error.c */ +extern volatile short int use_log_lock; +/* --- */ + +void crash_msg(char *msg); + +inline static void init_log_lock(void) __attribute__((always_inline)); +inline static void init_log_lock(void) +{ + use_log_lock=1; +} + +void log_message(int prior,const char *s, ...) printfunc(2, 3); +#if !defined(CPP_C99_VARIADIC_MACROS) +/* GNU C Macro Varargs style. */ +#define log_error(args...) log_message(LOG_ERR,args) +#define log_warn(args...) log_message(LOG_WARNING,args) +#define log_info(level,args...) {if((level)<=global.verbosity) log_message(LOG_INFO,args);} +#else +/* ANSI C99 style. */ +#define log_error(...) log_message(LOG_ERR,__VA_ARGS__) +#define log_warn(...) log_message(LOG_WARNING,__VA_ARGS__) +#define log_info(level,...) {if((level)<=global.verbosity) log_message(LOG_INFO,__VA_ARGS__);} +#endif + +/* Following are some ugly macros for debug messages that + * should inhibit any code generation when DEBUG is not defined. + * Of course, those messages could be done in a function, but I + * want to save the overhead when DEBUG is not defined. + * debug_p needs to be defined (by including conff.h), or you + * will get strange errors. + * A macro call expands to a complete statement, so a semicolon after + * the macro call is redundant. + * The arguments are normal printfs, so you know how to use the args + */ +#if DEBUG>0 +void debug_msg(int c, const char *fmt, ...) printfunc(2, 3); +/* from main.c */ +extern FILE *dbg_file; +#endif + +#if !defined(CPP_C99_VARIADIC_MACROS) +/* GNU C Macro Varargs style. */ +# if DEBUG > 0 +# define DEBUG_MSG(args...) {if (debug_p) debug_msg(0,args);} +# define DEBUG_MSGC(args...) {if (debug_p) debug_msg(1,args);} +# define DEBUG_PDNSDA_MSG(args...) {char _debugsockabuf[ADDRSTR_MAXLEN]; DEBUG_MSG(args);} +# define PDNSDA2STR(a) pdnsd_a2str(a,_debugsockabuf,sizeof(_debugsockabuf)) +# define DEBUG_RHN_MSG(args...) {unsigned char _debugstrbuf[DNSNAMEBUFSIZE]; DEBUG_MSG(args);} +# define RHN2STR(a) rhn2str(a,_debugstrbuf,sizeof(_debugstrbuf)) +# else +# define DEBUG_MSG(args...) +# define DEBUG_MSGC(args...) +# define DEBUG_PDNSDA_MSG(args...) +# define DEBUG_RHN_MSG(args...) +# endif /* DEBUG > 0 */ +#else +/* ANSI C99 style. */ +# if DEBUG > 0 +/* + * XXX: The ANSI and GCC variadic macros should be merged as far as possible, but that + * might make things even more messy... + */ +# define DEBUG_MSG(...) {if (debug_p) debug_msg(0,__VA_ARGS__);} +# define DEBUG_MSGC(...) {if (debug_p) debug_msg(1,__VA_ARGS__);} +# define DEBUG_PDNSDA_MSG(...) {char _debugsockabuf[ADDRSTR_MAXLEN]; DEBUG_MSG(__VA_ARGS__);} +# define PDNSDA2STR(a) pdnsd_a2str(a,_debugsockabuf,ADDRSTR_MAXLEN) +# define DEBUG_RHN_MSG(...) {unsigned char _debugstrbuf[DNSNAMEBUFSIZE]; DEBUG_MSG(__VA_ARGS__);} +# define RHN2STR(a) rhn2str(a,_debugstrbuf,sizeof(_debugstrbuf)) +# else +# define DEBUG_MSG(...) +# define DEBUG_MSGC(...) +# define DEBUG_PDNSDA_MSG(...) +# define DEBUG_RHN_MSG(...) +# endif /* DEBUG > 0 */ +#endif + +#endif diff --git a/jni/pdnsd/src/freebsd_netinet_ip_icmp.h b/jni/pdnsd/src/freebsd_netinet_ip_icmp.h new file mode 100644 index 00000000..e4577cea --- /dev/null +++ b/jni/pdnsd/src/freebsd_netinet_ip_icmp.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 THE REGENTS OR CONTRIBUTORS 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. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/netinet/ip_icmp.h,v 1.20 2003/03/21 15:28:10 mdodd Exp $ + */ + +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ + +/* + * Interface Control Message Protocol Definitions. + * Per RFC 792, September 1981. + */ + +/* + * Internal of an ICMP Router Advertisement + */ +struct icmp_ra_addr { + u_int32_t ira_addr; + u_int32_t ira_preference; +}; + +/* + * Structure of an icmp header. + */ +struct icmp { + u_char icmp_type; /* type of message, see below */ + u_char icmp_code; /* type sub code */ + u_short icmp_cksum; /* ones complement cksum of struct */ + union { + u_char ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + n_short icd_id; + n_short icd_seq; + } ih_idseq; + int ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + n_short ipm_void; + n_short ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + u_char irt_num_addrs; + u_char irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct id_ts { /* ICMP Timestamp */ + n_time its_otime; /* Originate */ + n_time its_rtime; /* Receive */ + n_time its_ttime; /* Transmit */ + } id_ts; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + struct icmp_ra_addr id_radv; + u_int32_t id_mask; + char id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_radv +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +}; + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enough to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ + +/* + * Definition of type and code field values. + */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_ERRATPTR 0 /* error at param ptr */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ +#define ICMP_PARAMPROB_LENGTH 2 /* bad length */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ + +#define ICMP_MAXTYPE 18 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef _KERNEL +void icmp_error(struct mbuf *, int, int, n_long, struct ifnet *); +void icmp_input(struct mbuf *, int); +#endif + +#endif diff --git a/jni/pdnsd/src/hash.c b/jni/pdnsd/src/hash.c new file mode 100644 index 00000000..12e20740 --- /dev/null +++ b/jni/pdnsd/src/hash.c @@ -0,0 +1,322 @@ +/* hash.c - Manage hashes for cached dns records + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2005 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include "hash.h" +#include "cache.h" +#include "error.h" +#include "helpers.h" +#include "consts.h" + + +/* This is not a perfect hash, but I hope it holds. It is designed for 1024 hash + * buckets, and hashes strings with case-insensitivity. + * It is position-aware in a limited way. + * It is exactly seen a two-way hash: because I do not want to exaggerate + * the hash buckets (i do have 1024), but I hash strings and string-comparisons + * are expensive, I save another 32 bit hash in each hash element that is checked + * before the string. The 32 bit hash is also used to order the entries in a hash chain. + * I hope not to have all too much collision concentration. + * + * The ip hash was removed. I don't think it concentrated the collisions too much. + * If it does, the hash algorithm needs to be changed, rather than using another + * hash. + * Some measurements seem to indicate that the hash algorithm is doing reasonable well. + */ + +dns_hash_ent_t *hash_buckets[HASH_NUM_BUCKETS]; + + +/* + * Hash a dns name (length-byte string format) to HASH_SZ bit. + * *rhash is set to a long int hash. + */ +static unsigned dns_hash(const unsigned char *str, unsigned long *rhash) +{ + unsigned s,i,lb,c; + unsigned long r; + s=0; r=0; + i=0; + while((lb=str[i])) { + s+=lb<<(i%(HASH_SZ-5)); + r+=((unsigned long)lb)<<(i%(8*sizeof(unsigned long)-7)); + ++i; + do { + c=toupper(str[i]); + s+=c<<(i%(HASH_SZ-5)); + r+=((unsigned long)c)<<(i%(8*sizeof(unsigned long)-7)); + ++i; + } while(--lb); + } + s=(s&HASH_BITMASK)+((s&(~HASH_BITMASK))>>HASH_SZ); + s=(s&HASH_BITMASK)+((s&(~HASH_BITMASK))>>HASH_SZ); + s &= HASH_BITMASK; +#ifdef DEBUG_HASH + { + unsigned char buf[DNSNAMEBUFSIZE]; + printf("Diagnostic: hashes for %s: %03x,%04lx\n",rhn2str(str,buf,sizeof(buf)),s,r); + } +#endif + if(rhash) *rhash=r; + return s; +} + +/* + * Initialize hash to hold a dns hash table + */ +/* This is now defined as an inline function in hash.h */ +#if 0 +void mk_dns_hash() +{ + int i; + for(i=0;irhash<=rh) { + if (he->rhash==rh && rhnicmp(key,he->data->qname)) { + retval = he->data; + break; + } + hep = &he->next; + } + if(loc) { + loc->pos = hep; + loc->rhash = rh; + } + return retval; +} + +/* + Add a cache entry to the hash table. + + loc must contain the location where the the new entry should be inserted + (this location can be obtained with dns_lookup). + + add_dns_hash returns 1 on success, or 0 if out of memory. +*/ +int add_dns_hash(dns_cent_t *data, dns_hash_loc_t *loc) +{ + dns_hash_ent_t *he = malloc(sizeof(dns_hash_ent_t)); + + if(!he) + return 0; + + he->next = *(loc->pos); + he->rhash = loc->rhash; + he->data = data; + *(loc->pos) = he; + + return 1; +} + +/* + Delete the hash entry indentified by the location returned by dns_lookup(). +*/ +dns_cent_t *del_dns_hash_ent(dns_hash_loc_t *loc) +{ + dns_hash_ent_t *he = *(loc->pos); + dns_cent_t *data; + + *(loc->pos) = he->next; + data = he->data; + free(he); + return data; +} + +/* + * Delete the first entry indexed by key from the hash. Returns the data field or NULL. + * Since two cents are not allowed to be for the same host name, there will be only one. + */ +dns_cent_t *del_dns_hash(const unsigned char *key) +{ + unsigned idx; + unsigned long rh; + dns_hash_ent_t **hep,*he; + dns_cent_t *data; + + idx = dns_hash(key,&rh); + hep = &hash_buckets[idx]; + while ((he= *hep) && he->rhash<=rh) { + if (he->rhash==rh && rhnicmp(key,he->data->qname)) { + *hep = he->next; + data = he->data; + free(he); + return data; + } + hep = &he->next; + } + return NULL; /* not found */ +} + + +/* + * Delete all entries in a hash bucket. + */ +void free_dns_hash_bucket(int i) +{ + dns_hash_ent_t *he,*hen; + + he=hash_buckets[i]; + hash_buckets[i]=NULL; + while (he) { + hen=he->next; + del_cent(he->data); + free(he); + he=hen; + } +} + +/* + * Delete all entries in a hash bucket whose names match those in + * an include/exclude list. + */ +void free_dns_hash_selected(int i, slist_array sla) +{ + dns_hash_ent_t **hep,*he,*hen; + int j,m=DA_NEL(sla); + + hep= &hash_buckets[i]; + he= *hep; + + while (he) { + unsigned char *name=he->data->qname; + for(j=0;jdomain,&nrem,&lrem); + if(!lrem && (!sl->exact || !nrem)) { + if(sl->rule==C_INCLUDED) + goto delete_entry; + else + break; + } + } + /* default policy is not to delete */ + hep= &he->next; + he= *hep; + continue; + + delete_entry: + *hep=hen=he->next;; + del_cent(he->data); + free(he); + he=hen; + } +} + +/* + * Delete the whole hash table, freeing all memory + */ +void free_dns_hash() +{ + int i; + dns_hash_ent_t *he,*hen; + for (i=0;inext; + del_cent(he->data); + free(he); + he=hen; + } + } +} + +/* + * The following functions are for iterating over the hash. + * fetch_first returns the data field of the first element (or NULL if there is none), and fills pos + * for subsequent calls of fetch_next. + * fetch_next returns the data field of the element after the element that was returned by the last + * call with the same position argument (or NULL if there is none) + * + * Note that these are designed so that you may actually delete the elements you retrieved from the hash. + */ +dns_cent_t *fetch_first(dns_hash_pos_t *pos) +{ + int i; + for (i=0;ibucket=i; + pos->ent=he->next; + return he->data; + } + } + return NULL; +} + +dns_cent_t *fetch_next(dns_hash_pos_t *pos) +{ + dns_hash_ent_t *he=pos->ent; + int i; + if (he) { + pos->ent=he->next; + return he->data; + } + + for (i=pos->bucket+1;ibucket=i; + pos->ent=he->next; + return he->data; + } + } + return NULL; +} + +#ifdef DEBUG_HASH +void dumphash() +{ + if(debug_p) { + int i, j; + dns_hash_ent_t *he; + + for (i=0; inext, j++) ; + DEBUG_MSG("bucket %d: %d entries\n", i, j); + } + } +} +#endif diff --git a/jni/pdnsd/src/hash.h b/jni/pdnsd/src/hash.h new file mode 100644 index 00000000..db25a34f --- /dev/null +++ b/jni/pdnsd/src/hash.h @@ -0,0 +1,83 @@ +/* hash.h - Manage hashes for cached dns records + + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2003, 2005 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _HASH_H_ +#define _HASH_H_ +#include +#include "cache.h" + +typedef struct dns_hash_ent_s { + struct dns_hash_ent_s *next; + unsigned long rhash; /* this is a better hash */ + dns_cent_t *data; +} dns_hash_ent_t; + +/* Redefine this if you want another hash size. Should work ;-). + * The number of hash buckets is computed as power of two; + * so, e.g. HASH_SZ set to 10 yields 1024 hash rows (2^10 or 1<<10). + * Only powers of two are possible conveniently. + * HASH_SZ may not be bigger than 32 (if you set it even close to that value, + * you are nuts.) */ +/* #define HASH_SZ 10 */ /* Now defined in config.h */ +#define HASH_NUM_BUCKETS (1<. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipvers.h" +#include "thread.h" +#include "error.h" +#include "helpers.h" +#include "cache.h" +#include "conff.h" + + +/* + * This is to exit pdnsd from any thread. + */ +void pdnsd_exit() +{ + pthread_kill(main_thrid,SIGTERM); + pthread_exit(NULL); +} + +/* + * Try to grab a mutex. If we can't, fail. This will loop until we get the + * mutex or fail. This is only used in debugging code or at exit, otherwise + * we might run into lock contention problems. + */ +int softlock_mutex(pthread_mutex_t *mutex) +{ + unsigned int tr=0; + while(pthread_mutex_trylock(mutex)) { + if (++tr>=SOFTLOCK_MAXTRIES) + return 0; + usleep_r(10000); + } + return 1; +} + +/* + * setuid() and setgid() for a specified user. + */ +int run_as(const char *user) +{ + if (user[0]) { +#ifdef HAVE_GETPWNAM_R + struct passwd pwdbuf, *pwd; + size_t buflen; + int err; + + for(buflen=128;; buflen*=2) { + char buf[buflen]; /* variable length array */ + + /* Note that we use getpwnam_r() instead of getpwnam(), + which returns its result in a statically allocated buffer and + cannot be considered thread safe. + Doesn't use NSS! */ + err=getpwnam_r(user, &pwdbuf, buf, buflen, &pwd); + if(err==0 && pwd) { + /* setgid first, because we may not be allowed to do it anymore after setuid */ + if (setgid(pwd->pw_gid)!=0) { + log_error("Could not change group id to that of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } + + /* initgroups uses NSS, so we can disable it, + i.e. we might need DNS for LDAP lookups, which times out */ + if (global.use_nss && (initgroups(user, pwd->pw_gid)!=0)) { + log_error("Could not initialize the group access list of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } + if (setuid(pwd->pw_uid)!=0) { + log_error("Could not change user id to that of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } + break; + } + else if(err!=ERANGE) { + if(err) + log_error("run_as user '%s' could not be found: %s",user,strerror(err)); + else + log_error("run_as user '%s' could not be found.",user); + return 0; + } + else if(buflen>=16*1024) { + /* If getpwnam_r() seems defective, call it quits rather than + keep on allocating ever larger buffers until we crash. */ + log_error("getpwnam_r() requires more than %u bytes of buffer space.",(unsigned)buflen); + return 0; + } + /* Else try again with larger buffer. */ + } +#else + /* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */ + struct passwd *pwd; + + if (!(pwd=getpwnam(user))) { + log_error("run_as user %s could not be found.",user); + return 0; + } + /* setgid first, because we may not allowed to do it anymore after setuid */ + if (setgid(pwd->pw_gid)!=0) { + log_error("Could not change group id to that of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } + /* initgroups uses NSS, so we can disable it, + i.e. we might need DNS for LDAP lookups, which times out */ + if (global.use_nss && (initgroups(user, pwd->pw_gid)!=0)) { + log_error("Could not initialize the group access list of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } + if (setuid(pwd->pw_uid)!=0) { + log_error("Could not change user id to that of run_as user '%s': %s", + user,strerror(errno)); + return 0; + } +#endif + } + + return 1; +} + +/* + * returns whether c is allowed in IN domain names + */ +#if 0 +int isdchar (unsigned char c) +{ + if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='-' +#ifdef UNDERSCORE + || c=='_' +#endif + ) + return 1; + return 0; +} +#endif + +/* + * Convert a string given in dotted notation to the transport format (length byte prepended + * domain name parts, ended by a null length sequence) + * The memory areas referenced by str and rhn may not overlap. + * The buffer rhn points to is assumed to be at least DNSNAMEBUFSIZE bytes in size. + * + * Returns 1 if successful, otherwise 0. + */ +int str2rhn(const unsigned char *str, unsigned char *rhn) +{ + unsigned int i,j; + + if(*str=='.' && !*(str+1)) { + /* Special case: root domain */ + rhn[0]=0; + return 1; + } + + for(i=0;;) { + unsigned int jlim= i+63; + if(jlim>DNSNAMEBUFSIZE-2) jlim=DNSNAMEBUFSIZE-2; /* DNSNAMEBUFSIZE-2 because the termination 0 has to follow */ + for(j=i; str[j] && str[j]!='.'; ++j) { + if(j>=jlim) return 0; + rhn[j+1]=str[j]; + } + if(!str[j]) + break; + if(j<=i) + return 0; + rhn[i]=(unsigned char)(j-i); + i = j+1; + } + + rhn[i]=0; + if (j>i || i==0) + return 0; + return 1; +} + +/* + parsestr2rhn is essentially the same as str2rhn, except that it doesn't look beyond + the first len chars in the input string. It also tolerates strings + not ending in a dot and returns a message in case of an error. + */ +const char *parsestr2rhn(const unsigned char *str, unsigned int len, unsigned char *rhn) +{ + unsigned int i,j; + + if(len>0 && *str=='.' && (len==1 || !*(str+1))) { + /* Special case: root domain */ + rhn[0]=0; + return NULL; + } + + i=0; + do { + unsigned int jlim= i+63; + if(jlim>DNSNAMEBUFSIZE-2) jlim=DNSNAMEBUFSIZE-2; + for(j=i; j=jlim) + return "Domain name element too long"; + rhn[j+1]=str[j]; + } + + if(j<=i) { + if(j=2) + str[j++]='.'; + } + else { + do { + for (;lb;--lb) { + unsigned char c; + if(j+2>=size) + goto overflow; + c=rhn[i++]; + if(isgraph(c)) { + if(c=='.' || c=='\\' || c=='"') { + str[j++]='\\'; + if(j+2>=size) + goto overflow; + } + str[j++]=c; + } + else { + unsigned int rem=size-1-j; + int n=snprintf(charp &str[j],rem,"\\%03o",c); + if(n<0 || n>=rem) { + str[j++]='.'; + goto overflow; + } + j+=n; + } + } + str[j++]='.'; + lb=rhn[i++]; + } while(lb); + } + str[j]=0; + return str; + + overflow: + j=size; + str[--j]=0; + if(j>0) { + str[--j]='.'; + if(j>0) { + str[--j]='.'; + if(j>0) + str[--j]='.'; + } + } + return str; +} + +/* Return the length of a domain name in transport format. + The definition has in fact been moved to helpers.h as an inline function. + Note added by Paul Rombouts: + Compared to the definition used by Thomas Moestl (strlen(rhn)+1), the following definition of rhnlen + may yield a different result in certain error situations (when a domain name segment contains null byte). +*/ +#if 0 +unsigned int rhnlen(const unsigned char *rhn) +{ + unsigned int i=0,lb; + + while((lb=rhn[i++])) + i+=lb; + return i; +} +#endif + +/* + * Non-validating rhn copy (use with checked or generated data only). + * Returns number of characters copied. The buffer dst points to is assumed to be DNSNAMEBUFSIZE (or + * at any rate large enough) bytes in size. + * The answer assembly code uses this; it is guaranteed to not clobber anything + * after the name. + */ +unsigned int rhncpy(unsigned char *dst, const unsigned char *src) +{ + unsigned int len = rhnlen(src); + + PDNSD_ASSERT(len<=DNSNAMEBUFSIZE,"rhncpy: src too long!"); + memcpy(dst,src,len>DNSNAMEBUFSIZE?DNSNAMEBUFSIZE:len); + return len; +} + + +/* Check whether a name is a normal wire-encoded domain name, + i.e. is not compressed, doesn't use extended labels and is not + too long. +*/ +int isnormalencdomname(const unsigned char *rhn, unsigned maxlen) +{ + unsigned int i,lb; + + if(maxlen>DNSNAMEBUFSIZE) + maxlen=DNSNAMEBUFSIZE; + for(i=0;;) { + if(i>=maxlen) return 0; + lb=rhn[i++]; + if(lb==0) break; + if(lb>0x3f) return 0; + i += lb; + } + + return 1; +} + +int str2pdnsd_a(const char *addr, pdnsd_a *a) +{ +#ifdef ENABLE_IPV4 + if (run_ipv4) { + return inet_aton(addr,&a->ipv4); + } +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + /* Try to map an IPv4 address to IPv6 */ + struct in_addr a4; + if(inet_aton(addr,&a4)) { + a->ipv6=global.ipv4_6_prefix; + ((uint32_t *)(&a->ipv6))[3]=a4.s_addr; + return 1; + } + return inet_pton(AF_INET6,addr,&a->ipv6)>0; + } +#endif + /* return 0; */ +} + +/* definition moved to helpers.h */ +#if 0 +int is_inaddr_any(pdnsd_a *a) +{ + return SEL_IPVER( a->ipv4.s_addr==INADDR_ANY, + IN6_IS_ADDR_UNSPECIFIED(&a->ipv6) ); +} +#endif + +/* + * This is used for user output only, so it does not matter when an error occurs. + */ +const char *pdnsd_a2str(pdnsd_a *a, char *buf, int maxlen) +{ + const char *res= SEL_IPVER( inet_ntop(AF_INET,&a->ipv4,buf,maxlen), + inet_ntop(AF_INET6,&a->ipv6,buf,maxlen) ); + if (!res) { + log_error("inet_ntop: %s", strerror(errno)); + return "?.?.?.?"; + } + + return res; +} + + +/* Appropriately set our random device */ +#ifdef R_DEFAULT +# if (TARGET == TARGET_BSD) && !defined(__NetBSD__) +# define R_ARC4RANDOM 1 +# else +# define R_RANDOM 1 +# endif +#endif + +#ifdef RANDOM_DEVICE +FILE *rand_file; +#endif + +#ifdef R_RANDOM +void init_crandom() +{ + struct timeval tv; + struct timezone tz; + + gettimeofday(&tv,&tz); + srandom(tv.tv_sec^tv.tv_usec); /* not as guessable as time() */ +} +#endif + +/* initialize the PRNG */ +int init_rng() +{ +#ifdef RANDOM_DEVICE + if (!(rand_file=fopen(RANDOM_DEVICE,"r"))) { + log_error("Could not open %s.",RANDOM_DEVICE); + return 0; + } +#endif +#ifdef R_RANDOM + init_crandom(); +#endif + return 1; +} + +/* The following function is now actually defined as a macro in helpers.h */ +#if 0 +void free_rng() +{ +#ifdef RANDOM_DEVICE + if (rand_file) + fclose(rand_file); +#endif +} +#endif + +/* generate a (more or less) random number 16 bits long. */ +unsigned short get_rand16() +{ +#ifdef RANDOM_DEVICE + unsigned short rv; + + if (rand_file) { + if (fread(&rv,sizeof(rv),1, rand_file)!=1) { + log_error("Error while reading from random device: %s", strerror(errno)); + pdnsd_exit(); + } + return rv&0xffff; + } else + return random()&0xffff; +#endif +#ifdef R_RANDOM + return random()&0xffff; +#endif +#ifdef R_ARC4RANDOM + return arc4random()&0xffff; +#endif +} + +/* fsprintf does formatted output to a file descriptor. + The functionality is similar to fprintf, but note that fd + is of type int instead of FILE*. + This function has been rewritten by Paul Rombouts */ +int fsprintf(int fd, const char *format, ...) +{ + int n; + va_list va; + + { + char buf[256]; + + va_start(va,format); + n=vsnprintf(buf,sizeof(buf),format,va); + va_end(va); + + if(n<(int)sizeof(buf)) { + if(n>0) n=write_all(fd,buf,n); + return n; + } + } + /* retry with a right sized buffer, needs glibc 2.1 or higher to work */ + { + unsigned bufsize=n+1; + char buf[bufsize]; + + va_start(va,format); + n=vsnprintf(buf,bufsize,format,va); + va_end(va); + + if(n>0) n=write_all(fd,buf,n); + } + return n; +} + +/* Convert data into a hexadecimal representation (for debugging purposes).. + The result is stored in the character array buf. + If buf is not large enough to hold the result, the + truncation is indicated by trailing dots. +*/ +void hexdump(const void *data, int dlen, char *buf, int buflen) +{ + const unsigned char *p=data; + int i,j=0; + for(i=0;i=rem) goto truncated; + j += n; + } + goto done; + + truncated: + if(j>=6) { + j -= 3; + if(j+4>=buflen) + j -= 3; + buf[j++]=' '; + buf[j++]='.'; + buf[j++]='.'; + buf[j++]='.'; + } + else { + int ndots=buflen-1; + if(ndots>3) ndots=3; + j=0; + while(j=size) + return -1; + c=in[i]; + if(!isprint(c)) { + int rem=size-j; + int n=snprintf(&str[j],rem,"\\%03o",c); + if(n<0 || n>=rem) { + return -1; + } + j+=n; + } + else { + if(c=='\\' || c=='"') { + str[j++]='\\'; + if(j+1>=size) + return -1; + } + str[j++]=c; + } + } + str[j]=0; + return j; +} + +/* + * This is not like strcmp, but will return 1 on match or 0 if the + * strings are different. + */ +/* definition moved to helpers.h as an inline function. */ +#if 0 +int stricomp(char *a, char *b) +{ + int i; + if (strlen(a) != strlen(b)) + return 0; + for (i=0;i= dstsz-1 && o!='\0') + return 0; + return 1; +} +#endif + +#ifndef HAVE_GETLINE +/* Note by Paul Rombouts: I know that getline is a GNU extension and is not really portable, + but the alternative standard functions have some real problems. + The following substitute does not have exactly the same semantics as the GNU getline, + but it should be good enough, as long as the stream doesn't contain any null chars. + This version is actually based on fgets_realloc() that I found in the WWWOFFLE source. +*/ + +#define BUFSIZE 256 +int getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line=*lineptr; + size_t sz=*n,i; + + if(!line || sz=sz) { + /* retry with a right sized buffer, needs glibc 2.1 or higher to work */ + sz=n+1; + { + char *tmp=realloc(line,sz); + if(tmp) { + line=tmp; + n=vsnprintf(line,sz,format,vasave); + } + else + n= -1; + } + } + va_end(vasave); + + if(n>=0) + *lineptr=line; + else + free(line); + return n; +} +#endif + +#ifndef HAVE_ASPRINTF +int asprintf (char **lineptr, const char *format, ...) +{ + int n; + va_list va; + + va_start(va,format); + n=vasprintf(lineptr,format,va); + va_end(va); + + return n; +} +#endif + +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size) +{ + const char *rc = NULL; + + if (src != NULL && dst != NULL && size > 0) { + switch (af) { + case AF_INET: + { + const unsigned char *p=src; + int n = snprintf(dst, size, "%u.%u.%u.%u", + p[0],p[1],p[2],p[3]); + if (n >= 0 && n < size) rc = dst; + } + break; + +#ifdef AF_INET6 + case AF_INET6: + { + const unsigned char *p=src; + unsigned int i,offs=0; + for (i=0;i<16;i+=2) { + int n=snprintf(dst+offs, size-offs,i==0?"%x":":%x", ((unsigned)p[i]<<8)|p[i+1]); + if(n<0) return NULL; + offs+=n; + if(offs>=size) return NULL; + } + rc = dst; + } + break; +#endif + } + } + + return rc; +} +#endif diff --git a/jni/pdnsd/src/helpers.h b/jni/pdnsd/src/helpers.h new file mode 100644 index 00000000..e45c56ee --- /dev/null +++ b/jni/pdnsd/src/helpers.h @@ -0,0 +1,319 @@ +/* helpers.h - Various helper functions + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2007, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef HELPERS_H +#define HELPERS_H + +#include +#include +#include +#include +#include +#include "cache.h" +#include "pdnsd_assert.h" + +#define SOFTLOCK_MAXTRIES 1000 + +int run_as(const char *user); +void pdnsd_exit(void); +int softlock_mutex(pthread_mutex_t *mutex); + +#if 0 +inline static int isdchar (unsigned char c) +{ + return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='-' +#ifdef UNDERSCORE + || c=='_' +#endif + ); +} +#endif + +const unsigned char *rhn2str(const unsigned char *rhn, unsigned char *str, unsigned int size); +int str2rhn(const unsigned char *str, unsigned char *rhn); +const char *parsestr2rhn(const unsigned char *str, unsigned int len, unsigned char *rhn); + +/* Note added by Paul Rombouts: + Compared to the definition used by Thomas Moestl (strlen(rhn)+1), the following definition of rhnlen + may yield a different result in certain error situations (when a domain name segment contains a null byte). +*/ +inline static unsigned int rhnlen(const unsigned char *rhn) + __attribute__((always_inline)); +inline static unsigned int rhnlen(const unsigned char *rhn) +{ + unsigned int i=0,lb; + + while((lb=rhn[i++])) + i+=lb; + return i; +} + +/* Skip k segments in a name in length-byte string notation. */ +inline static const unsigned char *skipsegs(const unsigned char *nm, unsigned k) + __attribute__((always_inline)); +inline static const unsigned char *skipsegs(const unsigned char *nm, unsigned k) +{ + unsigned lb; + for(;k && (lb= *nm); --k) { + nm += lb+1; + } + return nm; +} + +/* Skip a name in length-byte string notation and return a pointer to the + position right after the terminating null byte. +*/ +inline static unsigned char *skiprhn(unsigned char *rhn) + __attribute__((always_inline)); +inline static unsigned char *skiprhn(unsigned char *rhn) +{ + unsigned lb; + + while((lb= *rhn++)) + rhn += lb; + return rhn; +} + +/* count the number of name segments of a name in length-byte string notation. */ +inline static unsigned int rhnsegcnt(const unsigned char *rhn) + __attribute__((always_inline)); +inline static unsigned int rhnsegcnt(const unsigned char *rhn) +{ + unsigned int res=0,lb; + + while((lb= *rhn)) { + ++res; + rhn += lb+1; + } + return res; +} + +unsigned int rhncpy(unsigned char *dst, const unsigned char *src); +int isnormalencdomname(const unsigned char *rhn, unsigned maxlen); + +inline static int is_inaddr_any(pdnsd_a *a) __attribute__((always_inline)); +inline static int is_inaddr_any(pdnsd_a *a) +{ + return SEL_IPVER( a->ipv4.s_addr==INADDR_ANY, + IN6_IS_ADDR_UNSPECIFIED(&a->ipv6) ); +} + + +inline static int same_inaddr(pdnsd_a *a, pdnsd_a *b) + __attribute__((always_inline)); +inline static int same_inaddr(pdnsd_a *a, pdnsd_a *b) +{ + return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr, + IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) ); +} + +/* Compare a pdnsd_a* with a pdnsd_a2*. */ +inline static int same_inaddr2(pdnsd_a *a, pdnsd_a2 *b) + __attribute__((always_inline)); +inline static int same_inaddr2(pdnsd_a *a, pdnsd_a2 *b) +{ + return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr, + IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) && b->ipv4.s_addr==INADDR_ANY ); +} + +inline static int equiv_inaddr2(pdnsd_a *a, pdnsd_a2 *b) + __attribute__((always_inline)); +inline static int equiv_inaddr2(pdnsd_a *a, pdnsd_a2 *b) +{ + return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr, + IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) || + (b->ipv4.s_addr!=INADDR_ANY && ADDR_EQUIV6_4(&a->ipv6,&b->ipv4)) ); +} + +int str2pdnsd_a(const char *addr, pdnsd_a *a); +const char *pdnsd_a2str(pdnsd_a *a, char *buf, int maxlen); + +int init_rng(void); +#ifdef RANDOM_DEVICE +extern FILE *rand_file; +/* Because this is usually empty, it is now defined as a macro to save overhead.*/ +#define free_rng() {if (rand_file) fclose(rand_file);} +#else +#define free_rng() +#endif + +unsigned short get_rand16(void); + +int fsprintf(int fd, const char *format, ...) printfunc(2, 3); +#if !defined(CPP_C99_VARIADIC_MACROS) +/* GNU C Macro Varargs style. */ +# define fsprintf_or_return(args...) {int _retval; if((_retval=fsprintf(args))<0) return _retval;} +#else +/* ANSI C99 style variadic macro. */ +# define fsprintf_or_return(...) {int _retval; if((_retval=fsprintf(__VA_ARGS__))<0) return _retval;} +#endif + +/* Added by Paul Rombouts */ +inline static ssize_t write_all(int fd,const void *data,size_t n) + __attribute__((always_inline)); +inline static ssize_t write_all(int fd,const void *data,size_t n) +{ + ssize_t written=0; + + while(written +int vasprintf (char **lineptr, const char *format, va_list va); +#endif + +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + +#define strlitlen(strlit) (sizeof(strlit)-1) + +#endif /* HELPERS_H */ diff --git a/jni/pdnsd/src/icmp.c b/jni/pdnsd/src/icmp.c new file mode 100644 index 00000000..6e3e46fe --- /dev/null +++ b/jni/pdnsd/src/icmp.c @@ -0,0 +1,544 @@ +/* icmp.c - Server response tests using ICMP echo requests + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2005, 2007, 2012 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +/* + * This should now work on both Linux and FreeBSD (and CYGWIN?). If anyone + * with experience in other Unix flavors wants to contribute platform-specific + * code, he is very welcome. + */ + +#include +#ifdef HAVE_SYS_POLL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "ipvers.h" +#if (TARGET==TARGET_LINUX) +# include +# include +# include +#elif (TARGET==TARGET_BSD) +# include +# include +# include +#elif (TARGET==TARGET_CYGWIN) +# include +# include +# include +# include "freebsd_netinet_ip_icmp.h" +#else +# error Unsupported platform! +#endif +#ifdef ENABLE_IPV6 +# include +# include +#endif +#include +#include "icmp.h" +#include "error.h" +#include "helpers.h" +#include "servers.h" + + +#define ICMP_MAX_ERRS 10 +static volatile unsigned long icmp_errs=0; /* This is only here to minimize log output. + Since the consequences of a race is only + one log message more/less (out of + ICMP_MAX_ERRS), no lock is required. */ + +volatile int ping_isocket=-1; +#ifdef ENABLE_IPV6 +volatile int ping6_isocket=-1; +#endif + +/* different names, same thing... be careful, as these are macros... */ +#if (TARGET==TARGET_LINUX) +# define ip_saddr saddr +# define ip_daddr daddr +# define ip_hl ihl +# define ip_p protocol +#else +# define icmphdr icmp +# define iphdr ip +# define ip_saddr ip_src.s_addr +# define ip_daddr ip_dst.s_addr +#endif + +#if (TARGET==TARGET_LINUX) +# define icmp_type type +# define icmp_code code +# define icmp_cksum checksum +# define icmp_id un.echo.id +# define icmp_seq un.echo.sequence +#else +# define ICMP_DEST_UNREACH ICMP_UNREACH +# define ICMP_TIME_EXCEEDED ICMP_TIMXCEED +#endif + +#define ICMP_BASEHDR_LEN 8 +#define ICMP4_ECHO_LEN ICMP_BASEHDR_LEN + +#if (TARGET==TARGET_LINUX) || (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN) +/* + * These are the ping implementations for Linux/FreeBSD in their IPv4/ICMPv4 and IPv6/ICMPv6 versions. + * I know they share some code, but I'd rather keep them separated in some parts, as some + * things might go in different directions there. + */ + +/* Initialize the sockets for pinging */ +void init_ping_socket() +{ + if ((ping_isocket=socket(PF_INET, SOCK_RAW, IPPROTO_ICMP))==-1) { + log_warn("icmp ping: socket() failed: %s",strerror(errno)); + } +#ifdef ENABLE_IPV6 + if (!run_ipv4) { + /* Failure to initialize the IPv4 ping socket is not + necessarily a problem, as long as the IPv6 version works. */ + if ((ping6_isocket=socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6))==-1) { + log_warn("icmpv6 ping: socket() failed: %s",strerror(errno)); + } + } +#endif +} + +/* Takes a packet as send out and a received ICMP packet and looks whether the ICMP packet is + * an error reply on the sent-out one. packet is only the packet (without IP header). + * errmsg includes an IP header. + * to is the destination address of the original packet (the only thing that is actually + * compared of the IP header). The RFC says that we get at least 8 bytes of the offending packet. + * We do not compare more, as this is all we need.*/ +static int icmp4_errcmp(char *packet, int plen, struct in_addr *to, char *errmsg, int elen, int errtype) +{ + struct iphdr iph; + struct icmphdr icmph; + struct iphdr eiph; + char *data; + + /* XXX: lots of memcpy to avoid unaligned accesses on alpha */ + if (elen= ICMP_BASEHDR_LEN, "icmp4_errcmp: ICMP_BASEHDR_LEN botched"); + memcpy(&icmph,errmsg+iph.ip_hl*4,ICMP_BASEHDR_LEN); + memcpy(&eiph,errmsg+iph.ip_hl*4+ICMP_BASEHDR_LEN,sizeof(eiph)); + if (elens_addr, &eiph.ip_daddr, sizeof(to->s_addr))==0 && + memcmp(data, packet, plen<8?plen:8)==0; +} + +/* IPv4/ICMPv4 ping. Called from ping (see below) */ +static int ping4(struct in_addr addr, int timeout, int rep) +{ + int i; + int isock; +#if (TARGET==TARGET_LINUX) + struct icmp_filter f; +#endif + unsigned short id=(unsigned short)get_rand16(); /* randomize a ping id */ + + isock=ping_isocket; + +#if (TARGET==TARGET_LINUX) + /* Fancy ICMP filering -- only on Linux (as far is I know) */ + + /* In fact, there should be macros for treating icmp_filter, but I haven't found them in Linux 2.2.15. + * So, set it manually and unportable ;-) */ + /* This filter lets ECHO_REPLY (0), DEST_UNREACH(3) and TIME_EXCEEDED(11) pass. */ + /* !(0000 1000 0000 1001) = 0xff ff f7 f6 */ + f.data=0xfffff7f6; + if (setsockopt(isock,SOL_RAW,ICMP_FILTER,&f,sizeof(f))==-1) { + if (++icmp_errs<=ICMP_MAX_ERRS) { + log_warn("icmp ping: setsockopt() failed: %s", strerror(errno)); + } + return -1; + } +#endif + + for (i=0;i> 16) + (sum & 0xffff); + sum += (sum >> 16); + icmpd.icmp_cksum=~sum; + + memset(&to,0,sizeof(to)); + to.sin_family=AF_INET; + to.sin_port=0; + to.sin_addr=addr; + SET_SOCKA_LEN4(to); + if (sendto(isock,&icmpd,ICMP4_ECHO_LEN,0,(struct sockaddr *)&to,sizeof(to))==-1) { + if (++icmp_errs<=ICMP_MAX_ERRS) { + log_warn("icmp ping: sendto() failed: %s.",strerror(errno)); + } + return -1; + } + /* listen for reply. */ + tm=time(NULL); tpassed=0; + do { + int psres; +#ifdef NO_POLL + fd_set fds,fdse; + struct timeval tv; + FD_ZERO(&fds); + PDNSD_ASSERT(isocktpassed?timeout-tpassed:0; + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that the effort + to do this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + return -1; + } + psres=select(isock+1,&fds,NULL,&fdse,&tv); +#else + struct pollfd pfd; + pfd.fd=isock; + pfd.events=POLLIN; + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that the effort + to do this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + return -1; + } + psres=poll(&pfd,1,timeout>tpassed?(timeout-tpassed)*1000:0); +#endif + + if (psres<0) { + if(errno==EINTR && is_interrupted_servstat_thread()) { + DEBUG_MSG("poll/select interrupted in server status thread.\n"); + } + else if (++icmp_errs<=ICMP_MAX_ERRS) { + log_warn("poll/select failed: %s",strerror(errno)); + } + return -1; + } + if (psres==0) /* timed out */ + break; + +#ifdef NO_POLL + if (FD_ISSET(isock,&fds) || FD_ISSET(isock,&fdse)) +#else + if (pfd.revents&(POLLIN|POLLERR)) +#endif + { + char buf[1024]; + socklen_t sl=sizeof(from); + int len; + + if ((len=recvfrom(isock,&buf,sizeof(buf),0,(struct sockaddr *)&from,&sl))!=-1) { + if (len>sizeof(struct iphdr)) { + struct iphdr iph; + + memcpy(&iph, buf, sizeof(iph)); + if (len-iph.ip_hl*4>=ICMP_BASEHDR_LEN) { + struct icmphdr icmpp; + + memcpy(&icmpp, ((uint32_t *)buf)+iph.ip_hl, sizeof(icmpp)); + if (iph.ip_saddr==addr.s_addr && icmpp.icmp_type==ICMP_ECHOREPLY && + ntohs(icmpp.icmp_id)==id && ntohs(icmpp.icmp_seq)<=i) { + return (i-ntohs(icmpp.icmp_seq))*timeout+(time(NULL)-tm); /* return the number of ticks */ + } else { + /* No regular echo reply. Maybe an error? */ + if (icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, &to.sin_addr, buf, len, ICMP_DEST_UNREACH) || + icmp4_errcmp((char *)&icmpd, ICMP4_ECHO_LEN, &to.sin_addr, buf, len, ICMP_TIME_EXCEEDED)) { + return -1; + } + } + } + } + } else { + return -1; /* error */ + } + } + else { + if (++icmp_errs<=ICMP_MAX_ERRS) { + log_error("Unhandled poll/select event in ping4() at %s, line %d.",__FILE__,__LINE__); + } + return -1; + } + tpassed=time(NULL)-tm; + } while (tpassedtpassed?timeout-tpassed:0; + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that the effort + to do this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + return -1; + } + psres=select(isock+1,&fds,NULL,&fdse,&tv); +#else + struct pollfd pfd; + pfd.fd=isock; + pfd.events=POLLIN; + /* There is a possible race condition with the arrival of a signal here, + but it is so unlikely to be a problem in practice that the effort + to do this properly is not worth the trouble. + */ + if(is_interrupted_servstat_thread()) { + DEBUG_MSG("server status thread interrupted.\n"); + return -1; + } + psres=poll(&pfd,1,timeout>tpassed?(timeout-tpassed)*1000:0); +#endif + + if (psres<0) { + if(errno==EINTR && is_interrupted_servstat_thread()) { + DEBUG_MSG("poll/select interrupted in server status thread.\n"); + } + else if (++icmp_errs<=ICMP_MAX_ERRS) { + log_warn("poll/select failed: %s",strerror(errno)); + } + return -1; + } + if (psres==0) /* timed out */ + break; + +#ifdef NO_POLL + if (FD_ISSET(isock,&fds) || FD_ISSET(isock,&fdse)) +#else + if (pfd.revents&(POLLIN|POLLERR)) +#endif + { + char buf[1024]; + socklen_t sl=sizeof(from); + int len; + if ((len=recvfrom(isock,&buf,sizeof(buf),0,(struct sockaddr *)&from,&sl))!=-1) { + if (len>=sizeof(struct icmp6_hdr)) { + /* we get packets without IPv6 header, luckily */ + struct icmp6_hdr icmpp; + + memcpy(&icmpp, buf, sizeof(icmpp)); + if (IN6_ARE_ADDR_EQUAL(&from.sin6_addr,&a) && + ntohs(icmpp.icmp6_id)==id && ntohs(icmpp.icmp6_seq)<=i) { + return (i-ntohs(icmpp.icmp6_seq))*timeout+(time(NULL)-tm); /* return the number of ticks */ + } else { + /* No regular echo reply. Maybe an error? */ + if (icmp6_errcmp((char *)&icmpd, sizeof(icmpd), &from.sin6_addr, buf, len, ICMP6_DST_UNREACH) || + icmp6_errcmp((char *)&icmpd, sizeof(icmpd), &from.sin6_addr, buf, len, ICMP6_TIME_EXCEEDED)) { + return -1; + } + } + } + } else { + return -1; /* error */ + } + } + else { + if (++icmp_errs<=ICMP_MAX_ERRS) { + log_error("Unhandled poll/select event in ping6() at %s, line %d.",__FILE__,__LINE__); + } + return -1; + } + tpassed=time(NULL)-tm; + } while (tpassedipv4,timeout,rep); +#endif +#ifdef ENABLE_IPV6 + ELSE_IPV6 { + /* If it is a IPv4 mapped IPv6 address, we prefer ICMPv4. */ + if (ping_isocket!=-1 && IN6_IS_ADDR_V4MAPPED(&addr->ipv6)) { + struct in_addr v4; + v4.s_addr=((uint32_t *)&addr->ipv6)[3]; + return ping4(v4,timeout,rep); + } else + return ping6(addr->ipv6,timeout,rep); + } +#endif + return -1; +} + +#else +# error "Huh! No OS macro defined!" +#endif /*(TARGET==TARGET_LINUX) || (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN)*/ diff --git a/jni/pdnsd/src/icmp.h b/jni/pdnsd/src/icmp.h new file mode 100644 index 00000000..3fa6778c --- /dev/null +++ b/jni/pdnsd/src/icmp.h @@ -0,0 +1,43 @@ +/* icmp.h - Server response tests using ICMP echo requests + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2007 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef ICMP_H +#define ICMP_H + + +#include +#include "ipvers.h" + +volatile extern int ping_isocket; +volatile extern int ping6_isocket; + +/* initialize a socket for pinging */ +void init_ping_socket(void); + +/* + * This is a classical ping routine. + * timeout in 10ths of seconds, rep is the repetition count. + */ + +int ping(pdnsd_a *addr, int timeout, int rep); + +#endif diff --git a/jni/pdnsd/src/ipvers.h b/jni/pdnsd/src/ipvers.h new file mode 100644 index 00000000..b1d7a2cd --- /dev/null +++ b/jni/pdnsd/src/ipvers.h @@ -0,0 +1,297 @@ +/* ipvers.h - definitions for IPv4 and IPv6 + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2007, 2009 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef IPVERS_H +#define IPVERS_H + +#include +#include +#include +#include +#include +#include "rr_types.h" + +#if defined(ENABLE_IPV4) && !defined(ENABLE_IPV6) +# ifdef DEFAULT_IPV4 +# undef DEFAULT_IPV4 +# endif +# define DEFAULT_IPV4 1 +#endif + +#if !defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +# ifdef DEFAULT_IPV4 +# undef DEFAULT_IPV4 +# endif +# define DEFAULT_IPV4 0 +#endif + +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +# define ELSE_IPV6 else +#else +# define ELSE_IPV6 +#endif + +/* From main.c */ +#ifdef ENABLE_IPV4 +# ifdef ENABLE_IPV6 +extern short int run_ipv4; +extern short int cmdlineipv; +# define SEL_IPVER(a4,a6) (run_ipv4? a4: a6) +# else +# define run_ipv4 1 +# define SEL_IPVER(a4,a6) (a4) +# endif +#else +# define run_ipv4 0 +# define SEL_IPVER(a4,a6) (a6) +#endif +#ifdef ENABLE_IPV6 +#define DEFAULT_IPV4_6_PREFIX "::ffff:0.0.0.0" +/* extern short int cmdlineprefix; */ +#endif + +#if (TARGET==TARGET_LINUX) && !defined(HAVE_STRUCT_IN_PKTINFO) +struct in_pktinfo +{ + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; +#endif + +#if (TARGET==TARGET_LINUX) +/* some older glibc versions seem to lack this. */ +# ifndef IP_PKTINFO +# define IP_PKTINFO 8 +# endif +# ifndef CMSG_LEN +/* ---- from glibc 2.1.2 */ + +/* Ancillary data object manipulation macros. */ +# if !defined __STRICT_ANSI__ && defined __GNUC__ && __GNUC__ >= 2 +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +# else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +# endif +# define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +# define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +# define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \ + & ~(sizeof (size_t) - 1)) +# define CMSG_SPACE(len) (CMSG_ALIGN (len) \ + + CMSG_ALIGN (sizeof (struct cmsghdr))) +# define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) +extern struct cmsghdr *__cmsg_nxthdr __P ((struct msghdr *__mhdr, + struct cmsghdr *__cmsg)); +# ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg) __THROW +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) >= ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + >= ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +# endif /* Use `extern inline'. */ +/* ---- */ +# endif +#endif + +#if defined(ENABLE_IPV4) && !defined(SIN_LEN) && (TARGET==TARGET_BSD) +# define SIN_LEN +#endif + +#if defined(ENABLE_IPV6) && (TARGET==TARGET_LINUX) + +/* Some glibc versions (I know of 2.1.2) get this wrong, so we define our own. To be exact, this is fixed + * glibc code. */ +#ifdef IN6_ARE_ADDR_EQUAL +# undef IN6_ARE_ADDR_EQUAL +#endif +#define IN6_ARE_ADDR_EQUAL(a,b) \ + ((((uint32_t *) (a))[0] == ((uint32_t *) (b))[0]) && \ + (((uint32_t *) (a))[1] == ((uint32_t *) (b))[1]) && \ + (((uint32_t *) (a))[2] == ((uint32_t *) (b))[2]) && \ + (((uint32_t *) (a))[3] == ((uint32_t *) (b))[3])) + +#endif + +/* This is the IPv6 flowid that we pass on to the IPv6 protocol stack. This value was not currently defined + * at the time of writing. Should this change, define a appropriate flowinfo here. */ +#ifndef IPV6_FLOWINFO +#define IPV6_FLOWINFO 0 +#endif + +/* There does not seem to be a function/macro to generate IPv6-mapped IPv4-Adresses. So here comes mine. + * Pass an in_addr* and an in6_addr* */ +#define IPV6_MAPIPV4(a,b) {((uint32_t *)(b))[3]=(a)->s_addr; \ + ((uint32_t *)(b))[2]=htonl(0xffff); \ + ((uint32_t *)(b))[1]=((uint32_t *)(b))[0]=0; } + +/* A macro to extract the pointer to the address of a struct sockaddr (_in or _in6) */ + +#define SOCKA_A4(a) ((pdnsd_a *)&((struct sockaddr_in *)(a))->sin_addr) +#define SOCKA_A6(a) ((pdnsd_a *)&((struct sockaddr_in6 *)(a))->sin6_addr) + +#define SOCKA_A(a) SEL_IPVER(SOCKA_A4(a),SOCKA_A6(a)) +#define PDNSD_PF_INET SEL_IPVER(PF_INET,PF_INET6) +#define PDNSD_AF_INET SEL_IPVER(AF_INET,AF_INET6) + +/* This is to compare two addresses. This is a macro because it may change due to the more complex IPv6 adressing architecture + * (there are, for example, two equivalent addresses of the loopback device) + * Pass this two addresses as in_addr or in6_addr. pdnsd_a is ok (it is a union) */ + +#define ADDR_EQUIV4(a,b) (((struct in_addr *)(a))->s_addr==((struct in_addr *)(b))->s_addr) +#define ADDR_EQUIV6(a,b) IN6_ARE_ADDR_EQUAL(((struct in6_addr *)(a)),((struct in6_addr *)(b))) + +#define ADDR_EQUIV(a,b) SEL_IPVER(ADDR_EQUIV4(a,b), ADDR_EQUIV6(a,b)) + +/* Compare an IPv6 adress with an IPv4 one. b should have type struct in_addr*. + Note the similarity with the IPV6_MAPIPV4 macro. */ +#define ADDR_EQUIV6_4(a,b) (((uint32_t *)(a))[3]==(b)->s_addr && \ + ((uint32_t *)(a))[2]==htonl(0xffff) && \ + ((uint32_t *)(a))[1]==0 && \ + ((uint32_t *)(a))[0]==0) + +/* Compare two address a and b in combination with a netmask m. + Only the bits coresponding to those set in the netmask are matched, the rest are ignored. + Pass in_addr* or in6_addr* arguments, respectively. */ +#define ADDR4MASK_EQUIV(a,b,m) ((((a)->s_addr^(b)->s_addr)&(m)->s_addr)==0) +#define ADDR6MASK_EQUIV(a,b,m) (((((uint32_t *)(a))[0]^((uint32_t *)(b))[0])&((uint32_t *)(m))[0])==0 && \ + ((((uint32_t *)(a))[1]^((uint32_t *)(b))[1])&((uint32_t *)(m))[1])==0 && \ + ((((uint32_t *)(a))[2]^((uint32_t *)(b))[2])&((uint32_t *)(m))[2])==0 && \ + ((((uint32_t *)(a))[3]^((uint32_t *)(b))[3])&((uint32_t *)(m))[3])==0) + +/* See if we need 4.4BSD style sockaddr_* structures and define some macros that set the length field. + * The non-4.4BSD behaviour is the only one that is POSIX-conformant.*/ +#if defined(SIN6_LEN) || defined(SIN_LEN) +# define BSD44_SOCKA +# define SET_SOCKA_LEN4(socka) (socka.sin_len=sizeof(struct sockaddr_in)) +# define SET_SOCKA_LEN6(socka) (socka.sin6_len=sizeof(struct sockaddr_in6)) +#else +# define SET_SOCKA_LEN4(socka) +# define SET_SOCKA_LEN6(socka) +#endif + +#ifdef ENABLE_IPV6 +# define ADDRSTR_MAXLEN INET6_ADDRSTRLEN +#else +# ifdef INET_ADDRSTRLEN +# define ADDRSTR_MAXLEN INET_ADDRSTRLEN +# else +# define ADDRSTR_MAXLEN 16 +# endif +#endif + +#if (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN) +# define SOL_IPV6 IPPROTO_IPV6 +#endif + +#ifdef ENABLE_IPV6 +# ifndef IPV6_RECVPKTINFO +/* This appears to be needed e.g. on Darwin (Mac OS X). */ +# define IPV6_RECVPKTINFO IPV6_PKTINFO +# endif +#endif + +typedef union { +#ifdef ENABLE_IPV4 + struct in_addr ipv4; +#endif +#ifdef ENABLE_IPV6 + struct in6_addr ipv6; +#endif +} pdnsd_a; + +#ifdef ENABLE_IPV4 +#define PDNSD_A_INITIALIZER {{INADDR_ANY}} +#else +#define PDNSD_A_INITIALIZER {IN6ADDR_ANY_INIT} +#endif + + +/* The pdnsd_a2 type is very similar to pdnsd_a, but can hold + both an IPv4 and an IPv6 address at the same time, + i.e. a struct instead of a union. +*/ +typedef struct { +#ifdef ENABLE_IPV6 + struct in6_addr ipv6; +#endif + struct in_addr ipv4; +} pdnsd_a2; + +/* Macros/functions for assigning/converting a pdnsd_a* to a pdnsd_a2* type, + and vice versa. +*/ +#ifdef ENABLE_IPV6 +inline static void SET_PDNSD_A2(pdnsd_a2 *a2, pdnsd_a *a) __attribute__((always_inline)); +inline static void SET_PDNSD_A2(pdnsd_a2 *a2, pdnsd_a *a) +{ +#ifdef ENABLE_IPV4 + if(run_ipv4) + a2->ipv4=a->ipv4; + else +#endif + { + a2->ipv6=a->ipv6; + a2->ipv4.s_addr=INADDR_ANY; + } +} +#else +# define SET_PDNSD_A2(a2,a) ((a2)->ipv4=(a)->ipv4) +#endif + +#define PDNSD_A2_TO_A(a2) SEL_IPVER(((pdnsd_a *)&(a2)->ipv4),((pdnsd_a *)&(a2)->ipv6)) + +/* Do we have sufficient support in the C libraries to allow local AAAA records + to be defined? */ +#if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_PTON) +# define ALLOW_LOCAL_AAAA IS_CACHED_AAAA +#else +# define ALLOW_LOCAL_AAAA 0 +#endif + +/* Used to enter local records */ +typedef union { + struct in_addr ipv4; +#if ALLOW_LOCAL_AAAA + struct in6_addr ipv6; +#endif +} pdnsd_ca; + + +#endif diff --git a/jni/pdnsd/src/list.c b/jni/pdnsd/src/list.c new file mode 100644 index 00000000..03701860 --- /dev/null +++ b/jni/pdnsd/src/list.c @@ -0,0 +1,171 @@ +/* list.c - Dynamic array and list handling + + Copyright (C) 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2007, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include "helpers.h" +#include "error.h" +#include "list.h" + + +/* Grow a dynamic array to hold one extra element. + This could be done using da_resize(), but this is such a common operation + it is has been given its own optimized implementation. + da_grow1() returns a pointer to the new (possibly reallocated) array if + successful, otherwise it frees the old array (after freeing all the array + elements if a clean-up routine is supplied) and returns NULL. +*/ +darray da_grow1(darray a, size_t headsz, size_t elemsz, void (*cleanuproutine) (void *)) +{ + size_t k = (a?a->nel:0); + if(!a || (k!=0 && (k&7)==0)) { + darray tmp=(darray)realloc(a, headsz+elemsz*(k+8)); + if (!tmp && a) { + if(cleanuproutine) { + size_t i; + for(i=0;inel=k+1; + return a; +} + +inline static size_t alloc_nel(size_t n) +{ + return n==0 ? 8 : (n+7)&(~7); +} + +/* da_resize() allows you to grow (or shrink) a dynamic array to an arbitrary length n, + but is otherwise similar to da_grow1(). +*/ +darray da_resize(darray a, size_t headsz, size_t elemsz, size_t n, void (*cleanuproutine) (void *)) +{ + size_t ael = (a?alloc_nel(a->nel):0); + size_t new_ael = alloc_nel(n); + if(new_ael != ael) { + /* adjust alloced space. */ + darray tmp=(darray)realloc(a, headsz+elemsz*new_ael); + if (!tmp && a) { + if(cleanuproutine) { + size_t i,k=a->nel; + for(i=0;inel=n; + return a; +} + +#ifdef ALLOC_DEBUG +void DBGda_free(darray a, size_t headsz, size_t elemsz, char *file, int line) +{ + if (a==NULL) + {DEBUG_MSG("- da_free, %s:%d, not initialized\n", file, line);} + else + {DEBUG_MSG("- da_free, %s:%d, %lu bytes\n", file, line, + (unsigned long)(headsz+elemsz*alloc_nel(a->nel)));} + free(a); +} +#endif + + +#define DLISTALIGN(len) (((len) + (sizeof(size_t)-1)) & ~(sizeof(size_t)-1)) +/* This mask corresponds to a chunk size of 1024. */ +#define DLISTCHUNKSIZEMASK ((size_t)0x3ff) + +/* Add space for a new item of size len to the list a. + dlist_grow() returns a pointer to the new (possibly reallocated) list structure if + successful, otherwise it frees the old list and returns NULL. +*/ +dlist dlist_grow(dlist a, size_t len) +{ + size_t sz=0, allocsz=0, szincr, newsz; + if(a) { + sz=a->last+a->lastsz; + allocsz = (sz+DLISTCHUNKSIZEMASK)&(~DLISTCHUNKSIZEMASK); + *((size_t *)&a->data[a->last])=a->lastsz; + } + szincr=DLISTALIGN(len+sizeof(size_t)); + newsz=sz+szincr; + if(newsz>allocsz) { + dlist tmp; + allocsz = (newsz+DLISTCHUNKSIZEMASK)&(~DLISTCHUNKSIZEMASK); + tmp=realloc(a, sizeof(struct _dynamic_list_head)+allocsz); + if (!tmp) + free(a); + a=tmp; + } + if(a) { + a->last=sz; + a->lastsz=szincr; + *((size_t *)&a->data[sz])=0; + } + return a; +} + + +/* Add a new node, capable of holding data of size len, at the end of a linked list. + llist_grow() returns 1 if successful, otherwise it frees the entire linked list + and returns 0. + */ +int llist_grow(llist *a, size_t len) +{ + struct llistnode_s *new= (struct llistnode_s *)malloc(sizeof(struct llistnode_s)+len); + + if(!new) { + llist_free(a); + return 0; + } + + new->next=NULL; + + if(!a->first) + a->first=new; + else + a->last->next=new; + + a->last=new; + + return 1; +} + +void llist_free(llist *a) +{ + struct llistnode_s *p= a->first; + + while(p) { + struct llistnode_s *next= p->next; + free(p); + p=next; + } + + a->first=NULL; + a->last= NULL; +} diff --git a/jni/pdnsd/src/list.h b/jni/pdnsd/src/list.h new file mode 100644 index 00000000..c63534e7 --- /dev/null +++ b/jni/pdnsd/src/list.h @@ -0,0 +1,170 @@ +/* list.h - Dynamic array and list handling + + Copyright (C) 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2007, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef LIST_H +#define LIST_H + +#include +#include +#include "pdnsd_assert.h" + + +typedef struct {size_t nel;} *darray; + +/* used in type declarations */ +#define DYNAMIC_ARRAY(typ) struct {size_t nel; typ elem[0];} +#define DA_TYP_OFFSET(atyp) ((size_t)((atyp)0)->elem) +#define DA_OFFSET(a) DA_TYP_OFFSET(typeof (a)) + +#define DA_CREATE(atyp,n) ((atyp)da_resize(NULL,DA_TYP_OFFSET(atyp),sizeof(((atyp)0)->elem[0]),n,NULL)) +#define DA_INDEX(a,i) ((a)->elem[i]) +/* Used often, so make special-case macro here */ +#define DA_LAST(a) ((a)->elem[(a)->nel-1]) + +#define DA_GROW1(a) ((typeof (a))da_grow1((darray)(a),DA_OFFSET(a),sizeof((a)->elem[0]),NULL)) +#define DA_GROW1_F(a,cleanup) ((typeof (a))da_grow1((darray)(a),DA_OFFSET(a),sizeof((a)->elem[0]),cleanup)) +#define DA_RESIZE(a,n) ((typeof (a))da_resize((darray)(a),DA_OFFSET(a),sizeof((a)->elem[0]),n,NULL)) +#define DA_NEL(a) da_nel((darray)(a)) + +/* + * Some or all of these should be inline. + * They aren't macros for type safety. + */ + +darray da_grow1(darray a, size_t headsz, size_t elemsz, void (*cleanuproutine) (void *)); +darray da_resize(darray a, size_t headsz, size_t elemsz, size_t n, void (*cleanuproutine) (void *)); + +inline static unsigned int da_nel(darray a) + __attribute__((always_inline)); +inline static unsigned int da_nel(darray a) +{ + if (a==NULL) + return 0; + return a->nel; +} + +/* alloc/free debug code.*/ +#ifdef ALLOC_DEBUG +void DBGda_free(darray a, size_t headsz, size_t elemsz, char *file, int line); +#define da_free(a) DBGda_free((darray)(a),DA_OFFSET(a),sizeof((a)->elem[0]), __FILE__, __LINE__) +#else +#define da_free free +#endif + + +/* This dynamic "list" structure is useful if the items are not all the same size. + The elements can only be read back in sequential order, not indexed as with the dynamic arrays. +*/ +struct _dynamic_list_head { + size_t last,lastsz; + char data[0]; +}; + +typedef struct _dynamic_list_head *dlist; + +inline static void *dlist_first(dlist a) + __attribute__((always_inline)); +inline static void *dlist_first(dlist a) +{ + return a?&a->data[sizeof(size_t)]:NULL; +} + +/* dlist_next() returns a reference to the next item in the list, or NULL is there is no next item. + ref should be properly aligned. + If the dlist was grown with dlist_grow(), this should be OK. +*/ +inline static void *dlist_next(void *ref) + __attribute__((always_inline)); +inline static void *dlist_next(void *ref) +{ + size_t incr= *(((size_t *)ref)-1); + return incr?((char *)ref)+incr:NULL; +} + +/* dlist_last() returns a reference to the last item. */ +inline static void *dlist_last(dlist a) + __attribute__((always_inline)); +inline static void *dlist_last(dlist a) +{ + return a?&a->data[a->last+sizeof(size_t)]:NULL; +} + +dlist dlist_grow(dlist a, size_t len); + +#define dlist_free free + + +/* linked list data type. */ +struct llistnode_s { + struct llistnode_s *next; + char *data[0]; +}; + +typedef struct { + struct llistnode_s *first, *last; +} + llist; + +inline static void llist_init(llist *a) + __attribute__((always_inline)); +inline static void llist_init(llist *a) +{ + a->first=NULL; + a->last= NULL; +} + +inline static int llist_isempty(llist *a) + __attribute__((always_inline)); +inline static int llist_isempty(llist *a) +{ + return a->first==NULL; +} + +inline static void *llist_first(llist *a) + __attribute__((always_inline)); +inline static void *llist_first(llist *a) +{ + struct llistnode_s *p= a->first; + return p?p->data:NULL; +} + +inline static void *llist_next(void *ref) + __attribute__((always_inline)); +inline static void *llist_next(void *ref) +{ + struct llistnode_s *next= *(((struct llistnode_s **)ref)-1); + return next?next->data:NULL; +} + +inline static void *llist_last(llist *a) + __attribute__((always_inline)); +inline static void *llist_last(llist *a) +{ + struct llistnode_s *p= a->last; + return p?p->data:NULL; +} + +int llist_grow(llist *a, size_t len); +void llist_free(llist *a); + +#endif /* def LIST_H */ diff --git a/jni/pdnsd/src/main.c b/jni/pdnsd/src/main.c new file mode 100644 index 00000000..1190b77c --- /dev/null +++ b/jni/pdnsd/src/main.c @@ -0,0 +1,710 @@ +/* main.c - Command line parsing, intialisation and server start + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +/* in order to use O_NOFOLLOW on Linux: */ +/* #define _GNU_SOURCE */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "consts.h" +#include "cache.h" +#include "status.h" +#include "servers.h" +#include "dns_answer.h" +#include "dns_query.h" +#include "error.h" +#include "helpers.h" +#include "icmp.h" +#include "hash.h" + + +#if DEBUG>0 +short int debug_p=0; +#endif +short int stat_pipe=0; + +/* int sigr=0; */ +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +short int run_ipv4=DEFAULT_IPV4; +short int cmdlineipv=0; +#endif +cmdlineflags_t cmdline={0}; +pthread_t main_thrid,servstat_thrid,statsock_thrid,tcps_thrid,udps_thrid; +uid_t init_uid; +#if DEBUG>0 +FILE *dbg_file=NULL; +#endif +volatile int tcp_socket=-1; +volatile int udp_socket=-1; +sigset_t sigs_msk; +char *conf_file=CONFDIR"/pdnsd.conf"; + + +/* version and licensing information */ +static const char info_message[] = + + "pdnsd - dns proxy daemon, version " VERSION "\n\n" + "Copyright (C) 2000, 2001 Thomas Moestl\n" + "Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 Paul A. Rombouts\n\n" + "pdnsd is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 3 of the License, or\n" + "(at your option) any later version.\n\n" + "pdnsd is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n\n" + "You should have received a copy of the GNU General Public License\n" + "along with pdsnd; see the file COPYING. If not, see\n" + ".\n"; + + +/* the help page */ +static const char help_message[] = + + "\n\nUsage: pdnsd [-h] [-V] [-s] [-d] [-g] [-t] [-p file] [-vn] [-mxx] [-c file]" +#ifdef ENABLE_IPV4 + " [-4]" +#endif +#ifdef ENABLE_IPV6 + " [-6] [-i prefix]" +#endif +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + " [-a]" +#endif + "\n\n" + "Options:\n" + "-h\t\t--or--\n" + "--help\t\tprint this help page and exit.\n" + "-V\t\t--or--\n" + "--version\tprint version and license information and exit.\n" + "--pdnsd-user\tprint the user pdnsd will run as and exit.\n" + "-s\t\t--or--\n" + "--status\tEnable status control socket in the cache directory.\n" + "-d\t\t--or--\n" + "--daemon\tStart pdnsd in daemon mode (as background process.)\n" + "-g\t\t--or--\n" + "--debug\t\tPrint some debug messages on the console or to the\n" + "\t\tfile pdnsd.debug in your cache directory (in daemon mode).\n" + "-t\t\t--or--\n" + "--tcp\t\tEnables the TCP server thread. pdnsd will then serve\n" + "\t\tTCP and UDP queries.\n" + "-p\t\tWrites the pid the server runs as to a specified filename.\n" + "\t\tWorks only in daemon mode.\n" + "-vn\t\tsets the verbosity of pdnsd. n is a numeric argument from 0\n" + "\t\t(normal operation) to 9 (many messages for debugging).\n" + "\t\tUse like -v2\n" + "-mxx\t\tsets the query method pdnsd uses. Possible values for xx are:\n" + "\t\tuo (UDP only), to (TCP only), tu (TCP or, if the server\n" + "\t\tdoes not support this, UDP) and ut (UDP and, if the reply was\n" + "\t\ttruncated, TCP). Use like -muo. Preset: " +#if M_PRESET==UDP_ONLY + "-muo" +#elif M_PRESET==TCP_ONLY + "-mto" +#elif M_PRESET==TCP_UDP + "-mtu" +#else + "-mut" +#endif + "\n" + "-c\t\t--or--\n" + "--config-file\tspecifies the file the configuration is read from.\n" + "\t\tDefault is " CONFDIR "/pdnsd.conf\n" +#ifdef ENABLE_IPV4 + "-4\t\tswitches to IPv4 mode.\n" + "\t\t" +# if DEFAULT_IPV4 + "On" +# else + "Off" +# endif + " by default.\n" +#endif +#ifdef ENABLE_IPV6 + "-6\t\tswitches to IPv6 mode.\n" + "\t\t" +# if DEFAULT_IPV4 + "Off" +# else + "On" +# endif + " by default.\n" + "-i\t\t--or--\n" + "--ipv4_6_prefix\tspecifies the prefix pdnsd uses to map IPv4 to IPv6\n" + "\t\taddresses. Must be a valid IPv6 address.\n" + "\t\tDefault is " DEFAULT_IPV4_6_PREFIX "\n" +#endif +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) + "-a\t\tWith this option, pdnsd will try to detect automatically if\n" + "\t\tthe system supports IPv6, and revert to IPv4 otherwise.\n" +#endif + "\n\n\"no\" can be prepended to the --status, --daemon, --debug and --tcp\n" + "options (e.g. --notcp) to reverse their effect.\n"; + + +/* These are some init steps we have to call before we get daemon on linux, but need + * to call after daemonizing on other OSes. + * Theay are also the last steps before we drop privileges. */ +int final_init() +{ +#ifndef NO_TCP_SERVER + if (!global.notcp) + tcp_socket=init_tcp_socket(); +#endif + udp_socket=init_udp_socket(); + if (tcp_socket==-1 && udp_socket==-1) { + log_error("tcp and udp initialization failed. Exiting."); + return 0; + } + if (global.strict_suid) { + if (!run_as(global.run_as)) { + return 0; + } + } + return 1; +} + +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +/* Check if IPv6 is available. + * With thanks to Juliusz Chroboczek. + */ +static int check_ipv6() +{ + int fd; + fd = socket(PF_INET6, SOCK_STREAM, 0); + if(fd < 0) { + if(errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT || errno == EINVAL) + return 0; + return -1; + } + close(fd); + return 1; +} +#endif + + +/* + * Argument parsing, init, server startup + */ +int main(int argc,char *argv[]) +{ + int i,sig,pfd=-1; /* Initialized to inhibit compiler warning */ + + main_thrid=pthread_self(); + servstat_thrid=main_thrid; + statsock_thrid=main_thrid; + tcps_thrid=main_thrid; + udps_thrid=main_thrid; + init_uid=getuid(); +#ifdef ENABLE_IPV6 + { + int err; + if((err=inet_pton(AF_INET6,DEFAULT_IPV4_6_PREFIX,&global.ipv4_6_prefix))<=0) { + fprintf(stderr,"Error: inet_pton() wont accept default prefix %s in %s, line %d\n", + DEFAULT_IPV4_6_PREFIX,__FILE__,__LINE__); + if(err) + perror("inet_pton"); + exit(1); + } + } +#endif + + /* Parse the command line. + Remember which options were specified here, because the command-line options + shall override the ones given in the config file */ + for (i=1;ipw_name); + else + printf("%i\n",uid); + } + exit(0); + } + + if(!global.cache_dir) global.cache_dir = CACHEDIR; + if(!global.scheme_file) global.scheme_file = "/var/lib/pcmcia/scheme"; + stat_pipe=global.stat_pipe; + + if (!(global.run_as[0] && global.strict_suid)) { + for (i=0; iuptest==C_EXEC && sp->uptest_usr[0]=='\0') { + uid_t uid=getuid(); + struct passwd *pws=getpwuid(uid); + + /* No explicit uptest user given. If we run_as and strict_suid, we assume that + * this is safe. If not - warn. */ + fprintf(stderr,"Warning: uptest command \"%s\" will implicitly be executed as user ", sp->uptest_cmd); + if (pws) + fprintf(stderr,"%s\n",pws->pw_name); + else + fprintf(stderr,"%i\n",uid); + + } + } + } + + if (global.daemon && global.pidfile) { + if (unlink(global.pidfile)!=0 && errno!=ENOENT) { + log_error("Error: could not unlink pid file %s: %s",global.pidfile, strerror(errno)); + exit(1); + } + if ((pfd=open(global.pidfile,O_WRONLY|O_CREAT|O_EXCL +#ifdef O_NOFOLLOW + |O_NOFOLLOW +#else + /* + * No O_NOFOLLOW. Nevertheless, this not a hole, since the + * directory for pidfiles should not be world writeable. + * OS's that do not support O_NOFOLLOW are currently not + * supported, this is just-in-case code. + */ +#endif + , 0600))==-1) + { + log_error("Error: could not open pid file %s: %s",global.pidfile, strerror(errno)); + exit(1); + } + } + for (i=0;i0 + if (global.debug) { + char dbgpath[strlen(global.cache_dir)+sizeof("/pdnsd.debug")]; + stpcpy(stpcpy(dbgpath,global.cache_dir),"/pdnsd.debug"); + if (!(dbg_file=fopen(dbgpath,"w"))) + log_warn("Warning: could not open debug file %s: %s",dbgpath, strerror(errno)); + } +#endif + } else { +#if DEBUG>0 + dbg_file=stdout; +#endif + } + +#if DEBUG>0 + debug_p= (global.debug && dbg_file); +#endif + log_info(0,"pdnsd-%s starting.\n",VERSION); + DEBUG_MSG("Debug messages activated\n"); + +#if (TARGET!=TARGET_LINUX) + if (!final_init()) + _exit(1); +#endif + DEBUG_MSG(SEL_IPVER("Using IPv4.\n", "Using IPv6.\n")); + + /* initialize attribute for creating detached threads */ + pthread_attr_init(&attr_detached); + pthread_attr_setdetachstate(&attr_detached,PTHREAD_CREATE_DETACHED); + + read_disk_cache(); + + /* This must be done before any other thread is started to avoid races. */ + if (stat_pipe) + init_stat_sock(); + + + /* Before this point, logging and cache accesses are not locked because we are single-threaded. */ + init_log_lock(); + init_cache_lock(); + + sigemptyset(&sigs_msk); + sigaddset(&sigs_msk,SIGHUP); + sigaddset(&sigs_msk,SIGINT); +#ifndef THREADLIB_NPTL + sigaddset(&sigs_msk,SIGILL); +#endif + sigaddset(&sigs_msk,SIGABRT); + sigaddset(&sigs_msk,SIGFPE); +#ifndef THREADLIB_NPTL + sigaddset(&sigs_msk,SIGSEGV); +#endif + sigaddset(&sigs_msk,SIGTERM); + /* if (!daemon_p) { + sigaddset(&sigs_msk,SIGQUIT); + } */ +#if (TARGET==TARGET_LINUX) + pthread_sigmask(SIG_BLOCK,&sigs_msk,NULL); +#endif + +#if DEBUG>0 + { + int err; + /* Generate a key for storing our thread id's */ + if ((err=pthread_key_create(&thrid_key, NULL)) != 0) { + log_error("pthread_key_create failed: %s",strerror(err)); + _exit(1); + } + } +#endif + + { +#if DEBUG>0 + int thrdsucc=1; +# define thrdfail (thrdsucc=0) +#else +# define thrdfail +#endif + + if(start_servstat_thread()) thrdfail; + +#if (TARGET==TARGET_LINUX) + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + _exit(1); + } + } +#endif + + if (stat_pipe) + if(start_stat_sock()) thrdfail; + + start_dns_servers(); + +#if DEBUG>0 + if(thrdsucc) { + DEBUG_MSG("All threads started successfully.\n"); + } +#endif +#undef thrdfail + } + +#if (TARGET==TARGET_LINUX) && !defined(THREADLIB_NPTL) + pthread_sigmask(SIG_BLOCK,&sigs_msk,NULL); + waiting=1; +#endif + { + int err; + while ((err=sigwait(&sigs_msk,&sig))) { + if (err!=EINTR) { + log_error("sigwait failed: %s",strerror(err)); + sig=0; + break; + } + } + } + if(sig) DEBUG_MSG("Signal %i caught.\n",sig); + write_disk_cache(); + destroy_cache(); + if(sig) log_warn("Caught signal %i. Exiting.",sig); + if (sig==SIGSEGV || sig==SIGILL || sig==SIGBUS) + crash_msg("This is a fatal signal probably triggered by a bug."); + if (ping_isocket!=-1) + close(ping_isocket); +#ifdef ENABLE_IPV6 + if (ping6_isocket!=-1) + close(ping6_isocket); +#endif + /* Close and delete the status socket */ + if(stat_pipe) close(stat_sock); + if (sock_path && unlink(sock_path)) + log_warn("Failed to unlink %s: %s",sock_path, strerror(errno)); + + free_rng(); +#if DEBUG>0 + if (debug_p && global.daemon) + if(fclose(dbg_file)<0) { + log_warn("Could not close debug file: %s", strerror(errno)); + } +#endif + _exit(0); +} diff --git a/jni/pdnsd/src/make_rr_types_h.pl b/jni/pdnsd/src/make_rr_types_h.pl new file mode 100644 index 00000000..c8c0f9fb --- /dev/null +++ b/jni/pdnsd/src/make_rr_types_h.pl @@ -0,0 +1,309 @@ +#!/usr/bin/perl -w + +# This Perl script is used to generate rr_types.h, using rr_types.in as input. +# +# Copyright (C) 2010, 2011 Paul A. Rombouts +# +# This file is part of the pdnsd package. +# + +use strict; +use integer; + +print << "END-OF-TEXT"; +/* This file was generated by running '$0 @ARGV'. + Modifications to this file may be lost the next time it is automatically + regenerated. +*/ + +END-OF-TEXT + +my %valdic; +my %namedic; +my %classdic; +my %muset; +my $nrr=0; +my $nmu=0; +my $minval; +my $maxval; +#my $maxmuval; + +while(<>) { + if(/\S/ && !/^\s*\#/) { + if(/^\s*(?:([*+-])\s*)?([\w-]+)\s+(\d+)\s+(?:\((\w+)\))?/) { + my $mu = $1; my $name=$2; my $val=$3+0; my $class=$4; + $name =~ s/-/_/g; + if(defined($valdic{$name})) {warn "The name \"$name\" does not have a unique value.\n"} + if(defined($namedic{$val})) {warn "The value \"$val\" does not have a unique name.\n"} + $valdic{$name}=$val; $namedic{$val}=$name; $classdic{$val}=$class if defined($class); + if(defined($mu)) { + if($mu eq '-') {next} + $muset{$val}= 1; + ++$nmu; + #if(!defined($maxmuval) || $val>$maxmuval) {$maxmuval=$val} + } + else {$muset{$val}= 0} + ++$nrr; + if(!defined($minval) || $val<$minval) {$minval=$val} + if(!defined($maxval) || $val>$maxval) {$maxval=$val} + } + else {die "Can't find name-value pair in following line:\n$_\n"} + } +} + +defined($minval) or die "No values defined.\n"; +if($nrr>255) {warn "Warning: total number of cache-able RR types is greater than 255.\n"} + +print << 'END-OF-TEXT'; +/* rr_types.h - A header file with names & descriptions of + all rr types known to pdnsd + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2007, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#ifndef _RR_TYPES_H_ +#define _RR_TYPES_H_ + +#include + +END-OF-TEXT + +print "#define T_MIN $minval\n"; +foreach my $name (sort {$valdic{$a} <=> $valdic{$b} } (keys %valdic)) { + printf("#define %-12s %2d\n", "T_$name", $valdic{$name}); +} +print "#define T_MAX $maxval\n"; +print("\n/* T_MAX - T_MIN + 1 */\n","#define T_NUM ",$maxval+1-$minval,"\n"); +#print("\n/* Largest most frequently used type value. */\n","#define T_MAXMU $maxmuval\n"); +print("\n/* Number of most frequently used rr types. */\n","#define NRRMU $nmu\n"); +print("\n/* Number of remaining rr types. */\n","#define NRREXT ",$nrr-$nmu,"\n"); +print("\n/* NRRMU + NRREXT */\n","#define NRRTOT $nrr\n"); + +print << 'END-OF-TEXT'; + +/* Lookup table for converting rr type values to internally used indices. */ +extern const unsigned short int rrlkuptab[T_NUM]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const unsigned short int rrlkuptab[T_NUM] = { +END-OF-TEXT +my @rrtpval=(); +for(my $val=$minval, my $i=0, my $j=$nmu, my $k=$nrr; $val<=$maxval; ++$val) { + my $idx; + if(defined($muset{$val})) { + if($muset{$val}) { + $idx = $i++; + } + else { + $idx = $j++; + } + $rrtpval[$idx]=$val; + } + else { + $idx = $k++; + } + + printf('%4d', $idx); + if(defined($namedic{$val})) { + print " /* $namedic{$val} */"; + } + print ',' if $val<$maxval; + print "\n"; +} +#print << 'END-OF-TEXT'; +#}; +##endif +# +#/* Table for converting internally used indices to rr type values. +# This is more or less the inverse of the rrlkuptab[] mapping. */ +#extern const unsigned short int rrtpval[NRRTOT]; +##if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +#const unsigned short int rrtpval[NRRTOT] = { +#END-OF-TEXT +#for(my $i=0; $i<$nrr; ++$i) { +# if($i ==0) { +# print " /* Most frequently used types. */\n"; +# } +# else { +# print ",\n"; +# } +# print " /* Remaining (less frequently used) types. */\n" +# if $i == $nmu; +# my $val= $rrtpval[$i]; +# print(" ",defined($namedic{$val})? "T_$namedic{$val}": $val); +#} +print << 'END-OF-TEXT'; +}; +#endif + +/* List of most frequently used RR types in ascending order. */ +extern const unsigned short int rrmuiterlist[NRRMU]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const unsigned short int rrmuiterlist[NRRMU] = { +END-OF-TEXT +for(my $val=$minval, my $i=0; $val<=$maxval; ++$val) { + if(defined($muset{$val}) && $muset{$val}) { + print ",\n" if $i++; + print(" ",defined($namedic{$val})? "T_$namedic{$val}": $val); + } +} +print << 'END-OF-TEXT'; + +}; +#endif + +/* List of the cache-able RR types in ascending order. */ +extern const unsigned short int rrcachiterlist[NRRTOT]; +#if DEFINE_RR_TYPE_ARRAYS +const unsigned short int rrcachiterlist[NRRTOT] = { +END-OF-TEXT +for(my $val=$minval, my $i=0; $val<=$maxval; ++$val) { + if(defined($muset{$val})) { + print ",\n" if $i++; + print(" ",defined($namedic{$val})? "T_$namedic{$val}": $val); + } +} +print << 'END-OF-TEXT'; + +}; +#endif + +/* Optimized getrrset macros for fixed rr types. */ +END-OF-TEXT +for(my $val=$minval, my $i=0, my $j=0; $val<=$maxval; ++$val) { + if(defined($muset{$val})) { + my $name = $namedic{$val}; + my $mdef; + if($muset{$val}) { + $mdef= "GET_RRSMU(cent,$i)"; + ++$i; + } + else { + $mdef= "GET_RRSEXT(cent,$j)"; + ++$j; + } + printf("#define %-25s %s\n", "getrrset_$name(cent)", $mdef) + if defined($name); + } +} +print << 'END-OF-TEXT'; + +/* have_rr macros for fixed rr types. */ +END-OF-TEXT +for(my $val=$minval, my $i=0, my $j=0; $val<=$maxval; ++$val) { + my $name = $namedic{$val}; + my $mdef = '0'; + if(defined($muset{$val})) { + if($muset{$val}) { + $mdef= "HAVE_RRMU(cent,$i)"; + ++$i; + } + else { + $mdef= "HAVE_RREXT(cent,$j)"; + ++$j; + } + } + printf("#define %-25s %s\n", "have_rr_$name(cent)", $mdef) + if defined($name); +} +print << 'END-OF-TEXT'; + +/* These macros specify which RR types are cached by pdnsd. */ +END-OF-TEXT +for(my $val=$minval; $val<=$maxval; ++$val) { + if(defined($muset{$val})) { + my $name = $namedic{$val}; + printf("#define IS_CACHED_%-10s 1\n", defined($name)? $name: "TYPE$val") + } +} +print << 'END-OF-TEXT'; + +/* Array indices for most frequently used rr types. */ +END-OF-TEXT +for(my $val=$minval, my $i=0; $val<=$maxval; ++$val) { + if(defined($muset{$val}) && $muset{$val}) { + printf("#define %-18s %2d\n", "RRMUINDEX_$namedic{$val}", $i) + if defined($namedic{$val}); + ++$i; + } +} +print << 'END-OF-TEXT'; + +/* Table of rr names. */ +extern const char *const rrnames[T_NUM]; +#if DEFINE_RR_TYPE_ARRAYS +const char *const rrnames[T_NUM] = { +END-OF-TEXT +for(my $val=$minval; $val<=$maxval; ++$val) { + my $name = $namedic{$val}; + print(' "', defined($name)? $name: "TYPE$val", '"'); + print ',' if $val<$maxval; + print "\n"; +} +print << 'END-OF-TEXT'; +}; +#endif + +/* Structure for rr information */ +struct rr_infos { + unsigned short class; /* class (values see below) */ + unsigned short excludes; /* relations to other classes. + Mutual exclusion is marked by or'ing the + respective RRCL value in this field. + Exclusions should be symmetric. */ +}; + +/* Class values */ +#define RRCL_ALIAS 1 /* for CNAMES, conflicts with RRCL_RECORD */ +#define RRCL_RECORD 2 /* normal direct record */ +#define RRCL_IDEM 4 /* types that conflict with no others (MX, CNAME, ...) */ +#define RRCL_PTR 8 /* PTR */ + +/* Standard excludes for the classes */ +#define RRX_ALIAS (RRCL_RECORD|RRCL_PTR) +#define RRX_RECORD (RRCL_ALIAS|RRCL_PTR) +#define RRX_IDEM 0 +#define RRX_PTR (RRCL_ALIAS|RRCL_RECORD) + +/* There could be a separate table detailing the relationship of types, but this + * is slightly more flexible, as it allows a finer granularity of exclusion. Also, + * Membership in multiple classes could be added. + * Index by internally used RR-set indices, not RR type values! + */ +extern const struct rr_infos rr_info[NRRTOT]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const struct rr_infos rr_info[NRRTOT] = { +END-OF-TEXT +for(my $i=0; $i<$nrr; ++$i) { + print ",\n" if $i; + my $val=$rrtpval[$i]; + my $class = (defined($classdic{$val})? $classdic{$val}: 'IDEM'); + printf(' %-16s %-15s %s',"{RRCL_$class,", "RRX_$class}", defined($namedic{$val})?"/* $namedic{$val} */":""); +} +print << 'END-OF-TEXT'; + +}; +#endif + +int rr_tp_byname(char *name); +const char *loc2str(const void *binary, char *ascii, size_t asclen); + +#endif +END-OF-TEXT + +exit diff --git a/jni/pdnsd/src/netdev.c b/jni/pdnsd/src/netdev.c new file mode 100644 index 00000000..bd5f8c45 --- /dev/null +++ b/jni/pdnsd/src/netdev.c @@ -0,0 +1,363 @@ +/* netdev.c - Test network devices for existence and status + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +/* + * Portions are under the following copyright and taken from FreeBSD + * (clause 3 deleted as it no longer applies): + * + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University 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 REGENTS 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 THE REGENTS OR CONTRIBUTORS 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. + * + * @(#)if.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/net/if.h,v 1.58.2.1 2000/05/05 13:37:04 jlemon Exp $ + */ + +#include +#include "ipvers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "helpers.h" +#include "netdev.h" +#include "error.h" + + +#if (TARGET==TARGET_BSD) +/* Taken from FreeBSD net/if.h rev. 1.58.2.1 */ +#define SIZEOF_ADDR_IFREQ(ifr) \ + ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ + (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ + (ifr).ifr_addr.sa_len) : sizeof(struct ifreq)) +#elif (TARGET==TARGET_CYGWIN) +#define SIZEOF_ADDR_IFREQ(ifr) (sizeof(struct sockaddr)) +#endif + +#define MAX_SOCKETOPEN_ERRS 10 +static volatile unsigned long socketopen_errs=0; + +/* + * Portions of the following code are Linux/FreeBSD specific. + * Please write interface-detection routines for other flavours of Unix if you can and want. + */ + +#if (TARGET==TARGET_LINUX) || (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN) +# if (TARGET==TARGET_LINUX) + +static volatile unsigned long isdn_errs=0; + +# ifdef ISDN_SUPPORT + +/* + * Test the status of an ippp interface. Taken from the isdn4k-utils (thanks!) and adapted + * by me (I love free software!) + * This will not work with older kernels. + * If your kernel is too old or too new, just try to get the status as uptest=exec command + * This will work, although slower. + */ + +# include + +int statusif(char *name) +{ + isdn_net_ioctl_phone phone; + int isdninfo,rc=0; + + if ((isdninfo = open("/dev/isdninfo", O_RDONLY))<0) { + if (++isdn_errs<=2) { + log_warn("Could not open /dev/isdninfo for uptest: %s",strerror(errno)); + } + return 0; + } + + strncp(phone.name, name, sizeof(phone.name)); + if (ioctl(isdninfo, IIOCNETGPN, &phone)==0) + rc=1; + close(isdninfo); + return rc; +} +# endif + +/* + * Test whether the network interface specified in ifname and its + * associated device specified in devname have locks owned by the + * same process. + */ +int dev_up(char *ifname, char *devname) +{ + FILE *fd; + int pidi, pidd, rv; + + { + char path[sizeof("/var/run/.pid")+strlen(ifname)]; + stpcpy(stpcpy(stpcpy(path,"/var/run/"),ifname),".pid"); + if ((fd=fopen(path, "r")) == NULL ) + return 0; + + if (fscanf(fd, "%d", &pidi) != 1 ) { + fclose(fd) ; + return 0; + } + fclose(fd); + } + + { + char path[sizeof("/var/lock/LCK..")+strlen(devname)]; + stpcpy(stpcpy(path,"/var/lock/LCK.."),devname); + if ((fd=fopen(path, "r")) == NULL) + return 0; + + if (fscanf(fd, "%d", &pidd) != 1) { + fclose(fd); + return 0; + } + fclose(fd); + } + + if (pidi != pidd) + return 0; + /* Test whether pppd is still alive */ + rv=kill(pidi,0); + return (rv==0 || (rv==-1 && errno!=ESRCH)); +} + + +# endif /*(TARGET==TARGET_LINUX)*/ + +/* + * Test whether the network device specified in devname is up and + * running (returns -1) or non-existent, down or not-running (returns 0) + * + * Note on IPv6-Comptability: rfc2133 requires all IPv6 implementation + * to be backwards-compatible to IPv4 in means of permitting socket(PF_INET,...) + * and similar. So, I don't put code here for both IPv4 and IPv6, since + * I use that socket only for ioctls. If somebody notices incompatabilities, + * please notify me. + */ +int if_up(char *devname) +{ + int sock; + struct ifreq ifr; +# if (TARGET==TARGET_LINUX) + unsigned int devnamelen=strlen(devname); + if (devnamelen>4 && devnamelen<=6 && strncmp(devname,"ippp",4)==0) { + /* This function didn't manage the interface uptest correctly. Thanks to + * Joachim Dorner for pointing out. + * The new code (statusif()) was shamelessly stolen from isdnctrl.c of the + * isdn4k-utils. */ +# ifdef ISDN_SUPPORT + return statusif(devname); +# else + if (isdn_errs++==0) { + log_warn("An ippp? device was specified for uptest, but pdnsd was compiled without ISDN support."); + log_warn("The uptest result will be wrong."); + } +# endif + /* If it doesn't match our rules for isdn devices, treat as normal if */ + } +# endif + if ((sock=socket(PF_INET,SOCK_DGRAM, IPPROTO_UDP))==-1) { + if(++socketopen_errs<=MAX_SOCKETOPEN_ERRS) { + log_warn("Could not open socket in if_up(): %s",strerror(errno)); + } + return 0; + } + strncp(ifr.ifr_name,devname,IFNAMSIZ); + if (ioctl(sock,SIOCGIFFLAGS,&ifr)==-1) { + close(sock); + return 0; + } + close(sock); + return (ifr.ifr_flags&IFF_UP) && (ifr.ifr_flags&IFF_RUNNING); +} + +# if (TARGET==TARGET_LINUX) +# ifdef ENABLE_IPV6 +#define MAX_IF_INET6_OPEN_ERRS 10 +static volatile unsigned long if_inet6_open_errs=0; +# endif + +int is_local_addr(pdnsd_a *a) +{ + int res=0; + +# ifdef ENABLE_IPV4 + if (run_ipv4) { + int i,sock; + struct ifreq ifr; + if ((sock=socket(PF_INET,SOCK_DGRAM, IPPROTO_UDP))==-1) { + if(++socketopen_errs<=MAX_SOCKETOPEN_ERRS) { + log_warn("Could not open socket in is_local_addr(): %s",strerror(errno)); + } + return 0; + } + for (i=1;i<255;i++) { + ifr.ifr_ifindex=i; + if (ioctl(sock,SIOCGIFNAME,&ifr)==-1) { + /* There may be gaps in the interface enumeration, so just continue */ + continue; + } + if (ioctl(sock,SIOCGIFADDR, &ifr)==-1) { + continue; + } + if (((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr.s_addr==a->ipv4.s_addr) { + res=1; + break; + } + } + close(sock); + } + +# endif +# ifdef ENABLE_IPV6 + ELSE_IPV6 { + char buf[40]; + FILE *f; + struct in6_addr b; + /* the interface configuration and information retrieval is obiously currently done via + * rt-netlink sockets. I think it is relatively likely to change in an incompatible way the + * Linux kernel (there seem to be some major changes for 2.4). + * Right now, I just analyze the /proc/net/if_inet6 entry. This may not be the fastest, but + * should work and is easy to adapt should the format change. */ + if (!(f=fopen("/proc/net/if_inet6","r"))) { + if(++if_inet6_open_errs<=MAX_IF_INET6_OPEN_ERRS) { + log_warn("Could not open /proc/net/if_inet6 in is_local_addr(): %s",strerror(errno)); + } + return 0; + } + /* The address is at the start of the line. We just read 32 characters and insert a ':' 7 + * times. Such, we can use inet_pton conveniently. More portable, that. */ + for(;;) { + int i,ch; char *p=buf; + for (i=0;i<32;i++) { + if(i && i%4==0) *p++ = ':'; + if ((ch=fgetc(f))==EOF) + goto fclose_return; /* we are at the end of the file and haven't found anything.*/ + if(ch=='\n') goto nextline; + *p++ = ch; + } + *p=0; + if (inet_pton(AF_INET6,buf,&b) >0) { + if (IN6_ARE_ADDR_EQUAL(&b,&a->ipv6)) { + res=1; + goto fclose_return; + } + } + do { + if ((ch=fgetc(f))==EOF) goto fclose_return; + } while(ch!='\n'); + nextline:; + } + fclose_return: + fclose(f); + } +# endif + return res; +} + +# else /*(TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN)*/ + + +#define MAX_SIOCGIFCONF_ERRS 4 +static volatile unsigned long siocgifconf_errs=0; + +int is_local_addr(pdnsd_a *a) +{ + int retval=0, sock, cnt; + struct ifconf ifc; + char buf[2048]; + + + if ((sock=socket(PF_INET,SOCK_DGRAM, IPPROTO_UDP))==-1) { + if(++socketopen_errs<=MAX_SOCKETOPEN_ERRS) { + log_warn("Could not open socket in is_local_addr(): %s",strerror(errno)); + } + return 0; + } + + ifc.ifc_len=sizeof(buf); + ifc.ifc_buf=buf; + if (ioctl(sock,SIOCGIFCONF,&ifc)==-1) { + if(++siocgifconf_errs<=MAX_SIOCGIFCONF_ERRS) { + log_warn("ioctl() call with request SIOCGIFCONF failed in is_local_addr(): %s",strerror(errno)); + } + goto close_sock_return; + } + + cnt=0; + while(cnt+sizeof(struct ifreq)<=ifc.ifc_len) { + struct ifreq *ir= (struct ifreq *)(buf+cnt); + cnt += SIZEOF_ADDR_IFREQ(*ir); + if (cnt>ifc.ifc_len) + break; + if (SEL_IPVER(ir->ifr_addr.sa_family==AF_INET && + ((struct sockaddr_in *)&ir->ifr_addr)->sin_addr.s_addr==a->ipv4.s_addr, + ir->ifr_addr.sa_family==AF_INET6 && + IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)&ir->ifr_addr)->sin6_addr, + &a->ipv6))) + { + retval=1; + break; + } + } + + close_sock_return: + close(sock); + + return retval; +} + +# endif + +#else +# error "Huh. No OS macro defined." +#endif diff --git a/jni/pdnsd/src/netdev.h b/jni/pdnsd/src/netdev.h new file mode 100644 index 00000000..529b8a88 --- /dev/null +++ b/jni/pdnsd/src/netdev.h @@ -0,0 +1,32 @@ +/* netdev.h - Test network devices for existence and status + Copyright (C) 2000 Thomas Moestl + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _NETDEV_H_ +#define _NETDEV_H_ + +#include +#include "ipvers.h" + +int if_up(char *devname); +int dev_up(char *ifname, char *devname); +int is_local_addr(pdnsd_a *a); + +#endif diff --git a/jni/pdnsd/src/pdnsd-ctl/Makefile.am b/jni/pdnsd/src/pdnsd-ctl/Makefile.am new file mode 100644 index 00000000..bcb73274 --- /dev/null +++ b/jni/pdnsd/src/pdnsd-ctl/Makefile.am @@ -0,0 +1,18 @@ + +sbin_PROGRAMS = pdnsd-ctl + +pdnsd_ctl_SOURCES = pdnsd-ctl.c +pdnsd_ctl_LDADD = rr_types.o +pdnsd_ctl_DEPENDENCIES = rr_types.o + +# These are Symlinks we want to have in the package +#EXTRA_DIST = rr_types.h + +pdnsd-ctl.o rr_types.o: ../rr_types.h + +../rr_types.h: ../make_rr_types_h.pl ../rr_types.in + perl ../make_rr_types_h.pl ../rr_types.in > ../rr_types.h + +rr_types.o: %.o: ../%.c + $(COMPILE) -DCLIENT_ONLY -c $< + diff --git a/jni/pdnsd/src/pdnsd-ctl/Makefile.in b/jni/pdnsd/src/pdnsd-ctl/Makefile.in new file mode 100644 index 00000000..80f39872 --- /dev/null +++ b/jni/pdnsd/src/pdnsd-ctl/Makefile.in @@ -0,0 +1,470 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +sbin_PROGRAMS = pdnsd-ctl$(EXEEXT) +subdir = src/pdnsd-ctl +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am_pdnsd_ctl_OBJECTS = pdnsd-ctl.$(OBJEXT) +pdnsd_ctl_OBJECTS = $(am_pdnsd_ctl_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(pdnsd_ctl_SOURCES) +DIST_SOURCES = $(pdnsd_ctl_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pdnsd_ctl_SOURCES = pdnsd-ctl.c +pdnsd_ctl_LDADD = rr_types.o +pdnsd_ctl_DEPENDENCIES = rr_types.o +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .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) --gnu src/pdnsd-ctl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/pdnsd-ctl/Makefile +.PRECIOUS: 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-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + 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) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(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: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) +pdnsd-ctl$(EXEEXT): $(pdnsd_ctl_OBJECTS) $(pdnsd_ctl_DEPENDENCIES) + @rm -f pdnsd-ctl$(EXEEXT) + $(LINK) $(pdnsd_ctl_OBJECTS) $(pdnsd_ctl_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdnsd-ctl.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +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 $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; 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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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-sbinPROGRAMS 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-sbinPROGRAMS + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-sbinPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-sbinPROGRAMS ctags distclean distclean-compile \ + distclean-generic 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-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-sbinPROGRAMS + + +# These are Symlinks we want to have in the package +#EXTRA_DIST = rr_types.h + +pdnsd-ctl.o rr_types.o: ../rr_types.h + +../rr_types.h: ../make_rr_types_h.pl ../rr_types.in + perl ../make_rr_types_h.pl ../rr_types.in > ../rr_types.h + +rr_types.o: %.o: ../%.c + $(COMPILE) -DCLIENT_ONLY -c $< + +# 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/jni/pdnsd/src/pdnsd-ctl/pdnsd-ctl.c b/jni/pdnsd/src/pdnsd-ctl/pdnsd-ctl.c new file mode 100644 index 00000000..33a21cec --- /dev/null +++ b/jni/pdnsd/src/pdnsd-ctl/pdnsd-ctl.c @@ -0,0 +1,799 @@ +/* pdnsd-ctl.c - Control pdnsd through a pipe + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include /* for offsetof */ +#include "../helpers.h" +#include "../status.h" +#include "../conff.h" +#include "../list.h" +#include "../dns.h" +#include "../rr_types.h" +#include "../cache.h" + +#if !defined(HAVE_ALLOCA) && !defined(alloca) +#define alloca malloc +#endif + + +#if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_PTON) +# define ALLOW_AAAA IS_CACHED_AAAA +#else +# define ALLOW_AAAA 0 +#endif + +static short int verbose=1; + +typedef struct { + char *name; + int val; +} cmd_s; + +#define CMD_LIST_RRTYPES (CTL_MAX+1) +#define CMD_HELP (CTL_MAX+2) +#define CMD_VERSION (CTL_MAX+3) + +static const cmd_s top_cmds[]={ + {"help",CMD_HELP},{"version",CMD_VERSION},{"list-rrtypes",CMD_LIST_RRTYPES}, + {"status",CTL_STATS},{"server",CTL_SERVER},{"record",CTL_RECORD}, + {"source",CTL_SOURCE},{"add",CTL_ADD},{"neg",CTL_NEG}, + {"config",CTL_CONFIG},{"include",CTL_INCLUDE},{"eval",CTL_EVAL}, + {"empty-cache",CTL_EMPTY}, {"dump",CTL_DUMP}, + {NULL,0} +}; +static const cmd_s server_cmds[]= {{"up",CTL_S_UP},{"down",CTL_S_DOWN},{"retest",CTL_S_RETEST},{NULL,0}}; +static const cmd_s record_cmds[]= {{"delete",CTL_R_DELETE},{"invalidate",CTL_R_INVAL},{NULL,0}}; +static const cmd_s onoff_cmds[]= {{"off",0},{"on",1},{NULL,0}}; +static const cmd_s rectype_cmds[]= {{"a",T_A}, +#if ALLOW_AAAA + {"aaaa",T_AAAA}, +#endif + {"ptr",T_PTR},{"cname",T_CNAME},{"mx",T_MX},{"ns",T_NS},{NULL,0}}; + +static const char version_message[] = + "pdnsd-ctl, version pdnsd-" VERSION "\n\n"; + +static const char license_statement[] = + "Copyright (C) 2000, 2001 Thomas Moestl\n" + "Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Paul A. Rombouts\n\n" + "This program is part of the pdnsd package.\n\n" + "pdnsd is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 3 of the License, or\n" + "(at your option) any later version.\n\n" + "pdnsd is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n\n" + "You should have received a copy of the GNU General Public License\n" + "along with pdsnd; see the file COPYING. If not, see\n" + ".\n"; + +static const char *const help_messages[] = +{ + "Usage: pdnsd-ctl [-c cachedir] [-q] [arguments]\n\n" + + "Command-line options:\n" + + "-c\tcachedir\n\tSet the cache directory to cachedir (must match pdnsd setting).\n" + "\tThe default is '" CACHEDIR "'.\n" + "-q\n\tBe quiet unless output is specified by command or something goes wrong.\n\n" + + "Commands and needed arguments are:\n" + + "help\t[no arguments]\n\tPrint this help.\n" + "version\t[no arguments]\n\tPrint version and license info.\n", + + "status\t[no arguments]\n\tPrint pdnsd's status.\n", + + "server\t(index|label)\t(up|down|retest)\t[dns1[,dns2[,...]]]\n" + "\tSet the status of the server with the given index to up or down, or\n" + "\tforce a retest. The index is assigned in the order of definition in\n" + "\tpdnsd.conf starting with 0. Use the status command to see the indexes.\n" + "\tYou can specify the label of a server (that matches the label option)\n" + "\tinstead of an index to make this easier.\n" + + "\tYou can specify all instead of an index to perform the action for all\n" + "\tservers registered with pdnsd.\n" + + "\tAn optional third argument can be given consisting of a list of IP\n" + "\taddresses separated by commas or spaces. This list will replace the\n" + "\taddresses of name servers used by pdnsd for the given server section.\n" + "\tThis feature is useful for run-time configuration of pdnsd with dynamic\n" + "\tDNS data in scripts called by ppp or DHCP clients. The last argument\n" + "\tmay also be an empty string, which causes existing IP addresses to be\n" + "\tremoved and the corresponding server section to become inactive.\n", + + "record\tname\t(delete|invalidate)\n" + "\tDelete or invalidate the record of the given domain if it is in the\n" + "\tcache.\n", + + "source\tfn\towner\t[ttl]\t[(on|off)]\t[noauth]\n" + "\tLoad a hosts-style file. Works like using the pdnsd source\n" + "\tconfiguration section.\n" + "\tOwner and ttl are used as in the source section. ttl has a default\n" + "\tof 900 (it does not need to be specified). The next to last argument\n" + "\tcorresponds to the serve_aliases option, and is off by default.\n" + "\tnoauth is used to make the domains non-authoritative (please\n" + "\tconsult the pdnsd manual for what that means).\n" + "\tfn is the name of the file, which must be readable by pdnsd.\n", + + "add\ta\taddr\tname\t[ttl]\t[noauth]\n" +#if ALLOW_AAAA + "add\taaaa\taddr\tname\t[ttl]\t[noauth]\n" +#endif + "add\tptr\thost\tname\t[ttl]\t[noauth]\n" + "add\tcname\thost\tname\t[ttl]\t[noauth]\n" + "add\tmx\thost\tname\tpref\t[ttl]\t[noauth]\n" + "add\tns\thost\tname\t[ttl]\t[noauth]\n" + "\tAdd a record of the given type to the pdnsd cache, replacing existing\n" + "\trecords for the same name and type. The 2nd argument corresponds\n" + "\tto the value of the option in the rr section that is named like\n" + "\tthe first argument. The addr argument may be a list of IP addresses,\n" + "\tseparated by commas or white space. The ttl is optional, the default is\n" + "\t900 seconds. noauth is used to make the domains non-authoritative.\n" + "\tIf you want no other record than the newly added in the cache, do\n" + "\tpdnsdctl record delete\n" + "\tbefore adding records.\n", + + "neg\tname\t[type]\t[ttl]\n" + "\tAdd a negatively cached record to pdnsd's cache, replacing existing\n" + "\trecords for the same name and type. If no type is given, the whole\n" + "\tdomain is cached negatively. For negatively cached records, errors are\n" + "\timmediately returned on a query, without querying other servers first.\n" + "\tThe ttl is optional, the default is 900 seconds.\n", + + "config\t[filename]\n" + "\tReload pdnsd's configuration file.\n" + "\tThe config file must be owned by the uid that pdnsd had when it was\n" + "\tstarted, and be readable by pdnsd's run_as uid. If no file name is\n" + "\tspecified, the config file used at start up is reloaded.\n", + + "include\tfilename\n" + "\tParse the given file as an include file, which may contain the same\n" + "\ttype of sections as a config file, expect for global and server\n" + "\tsections, which are not allowed. This command can be used to add data\n" + "\tto the cache without reconfiguring pdnsd.\n", + + "eval\tstring\n" + "\tParse string as if it were part of pdnsd's configuration file.\n" + "\tThe string should hold one or more complete configuration sections,\n" + "\tbut no global and server sections, which are not allowed.\n" + "\tIf multiple strings are given, they will be joined using newline chars\n" + "\tand parsed together.\n", + + "empty-cache\t[[+|-]name ...]\n" + "\tDelete all entries in the cache matching include/exclude rules.\n" + "\tIf no arguments are provided, the cache is completely emptied,\n" + "\tfreeing all existing entries. This also removes \"local\" records,\n" + "\tas defined by the config file. To restore local records, run\n" + "\t\"pdnsd-ctl config\" or \"pdnsd-ctl include filename\" immediately\n" + "\tafterwards.\n" + "\tIf one or more arguments are provided, these are interpreted as \n" + "\tinclude/exclude names. If an argument starts with a '+' the name is to\n" + "\tbe included. If an argument starts with a '-' it is to be excluded.\n" + "\tIf an argument does not begin with '+' or '-', a '+' is assumed.\n" + "\tIf the domain name of a cache entry ends in one of the names in the\n" + "\tlist, the first match will determine what happens. If the matching name\n" + "\tis to be included, the cache entry is deleted, otherwise it remains.\n" + "\tIf there are no matches, the default action is not to delete.\n", + + "dump\t[name]\n" + "\tPrint information stored in the cache about name.\n" + "\tIf name begins with a dot and is not the root domain, information\n" + "\tabout the names in the cache ending in name (including name without\n" + "\tthe leading dot) will be printed. If name is missing, information about\n" + "\tall the names in the cache will be printed.\n", + + "list-rrtypes\t[no arguments]\n" + "\tList available rr types for the neg command. Note that those are only\n" + "\tused for the neg command, not for add!\n" +}; + +#define NUM_HELP_MESSAGES (sizeof(help_messages)/sizeof(char*)) + + +/* Open connection to control socket and send command code. + If successful, open_sock returns a file descriptor for the new socket, + otherwise the program is aborted. +*/ +static int open_sock(const char *cache_dir, uint16_t cmd) +{ + struct sockaddr_un *sa; + unsigned int sa_len; + int sock; + uint16_t nc; + + if ((sock=socket(PF_UNIX,SOCK_STREAM,0))==-1) { + perror("Error: could not open socket"); + exit(2); + } + + sa_len = (offsetof(struct sockaddr_un, sun_path) + strlitlen("/pdnsd.status") + strlen(cache_dir)); + sa=(struct sockaddr_un *)alloca(sa_len+1); + sa->sun_family=AF_UNIX; + stpcpy(stpcpy(sa->sun_path,cache_dir),"/pdnsd.status"); + + if (connect(sock,(struct sockaddr *)sa,sa_len)==-1) { + fprintf(stderr,"Error: could not open socket %s: %s\n",sa->sun_path,strerror(errno)); + close(sock); + exit(2); + } + if(verbose) printf("Opening socket %s\n",sa->sun_path); + + /* Send command code */ + + nc=htons(cmd|CTL_CMDVERNR); /* Add magic number, convert to network byte order. */ + + if (write(sock,&nc,sizeof(nc))!=sizeof(nc)) { + perror("Error: could not write command code"); + close(sock); + exit(2); + } + + return sock; +} + +static void send_long(int fd,uint32_t cmd) +{ + uint32_t nc=htonl(cmd); + + if (write(fd,&nc,sizeof(nc))!=sizeof(nc)) { + perror("Error: could not write long"); + close(fd); + exit(2); + } +} + +static void send_short(int fd,uint16_t cmd) +{ + uint16_t nc=htons(cmd); + + if (write(fd,&nc,sizeof(nc))!=sizeof(nc)) { + perror("Error: could not write short"); + close(fd); + exit(2); + } +} + +#define MAXSENDSTRLEN 0xfffe + +static void send_string(int fd, const char *s) +{ + if(s) { + size_t len=strlen(s); + if(len>MAXSENDSTRLEN) { + fprintf(stderr,"Error: send_string: string length (%lu) exceeds maximum (%u).\n", + (unsigned long)len, MAXSENDSTRLEN); + close(fd); + exit(2); + } + send_short(fd,len); + if (write_all(fd,s,len)!=len) { + perror("Error: could not write string"); + close(fd); + exit(2); + } + } + else + send_short(fd, ~0); +} + +static uint16_t read_short(int fd) +{ + ssize_t err; + uint16_t nc; + + if ((err=read(fd,&nc,sizeof(nc)))!=sizeof(nc)) { + fprintf(stderr,"Error: could not read short: %s\n",err<0?strerror(errno):"unexpected EOF"); + close(fd); + exit(2); + } + return ntohs(nc); +} + +/* copy data from file descriptor fd to file stream out until EOF + or error is encountered. +*/ +static ssize_t copymsgtofile(int fd, FILE* out) +{ + ssize_t n,ntot=0; + char buf[1024]; + + while ((n=read(fd,buf,sizeof(buf)))>0) + ntot+=fwrite(buf,1,n,out); + + if(n<0) + return n; + + return ntot; +} + +static int match_cmd(const char *cmd, const cmd_s cmds[]) +{ + int i; + for(i=0; cmds[i].name; ++i) { + if (strcasecmp(cmd,cmds[i].name)==0) + return cmds[i].val; + } + return -1; +} + +int main(int argc, char *argv[]) +{ + char *cache_dir= CACHEDIR; + int rv=0; + { + int i; + char *arg; + for(i=1; i4) + goto wrong_args; + acnt=2; + server_cmd=match_cmd(argv[2],server_cmds); + if(server_cmd==-1) goto bad_arg; + pf=open_sock(cache_dir, cmd); + send_string(pf,argv[1]); + send_short(pf,server_cmd); + send_string(pf,argc<4?NULL:argv[3]); + } + goto read_retval; + + case CTL_RECORD: { + int record_cmd; + if (argc!=3) + goto wrong_args; + acnt=2; + record_cmd=match_cmd(argv[2],record_cmds); + if(record_cmd==-1) goto bad_arg; + pf=open_sock(cache_dir, cmd); + send_short(pf,record_cmd); + send_string(pf,argv[1]); + } + goto read_retval; + + case CTL_SOURCE: { + long ttl; + int servaliases,flags; + if (argc<3 || argc>6) + goto wrong_args; + ttl=900; + flags=DF_LOCAL; + acnt=3; + if (argc==6 || (argc>=4 && isdigit(argv[3][0]))) { + char *endptr; + ttl=strtol(argv[3],&endptr,0); + if (*endptr) + goto bad_arg; + acnt++; + } + servaliases=0; + if (acntacnt+2) + goto wrong_args; + + ttl=900; + flags=DF_LOCAL; + pref=0; + if(tp==T_MX) { + char *endptr; + pref=strtol(argv[4],&endptr,0); + if (*endptr) { + acnt=4; + goto bad_arg; + } + } + + if (acnt4) + goto wrong_args; + tp=255; + ttl=900; + acnt=2; + if (argc==3) { + if (isdigit(argv[2][0])) { + char *endptr; + ttl=strtol(argv[2],&endptr,0); + if (*endptr) + goto bad_arg; + } else if ((tp=rr_tp_byname(argv[2]))==-1) { + goto bad_type; + } + } else if (argc==4) { + char *endptr; + if ((tp=rr_tp_byname(argv[2]))==-1) + goto bad_type; + ttl=strtol(argv[3],&endptr,0); + if (*endptr) { + acnt=3; + goto bad_arg; + } + } + pf=open_sock(cache_dir, cmd); + send_string(pf,argv[1]); + send_short(pf,tp); + send_long(pf,ttl); + } + goto read_retval; + + case CTL_CONFIG: + if (argc>2) + goto wrong_args; + pf=open_sock(cache_dir, cmd); + send_string(pf,argc<2?NULL:argv[1]); + goto read_retval; + + case CTL_INCLUDE: + if (argc!=2) + goto wrong_args; + pf=open_sock(cache_dir, cmd); + send_string(pf,argv[1]); + goto read_retval; + + case CTL_EVAL: { + int i; size_t bufsz; + + if (argc<2) + goto wrong_args; + bufsz=0; + for(i=1; iMAXSENDSTRLEN) { + fprintf(stderr,"Cannot send 'eval' command: " + "string length (%lu) exceeds maximum (%u).\n", + (unsigned long)bufsz, MAXSENDSTRLEN); + exit(2); + } + pf=open_sock(cache_dir, cmd); + send_short(pf,bufsz); + { + /* Variable-size array for storing the joined strings. */ + char buf[bufsz]; + char *p=buf; + for(i=1; iMAXSENDSTRLEN) { + fprintf(stderr,"Cannot send 'empty' command: " + "string length (%lu) exceeds maximum (%u).\n", + (unsigned long)totsz, MAXSENDSTRLEN); + exit(2); + } + pf=open_sock(cache_dir, cmd); + if(argc>1) { + send_short(pf,totsz); + for(i=1; i2) + goto wrong_args; + pf=open_sock(cache_dir, cmd); + send_string(pf,argc<2?NULL:argv[1]); + copy_pf: + if((rv=read_short(pf))) + goto retval_failed; + if(copymsgtofile(pf,stdout)<0) { + perror("Error while reading from socket"); + close(pf); + exit(2); + } + goto close_pf; + + read_retval: + if((rv=read_short(pf))) { + retval_failed: + fprintf(stderr,"Failed: "); + if(copymsgtofile(pf,stderr)<0) + fprintf(stderr,"(could not read error message from socket: %s)",strerror(errno)); + + fputc('\n',stderr); + } + close_pf: + if(close(pf)==-1) + perror("Couldn't close socket"); + else if (rv==0 && verbose) + printf("Succeeded\n"); + break; + wrong_args: + fprintf(stderr,"Wrong number of arguments for '%s' command.\n",argv[0]); + goto print_cmd_usage; + bad_arg: + fprintf(stderr,"Bad argument for '%s' command: %s\n",argv[0],argv[acnt]); + print_cmd_usage: + fprintf(stderr,"Usage:\n\n%s\n" + "Try 'pdnsd-ctl help' for a description of all available commands and options.\n", + help_messages[cmd]); + exit(2); + bad_type: + fprintf(stderr,"Bad (type) argument for '%s' command: %s\n" + "Run 'pdnsd-ctl list-rrtypes' for a list of available rr types.\n", + argv[0],argv[acnt]); + exit(2); + } + } + + return rv; +} + diff --git a/jni/pdnsd/src/pdnsd_assert.h b/jni/pdnsd/src/pdnsd_assert.h new file mode 100644 index 00000000..0acdfc24 --- /dev/null +++ b/jni/pdnsd/src/pdnsd_assert.h @@ -0,0 +1,51 @@ +/* This include file was added by Paul A. Rombouts. + I had terrible difficulties with cyclic dependencies of the include files + written by Thomas Moestl. The only way I knew how to break the cycle was to + put some declarations in a seperate file. + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#ifndef PDNSD_ASSERT_H +#define PDNSD_ASSERT_H + +/* Originally in helpers.h */ + +/* format string checking for printf-like functions */ +#ifdef __GNUC__ +#define printfunc(fmt, firstva) __attribute__((__format__(__printf__, fmt, firstva))) +#else +#define printfunc(fmt, firstva) +#endif + +void pdnsd_exit(void); + + +/* + * Assert macro, used in some places. For now, it should be always defined, not + * only in the DEBUG case, to be on the safe side security-wise. + */ +#define PDNSD_ASSERT(cond, msg) \ + { if (!(cond)) { \ + log_error("%s:%d: %s", __FILE__, __LINE__, msg); \ + pdnsd_exit(); \ + } } + +#endif diff --git a/jni/pdnsd/src/rc/ArchLinux/Makefile.am b/jni/pdnsd/src/rc/ArchLinux/Makefile.am new file mode 100644 index 00000000..2a7b4204 --- /dev/null +++ b/jni/pdnsd/src/rc/ArchLinux/Makefile.am @@ -0,0 +1,7 @@ + +install-exec-local: + if [ "$(distribution)" = "ArchLinux" ] ; then \ + $(mkinstalldirs) "$(DESTDIR)/etc/rc.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/rc.d/pdnsd";\ + fi + diff --git a/jni/pdnsd/src/rc/ArchLinux/Makefile.in b/jni/pdnsd/src/rc/ArchLinux/Makefile.in new file mode 100644 index 00000000..6af6f9e4 --- /dev/null +++ b/jni/pdnsd/src/rc/ArchLinux/Makefile.in @@ -0,0 +1,332 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = src/rc/ArchLinux +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/pdnsd.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdnsd +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +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) --gnu src/rc/ArchLinux/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/ArchLinux/Makefile +.PRECIOUS: 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): +pdnsd: $(top_builddir)/config.status $(srcdir)/pdnsd.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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-exec-local + +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 + +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 distclean \ + distclean-generic 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-exec-local \ + 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 pdf pdf-am ps ps-am uninstall \ + uninstall-am + + +install-exec-local: + if [ "$(distribution)" = "ArchLinux" ] ; then \ + $(mkinstalldirs) "$(DESTDIR)/etc/rc.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/rc.d/pdnsd";\ + fi + +# 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/jni/pdnsd/src/rc/ArchLinux/pdnsd.in b/jni/pdnsd/src/rc/ArchLinux/pdnsd.in new file mode 100644 index 00000000..c3927506 --- /dev/null +++ b/jni/pdnsd/src/rc/ArchLinux/pdnsd.in @@ -0,0 +1,45 @@ +#!/bin/bash + +. /etc/rc.conf +. /etc/rc.d/functions + +PID=`pidof -o %PPID @prefix@/sbin/pdnsd` + +start() { + stat_busy "Starting PDNSD" + [ -z "$PID" ] && @prefix@/sbin/pdnsd -d -c /etc/pdnsd.conf + if [ $? -gt 0 ]; then + stat_fail + else + add_daemon pdnsd + stat_done + fi +} + +stop() { + stat_busy "Stopping PDNSD" + [ ! -z "$PID" ] && kill $PID &> /dev/null + if [ $? -gt 0 ]; then + stat_fail + else + rm_daemon pdnsd + stat_done + fi +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + $0 stop + sleep 2 + $0 start + ;; + *) + echo "usage: $0 {start|stop|restart}" +esac +exit 0 diff --git a/jni/pdnsd/src/rc/Debian/Makefile.am b/jni/pdnsd/src/rc/Debian/Makefile.am new file mode 100644 index 00000000..61d3eb3b --- /dev/null +++ b/jni/pdnsd/src/rc/Debian/Makefile.am @@ -0,0 +1,8 @@ + +install-exec-local: + if [ "$(distribution)" = "Debian" ] ; then \ + CURDIR=`pwd`; \ + $(mkinstalldirs) "$(DESTDIR)/etc/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/init.d"; \ + update-rc.d pdnsd defaults 19 ;\ + fi diff --git a/jni/pdnsd/src/rc/Debian/Makefile.in b/jni/pdnsd/src/rc/Debian/Makefile.in new file mode 100644 index 00000000..992a0597 --- /dev/null +++ b/jni/pdnsd/src/rc/Debian/Makefile.in @@ -0,0 +1,334 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = src/rc/Debian +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/pdnsd.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdnsd +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +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) --gnu src/rc/Debian/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/Debian/Makefile +.PRECIOUS: 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): +pdnsd: $(top_builddir)/config.status $(srcdir)/pdnsd.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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-exec-local + +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 + +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 distclean \ + distclean-generic 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-exec-local \ + 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 pdf pdf-am ps ps-am uninstall \ + uninstall-am + + +install-exec-local: + if [ "$(distribution)" = "Debian" ] ; then \ + CURDIR=`pwd`; \ + $(mkinstalldirs) "$(DESTDIR)/etc/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/init.d"; \ + update-rc.d pdnsd defaults 19 ;\ + fi + +# 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/jni/pdnsd/src/rc/Debian/pdnsd.in b/jni/pdnsd/src/rc/Debian/pdnsd.in new file mode 100644 index 00000000..068606ee --- /dev/null +++ b/jni/pdnsd/src/rc/Debian/pdnsd.in @@ -0,0 +1,52 @@ +#!/bin/sh + +# +# This script was written and contributed by Markus Mohr, and +# slightly modified by me for version 1.0.6 (which obviously +# broke it some way). I then applied a set of corrections +# by Markus Mohr. +# +# Carsten Block has patched this with some magic so that +# the actual script is generated by configure, and that +# the pdnsd user is determined from pdnsd.conf +# I changed this a little to use the --pdnsd-user option +# of pdnsd to determine the run_as user. +# + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +test -x @prefix@/sbin/pdnsd || exit 0 + +case "$1" in + start) + # Check if cache dir exists and recreate if neccessary + test -d @cachedir@ || mkdir @cachedir@ + RUNAS=`@prefix@/sbin/pdnsd --pdnsd-user` || echo -n " failed" + [ -z "$RUNAS" ] && RUNAS=nobody + chown $RUNAS @cachedir@ + echo -n "Starting domain name service: pdnsd" + start-stop-daemon --start --quiet --pidfile /var/run/pdnsd.pid --name pdnsd \ + --exec @prefix@/sbin/pdnsd -- --daemon -p /var/run/pdnsd.pid \ + || echo -n " failed" + echo "." + ;; + + stop) + echo -n "Stopping domain name service: pdnsd" + start-stop-daemon --stop --quiet --pidfile /var/run/pdnsd.pid --name pdnsd --exec @prefix@/sbin/pdnsd \ + || echo -n " failed" + echo "." + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: /etc/init.d/pdnsd {start|stop|restart}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/jni/pdnsd/src/rc/Makefile.am b/jni/pdnsd/src/rc/Makefile.am new file mode 100644 index 00000000..abf2e6dc --- /dev/null +++ b/jni/pdnsd/src/rc/Makefile.am @@ -0,0 +1,5 @@ + +SUBDIRS = RedHat SuSE Debian Slackware ArchLinux + +EXTRA_DIST = README + diff --git a/jni/pdnsd/src/rc/Makefile.in b/jni/pdnsd/src/rc/Makefile.in new file mode 100644 index 00000000..38ee297c --- /dev/null +++ b/jni/pdnsd/src/rc/Makefile.in @@ -0,0 +1,526 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = src/rc +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +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@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = RedHat SuSE Debian Slackware ArchLinux +EXTRA_DIST = README +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) --gnu src/rc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/Makefile +.PRECIOUS: 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): + +# 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. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; 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" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +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 \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + 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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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 + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic 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 pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am + + +# 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/jni/pdnsd/src/rc/README b/jni/pdnsd/src/rc/README new file mode 100644 index 00000000..4e007640 --- /dev/null +++ b/jni/pdnsd/src/rc/README @@ -0,0 +1,104 @@ +rc/ +=== + +These are start scripts for different Linux distros and other things that +do not directly belong to pdnsd. +If you do start scripts for the distro you use, please GPL them and send +them in, so that they can be included in this package for other users. +Note that there is NO WARRANTY OF ANY KIND on anything in this directory; +read the COPYING that comes with pdnsd for details. +So far there are files in the following directories: + +SuSE +---- +pdnsd - Start script for SuSE Linux. Tested for 6.? but should run on some + versions below. You can do 'make install' as root in the SuSE + directory to install it, or you can install manually: + --manual installation------------------------------------------------- + For manual installation, copy it into /sbin/init.d/, go to + /sbin/init.d/rc2.d/ and create there the following two symlinks: + S11pdnsd -> ../pdnsd (do "ln -s ../pdnsd S11pdnsd" in that dir) + K34pdnsd -> ../pdnsd (do "ln -s ../pdnsd K34pdnsd" in that dir) + The numbers dictate the order different services are started and + might need to be modified. Then edit your /etc/rc.config file and + add the line "START_PDNSD=yes" to start pdnsd at boot time. + ---------------------------------------------------------------------- + If you used the 'make install' command, "START_PDNSD=yes" has been + appended to your /etc/rc.config file, causing pdnsd to be started + at boot time. If you don't want that, change the "yes" into "no". + This start script was created from /sbin/init.d/skeleton by me, so the + most is copyrighted by SuSE. They put it under the GPL, however, so + the licence stated in COPYING also applies to this script. + This is no official SuSE script, and SuSE naturally does NO support + for it. + +Redhat +------ +The contents of the Redhat directory and the following documentation were +contributed by Torben Janssen. Thanks a lot! + +pdnsd - Start script for Redhat Linux. Tested for 6.1 but should run on 5.0+. + You can do 'make install' as root in the Redhat directory to + install it, or you can install manually: + + --manual installation------------------------------------------------- + For manual installation, copy pdnsd into /etc/rc.d/init.d/ + + Then go to /etc/rc.d/rc3.d and create there the following symlink: + S78pdnsd -> ../init.d/pdnsd + (do "ln -f -s ../init.d/pdnsd S78pdnsd" in that dir) + + Then go to /etc/rc.d/rc0.d and create there the following symlink: + K78pdnsd -> ../init.d/pdnsd + (do "ln -f -s ../init.d/pdnsd K78pdnsd" in that dir) + + Then go to /etc/rc.d/rc6.d and create there the following symlink: + K78pdnsd -> ../init.d/pdnsd + (do "ln -f -s ../init.d/pdnsd K78pdnsd" in that dir) + + WHY + --- + the rc[0-6].d dirs includes the scripts which starts/stops the + services on entering runlevel [0-6] + the interesting runlevels on Redhat are: + 0 - halt + 3 - multi user system + 6 - reboot + The links have an 'S' or 'K' and a number at the beginnig. All links + with 'S' starts the script on entering the runlevel and 'K' stops + them. + So, there's an 'S' link in rc3 and 'K' links in rc0 and rc6. + I choose 78 as number, because there was no script with this number on + my system. You can choose every number you want, AFAIK . + + This is no offical Redhat script, and Redhat naturally does NO support + for it. + +Debian +------ +The contents of the Debian directory were contributed by Markus Mohr. +His installation instructions are (translated): +Install the pdnsd script to /etc/init and run +update-rc.d pdnsd defaults 19 +as root. + +Slackware +--------- +A Slackware start-up script rc.pdnsd was contributed by Nikola Kotur . +His comments were: + +Slackware uses traditional BSD style init script layout instead of SystemV +style startup scripts. So I adjusted the start-up script for pdnsd, and +now it can be used with Slackware 9.1 distribution, and probably with all the +others. + +Additional info: +1) put these lines in the /etc/rc.d/rc.M: + if [ -x /etc/rc.d/rc.pdnsd ]; then + /etc/rc.d/rc.pdnsd start + fi + +2) put these lines in the /etc/rc.d/rc.6 and /etc/rc.d/rc.K: + if [ -x /etc/rc.d/rc.pdnsd ]; then + /etc/rc.d/rc.pdnsd stop + fi diff --git a/jni/pdnsd/src/rc/RedHat/Makefile.am b/jni/pdnsd/src/rc/RedHat/Makefile.am new file mode 100644 index 00000000..cb8de885 --- /dev/null +++ b/jni/pdnsd/src/rc/RedHat/Makefile.am @@ -0,0 +1,12 @@ + +# no need to create links. 'chkconfig' will take care of this. +# In the spec case, chkconfig is called during rpm install +install-exec-local: + if [ "$(distribution)" = "RedHat" ] ; then \ + $(mkinstalldirs) "$(DESTDIR)/etc/rc.d/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/rc.d/init.d/pdnsd"; \ + if [ "$(specbuild)" = "no" ] ; then \ + /sbin/chkconfig --add pdnsd; \ + fi \ + fi + diff --git a/jni/pdnsd/src/rc/RedHat/Makefile.in b/jni/pdnsd/src/rc/RedHat/Makefile.in new file mode 100644 index 00000000..a88a037c --- /dev/null +++ b/jni/pdnsd/src/rc/RedHat/Makefile.in @@ -0,0 +1,337 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = src/rc/RedHat +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/pdnsd.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdnsd +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +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) --gnu src/rc/RedHat/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/RedHat/Makefile +.PRECIOUS: 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): +pdnsd: $(top_builddir)/config.status $(srcdir)/pdnsd.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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-exec-local + +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 + +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 distclean \ + distclean-generic 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-exec-local \ + 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 pdf pdf-am ps ps-am uninstall \ + uninstall-am + + +# no need to create links. 'chkconfig' will take care of this. +# In the spec case, chkconfig is called during rpm install +install-exec-local: + if [ "$(distribution)" = "RedHat" ] ; then \ + $(mkinstalldirs) "$(DESTDIR)/etc/rc.d/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/etc/rc.d/init.d/pdnsd"; \ + if [ "$(specbuild)" = "no" ] ; then \ + /sbin/chkconfig --add pdnsd; \ + fi \ + fi + +# 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/jni/pdnsd/src/rc/RedHat/pdnsd.in b/jni/pdnsd/src/rc/RedHat/pdnsd.in new file mode 100644 index 00000000..b6d9081d --- /dev/null +++ b/jni/pdnsd/src/rc/RedHat/pdnsd.in @@ -0,0 +1,88 @@ +#!/bin/bash +# +# /etc/rc.d/init.d/pdnsd +# +# Script for starting the Proxy DNS Daemon +# Modified by Paul Rombouts, 2003 +# +# chkconfig: 2345 11 89 +# description: Proxy DNS Daemon +# processname: pdnsd +# config: /etc/pdnsd.conf + +PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +if [[ $NETWORKING == [Nn][Oo] ]]; then exit 0; fi + +# Source sysconfig settings, if any. +if [ -f /etc/sysconfig/pdnsd ]; then . /etc/sysconfig/pdnsd; fi + +start() { + echo -n 'Starting pdnsd: ' + daemon @prefix@/sbin/pdnsd -d -s -p /var/run/pdnsd.pid "$EXTRAOPTIONS" + local RETVAL=$? + echo + if [ $RETVAL -eq 0 ]; then touch /var/lock/subsys/pdnsd; fi + return $RETVAL +} + +stop() { + echo -n 'Shutting down pdnsd: ' + killproc pdnsd + local RETVAL=$? + case @threadlib@ in + [Ll]inux[Tt]hreads*|lt*) + # Wait until all threads have terminated. + local -i count=20 + while [[ count -gt 0 ]] && pidof pdnsd > /dev/null + do + usleep 200000 + let --count + done + ;; + esac + echo + if [ $RETVAL -eq 0 ]; then rm -f /var/lock/subsys/pdnsd; fi + return $RETVAL +} + +restart() { + stop + start +} + +# +# See how we were called. +# +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status pdnsd + ;; + reload) + @prefix@/sbin/pdnsd-ctl config + ;; + restart) + restart + ;; + condrestart) + if [ -f /var/lock/subsys/pdnsd ]; then restart; fi + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}" + exit 1 +esac + +exit diff --git a/jni/pdnsd/src/rc/Slackware/Makefile.am b/jni/pdnsd/src/rc/Slackware/Makefile.am new file mode 100644 index 00000000..e44b50f8 --- /dev/null +++ b/jni/pdnsd/src/rc/Slackware/Makefile.am @@ -0,0 +1,3 @@ +# TODO: write an install rule for the Slackware start-up script. + +install-exec-local: diff --git a/jni/pdnsd/src/rc/Slackware/Makefile.in b/jni/pdnsd/src/rc/Slackware/Makefile.in new file mode 100644 index 00000000..14ebd33b --- /dev/null +++ b/jni/pdnsd/src/rc/Slackware/Makefile.in @@ -0,0 +1,330 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ + +# TODO: write an install rule for the Slackware start-up script. +VPATH = @srcdir@ +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 = : +subdir = src/rc/Slackware +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/rc.pdnsd.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = rc.pdnsd +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +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) --gnu src/rc/Slackware/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/Slackware/Makefile +.PRECIOUS: 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): +rc.pdnsd: $(top_builddir)/config.status $(srcdir)/rc.pdnsd.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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-exec-local + +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 + +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 distclean \ + distclean-generic 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-exec-local \ + 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 pdf pdf-am ps ps-am uninstall \ + uninstall-am + + +install-exec-local: + +# 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/jni/pdnsd/src/rc/Slackware/rc.pdnsd.in b/jni/pdnsd/src/rc/Slackware/rc.pdnsd.in new file mode 100644 index 00000000..6e969713 --- /dev/null +++ b/jni/pdnsd/src/rc/Slackware/rc.pdnsd.in @@ -0,0 +1,74 @@ +#!/bin/bash +# +# /etc/rc.d/rc.pdnsd +# +# Starts the Proxy DNS Daemon +# +# description: Proxy DNS Daemon +# processname: pdnsd +# config: /etc/pdnsd.conf +# distribution: Slackware +# author: Nikola Kotur +# +# Additional info: +# 1) put these lines in the /etc/rc.d/rc.M: +# if [ -x /etc/rc.d/rc.pdnsd ]; then +# /etc/rc.d/rc.pdnsd start +# fi +# +# 2) put these lines in the /etc/rc.d/rc.6 and /etc/rc.d/rc.K: +# if [ -x /etc/rc.d/rc.pdnsd ]; then +# /etc/rc.d/rc.pdnsd stop +# fi + + +test -x @prefix@/sbin/pdnsd || exit 0 +[ -f @sysconfdir@/pdnsd.conf ] || exit 1 + +RETVAL=0 + +start() { + echo -n "Starting pdnsd... " + RETVAL=$? + @prefix@/sbin/pdnsd -d + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/pdnsd + echo ' OK' +} + +stop() { + echo -n "Shutting down pdnsd... " + killall pdnsd + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/pdnsd + echo ' OK' +} + +restart() { + stop + start +} + +condrestart() { + [ -e /var/lock/subsys/pdnsd ] && restart + return 0 +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + reload|restart) + restart + ;; + condrestart) + condrestart + ;; + *) + echo $"Usage: $0 {start|stop|restart|condrestart|reload}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/jni/pdnsd/src/rc/SuSE/Makefile.am b/jni/pdnsd/src/rc/SuSE/Makefile.am new file mode 100644 index 00000000..dc5f485b --- /dev/null +++ b/jni/pdnsd/src/rc/SuSE/Makefile.am @@ -0,0 +1,22 @@ + +install-exec-local: + if [ "$(distribution)" = "SuSE" ] ; then \ + CURDIR=`pwd`; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/sbin/init.d/pdnsd"; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d/rc2.d"; \ + cd "$(DESTDIR)/sbin/init.d/rc2.d"; \ + ln -fs ../pdnsd K34pdnsd; ln -s ../pdnsd S11pdnsd; \ + cd $$CURDIR ; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d/rc3.d"; \ + cd "$(DESTDIR)/sbin/init.d/rc3.d"; \ + ln -fs ../pdnsd K34pdnsd; ln -s ../pdnsd S11pdnsd; \ + cd $$CURDIR ; \ + grep "START_PDNSD" "$(DESTDIR)/etc/rc.config" > /dev/null ; \ + if [ $$? -eq 1 ] ; then \ + echo -e "\n\n#\n# Set to yes to start pdnsd at boot time\n#\nSTART_PDNSD=yes" >> /etc/rc.config ; \ + fi \ + fi + + + diff --git a/jni/pdnsd/src/rc/SuSE/Makefile.in b/jni/pdnsd/src/rc/SuSE/Makefile.in new file mode 100644 index 00000000..df1660fd --- /dev/null +++ b/jni/pdnsd/src/rc/SuSE/Makefile.in @@ -0,0 +1,345 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +subdir = src/rc/SuSE +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/pdnsd.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = pdnsd +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +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) --gnu src/rc/SuSE/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/rc/SuSE/Makefile +.PRECIOUS: 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): +pdnsd: $(top_builddir)/config.status $(srcdir)/pdnsd.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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 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-exec-local + +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 + +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 distclean \ + distclean-generic 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-exec-local \ + 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 pdf pdf-am ps ps-am uninstall \ + uninstall-am + + +install-exec-local: + if [ "$(distribution)" = "SuSE" ] ; then \ + CURDIR=`pwd`; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d"; \ + $(INSTALL_SCRIPT) $(srcdir)/pdnsd "$(DESTDIR)/sbin/init.d/pdnsd"; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d/rc2.d"; \ + cd "$(DESTDIR)/sbin/init.d/rc2.d"; \ + ln -fs ../pdnsd K34pdnsd; ln -s ../pdnsd S11pdnsd; \ + cd $$CURDIR ; \ + $(mkinstalldirs) "$(DESTDIR)/sbin/init.d/rc3.d"; \ + cd "$(DESTDIR)/sbin/init.d/rc3.d"; \ + ln -fs ../pdnsd K34pdnsd; ln -s ../pdnsd S11pdnsd; \ + cd $$CURDIR ; \ + grep "START_PDNSD" "$(DESTDIR)/etc/rc.config" > /dev/null ; \ + if [ $$? -eq 1 ] ; then \ + echo -e "\n\n#\n# Set to yes to start pdnsd at boot time\n#\nSTART_PDNSD=yes" >> /etc/rc.config ; \ + fi \ + fi + +# 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/jni/pdnsd/src/rc/SuSE/pdnsd.in b/jni/pdnsd/src/rc/SuSE/pdnsd.in new file mode 100644 index 00000000..9711ecad --- /dev/null +++ b/jni/pdnsd/src/rc/SuSE/pdnsd.in @@ -0,0 +1,68 @@ +#! /bin/sh +# Copyright (c) 1995-1998 SuSE GmbH Nuernberg, Germany. +# +# Modified 2000 from SuSE Linux 6.3 /sbin/init.d/skeleton by Thomas Moestl +# +# /sbin/init.d/pdnsd +# +# and symbolic its link +# +# /sbin/rc?/pdnsd +# + +. /etc/rc.config + +# Determine the base and follow a runlevel link name. +base=${0##*/} +link=${base#*[SK][0-9][0-9]} + +# Force execution if not called by a runlevel directory. +test $link = $base && START_PDNSD=yes +test "$START_PDNSD" = yes || exit 0 + +# The echo return value for success (defined in /etc/rc.config). +return=$rc_done +case "$1" in + start) + echo -n "Starting pdnsd" + ## Start daemon with startproc(8). If this fails + ## the echo return value is set appropriate. + + startproc @prefix@/sbin/pdnsd -d || return=$rc_failed + + echo -e "$return" + ;; + stop) + echo -n "Shutting down pdnsd" + ## Stop daemon with killproc(8) and if this fails + ## set echo the echo return value. + + killproc -TERM @prefix@/sbin/pdnsd || return=$rc_failed + + echo -e "$return" + ;; + restart) + ## If first returns OK call the second, if first or + ## second command fails, set echo return value. + $0 stop && $0 start || return=$rc_failed + ;; + reload) + $0 stop && $0 start || return=$rc_failed + ;; + status) + echo -n "Checking for pdnsd: " + ## Check status with checkproc(8), if process is running + ## checkproc will return with exit status 0. + + checkproc @prefix@/sbin/pdnsd && echo OK || echo No process + ;; + *) + echo "Usage: $0 {start|stop|status|restart|reload}" + exit 1 + ;; +esac + +# Inform the caller not only verbosely and set an exit status. +test "$return" = "$rc_done" || exit 1 +exit 0 + diff --git a/jni/pdnsd/src/rr_types.c b/jni/pdnsd/src/rr_types.c new file mode 100644 index 00000000..275a90a4 --- /dev/null +++ b/jni/pdnsd/src/rr_types.c @@ -0,0 +1,172 @@ +/* rr_types.c - Tables with information for handling + all rr types known to pdnsd, plus + some helper functions useful for turning + binary RR data into text or vice versa. + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2003, 2004, 2007, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#define DEFINE_RR_TYPE_ARRAYS 1 +#include "helpers.h" +#include "dns.h" +#include "rr_types.h" + + +/* + * OK, this is inefficient. But it is used _really_ seldom (only in some cases while parsing the + * config file or by pdnsd-ctl), so it is much more effective to sort by id. + */ +int rr_tp_byname(char *name) +{ + int i; + + for (i=0;i> 4); + exponent = (prec & 0x0f); + + if(mantissa>=10 || exponent>=10) + return NULL; + if (exponent>= 2) + sprintf(retbuf, "%u", mantissa * poweroften[exponent-2]); + else + sprintf(retbuf, "0.%.2u", mantissa * poweroften[exponent]); + return (retbuf); +} + +/* takes an on-the-wire LOC RR and formats it in a human readable format. + This is an adapted version of the loc_ntoa function that + can be found in the BIND 9 source. + */ +const char *loc2str(const void *binary, char *ascii, size_t asclen) +{ + const unsigned char *cp = binary; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + const char *altsign; + int altmeters, altfrac; + + const uint32_t referencealt = 100000 * 100; + + int32_t latval, longval, altval; + uint32_t templ; + uint8_t sizeval, hpval, vpval, versionval; + + char sizestr[NPRECSIZE],hpstr[NPRECSIZE],vpstr[NPRECSIZE]; + + versionval = *cp++; + + if (versionval) { + /* unknown LOC RR version */ + return NULL; + } + + sizeval = *cp++; + + hpval = *cp++; + vpval = *cp++; + + GETINT32(templ, cp); + latval = (templ - ((unsigned)1<<31)); + + GETINT32(templ, cp); + longval = (templ - ((unsigned)1<<31)); + + GETINT32(templ, cp); + if (templ < referencealt) { /* below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = "-"; + } else { + altval = templ - referencealt; + altsign = ""; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval /= 1000; + latsec = latval % 60; + latval /= 60; + latmin = latval % 60; + latval /= 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval /= 1000; + longsec = longval % 60; + longval /= 60; + longmin = longval % 60; + longval /= 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100); + + if(!precsize_ntoa(sizeval,sizestr) || !precsize_ntoa(hpval,hpstr) || !precsize_ntoa(vpval,vpstr)) + return NULL; + { + int n=snprintf(ascii,asclen, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altsign, altmeters, altfrac, + sizestr, hpstr, vpstr); + if(n<0 || n>=asclen) + return NULL; + } + + return (ascii); +} + +#endif diff --git a/jni/pdnsd/src/rr_types.h b/jni/pdnsd/src/rr_types.h new file mode 100644 index 00000000..6025fae5 --- /dev/null +++ b/jni/pdnsd/src/rr_types.h @@ -0,0 +1,536 @@ +/* This file was generated by running 'make_rr_types_h.pl rr_types.in'. + Modifications to this file may be lost the next time it is automatically + regenerated. +*/ + +/* rr_types.h - A header file with names & descriptions of + all rr types known to pdnsd + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2007, 2010, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#ifndef _RR_TYPES_H_ +#define _RR_TYPES_H_ + +#include + +#define T_MIN 1 +#define T_A 1 +#define T_NS 2 +#define T_MD 3 +#define T_MF 4 +#define T_CNAME 5 +#define T_SOA 6 +#define T_MB 7 +#define T_MG 8 +#define T_MR 9 +#define T_NULL 10 +#define T_WKS 11 +#define T_PTR 12 +#define T_HINFO 13 +#define T_MINFO 14 +#define T_MX 15 +#define T_TXT 16 +#define T_RP 17 +#define T_AFSDB 18 +#define T_X25 19 +#define T_ISDN 20 +#define T_RT 21 +#define T_NSAP 22 +#define T_NSAP_PTR 23 +#define T_SIG 24 +#define T_KEY 25 +#define T_PX 26 +#define T_GPOS 27 +#define T_AAAA 28 +#define T_LOC 29 +#define T_NXT 30 +#define T_EID 31 +#define T_NIMLOC 32 +#define T_SRV 33 +#define T_ATMA 34 +#define T_NAPTR 35 +#define T_KX 36 +#define T_CERT 37 +#define T_A6 38 +#define T_DNAME 39 +#define T_SINK 40 +#define T_OPT 41 +#define T_APL 42 +#define T_DS 43 +#define T_SSHFP 44 +#define T_IPSECKEY 45 +#define T_RRSIG 46 +#define T_NSEC 47 +#define T_DNSKEY 48 +#define T_DHCID 49 +#define T_NSEC3 50 +#define T_NSEC3PARAM 51 +#define T_HIP 55 +#define T_NINFO 56 +#define T_RKEY 57 +#define T_TALINK 58 +#define T_SPF 99 +#define T_UINFO 100 +#define T_UID 101 +#define T_GID 102 +#define T_UNSPEC 103 +#define T_MAX 51 + +/* T_MAX - T_MIN + 1 */ +#define T_NUM 51 + +/* Number of most frequently used rr types. */ +#define NRRMU 8 + +/* Number of remaining rr types. */ +#define NRREXT 39 + +/* NRRMU + NRREXT */ +#define NRRTOT 47 + +/* Lookup table for converting rr type values to internally used indices. */ +extern const unsigned short int rrlkuptab[T_NUM]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const unsigned short int rrlkuptab[T_NUM] = { + 0 /* A */, + 1 /* NS */, + 8 /* MD */, + 9 /* MF */, + 2 /* CNAME */, + 3 /* SOA */, + 10 /* MB */, + 11 /* MG */, + 12 /* MR */, + 13 /* NULL */, + 14 /* WKS */, + 4 /* PTR */, + 15 /* HINFO */, + 16 /* MINFO */, + 5 /* MX */, + 6 /* TXT */, + 17 /* RP */, + 18 /* AFSDB */, + 19 /* X25 */, + 20 /* ISDN */, + 21 /* RT */, + 22 /* NSAP */, + 23 /* NSAP_PTR */, + 24 /* SIG */, + 25 /* KEY */, + 26 /* PX */, + 27 /* GPOS */, + 7 /* AAAA */, + 28 /* LOC */, + 29 /* NXT */, + 30 /* EID */, + 31 /* NIMLOC */, + 32 /* SRV */, + 33 /* ATMA */, + 34 /* NAPTR */, + 35 /* KX */, + 36 /* CERT */, + 47 /* A6 */, + 48 /* DNAME */, + 49 /* SINK */, + 50 /* OPT */, + 37 /* APL */, + 38 /* DS */, + 39 /* SSHFP */, + 40 /* IPSECKEY */, + 41 /* RRSIG */, + 42 /* NSEC */, + 43 /* DNSKEY */, + 44 /* DHCID */, + 45 /* NSEC3 */, + 46 /* NSEC3PARAM */ +}; +#endif + +/* List of most frequently used RR types in ascending order. */ +extern const unsigned short int rrmuiterlist[NRRMU]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const unsigned short int rrmuiterlist[NRRMU] = { + T_A, + T_NS, + T_CNAME, + T_SOA, + T_PTR, + T_MX, + T_TXT, + T_AAAA +}; +#endif + +/* List of the cache-able RR types in ascending order. */ +extern const unsigned short int rrcachiterlist[NRRTOT]; +#if DEFINE_RR_TYPE_ARRAYS +const unsigned short int rrcachiterlist[NRRTOT] = { + T_A, + T_NS, + T_MD, + T_MF, + T_CNAME, + T_SOA, + T_MB, + T_MG, + T_MR, + T_NULL, + T_WKS, + T_PTR, + T_HINFO, + T_MINFO, + T_MX, + T_TXT, + T_RP, + T_AFSDB, + T_X25, + T_ISDN, + T_RT, + T_NSAP, + T_NSAP_PTR, + T_SIG, + T_KEY, + T_PX, + T_GPOS, + T_AAAA, + T_LOC, + T_NXT, + T_EID, + T_NIMLOC, + T_SRV, + T_ATMA, + T_NAPTR, + T_KX, + T_CERT, + T_APL, + T_DS, + T_SSHFP, + T_IPSECKEY, + T_RRSIG, + T_NSEC, + T_DNSKEY, + T_DHCID, + T_NSEC3, + T_NSEC3PARAM +}; +#endif + +/* Optimized getrrset macros for fixed rr types. */ +#define getrrset_A(cent) GET_RRSMU(cent,0) +#define getrrset_NS(cent) GET_RRSMU(cent,1) +#define getrrset_MD(cent) GET_RRSEXT(cent,0) +#define getrrset_MF(cent) GET_RRSEXT(cent,1) +#define getrrset_CNAME(cent) GET_RRSMU(cent,2) +#define getrrset_SOA(cent) GET_RRSMU(cent,3) +#define getrrset_MB(cent) GET_RRSEXT(cent,2) +#define getrrset_MG(cent) GET_RRSEXT(cent,3) +#define getrrset_MR(cent) GET_RRSEXT(cent,4) +#define getrrset_NULL(cent) GET_RRSEXT(cent,5) +#define getrrset_WKS(cent) GET_RRSEXT(cent,6) +#define getrrset_PTR(cent) GET_RRSMU(cent,4) +#define getrrset_HINFO(cent) GET_RRSEXT(cent,7) +#define getrrset_MINFO(cent) GET_RRSEXT(cent,8) +#define getrrset_MX(cent) GET_RRSMU(cent,5) +#define getrrset_TXT(cent) GET_RRSMU(cent,6) +#define getrrset_RP(cent) GET_RRSEXT(cent,9) +#define getrrset_AFSDB(cent) GET_RRSEXT(cent,10) +#define getrrset_X25(cent) GET_RRSEXT(cent,11) +#define getrrset_ISDN(cent) GET_RRSEXT(cent,12) +#define getrrset_RT(cent) GET_RRSEXT(cent,13) +#define getrrset_NSAP(cent) GET_RRSEXT(cent,14) +#define getrrset_NSAP_PTR(cent) GET_RRSEXT(cent,15) +#define getrrset_SIG(cent) GET_RRSEXT(cent,16) +#define getrrset_KEY(cent) GET_RRSEXT(cent,17) +#define getrrset_PX(cent) GET_RRSEXT(cent,18) +#define getrrset_GPOS(cent) GET_RRSEXT(cent,19) +#define getrrset_AAAA(cent) GET_RRSMU(cent,7) +#define getrrset_LOC(cent) GET_RRSEXT(cent,20) +#define getrrset_NXT(cent) GET_RRSEXT(cent,21) +#define getrrset_EID(cent) GET_RRSEXT(cent,22) +#define getrrset_NIMLOC(cent) GET_RRSEXT(cent,23) +#define getrrset_SRV(cent) GET_RRSEXT(cent,24) +#define getrrset_ATMA(cent) GET_RRSEXT(cent,25) +#define getrrset_NAPTR(cent) GET_RRSEXT(cent,26) +#define getrrset_KX(cent) GET_RRSEXT(cent,27) +#define getrrset_CERT(cent) GET_RRSEXT(cent,28) +#define getrrset_APL(cent) GET_RRSEXT(cent,29) +#define getrrset_DS(cent) GET_RRSEXT(cent,30) +#define getrrset_SSHFP(cent) GET_RRSEXT(cent,31) +#define getrrset_IPSECKEY(cent) GET_RRSEXT(cent,32) +#define getrrset_RRSIG(cent) GET_RRSEXT(cent,33) +#define getrrset_NSEC(cent) GET_RRSEXT(cent,34) +#define getrrset_DNSKEY(cent) GET_RRSEXT(cent,35) +#define getrrset_DHCID(cent) GET_RRSEXT(cent,36) +#define getrrset_NSEC3(cent) GET_RRSEXT(cent,37) +#define getrrset_NSEC3PARAM(cent) GET_RRSEXT(cent,38) + +/* have_rr macros for fixed rr types. */ +#define have_rr_A(cent) HAVE_RRMU(cent,0) +#define have_rr_NS(cent) HAVE_RRMU(cent,1) +#define have_rr_MD(cent) HAVE_RREXT(cent,0) +#define have_rr_MF(cent) HAVE_RREXT(cent,1) +#define have_rr_CNAME(cent) HAVE_RRMU(cent,2) +#define have_rr_SOA(cent) HAVE_RRMU(cent,3) +#define have_rr_MB(cent) HAVE_RREXT(cent,2) +#define have_rr_MG(cent) HAVE_RREXT(cent,3) +#define have_rr_MR(cent) HAVE_RREXT(cent,4) +#define have_rr_NULL(cent) HAVE_RREXT(cent,5) +#define have_rr_WKS(cent) HAVE_RREXT(cent,6) +#define have_rr_PTR(cent) HAVE_RRMU(cent,4) +#define have_rr_HINFO(cent) HAVE_RREXT(cent,7) +#define have_rr_MINFO(cent) HAVE_RREXT(cent,8) +#define have_rr_MX(cent) HAVE_RRMU(cent,5) +#define have_rr_TXT(cent) HAVE_RRMU(cent,6) +#define have_rr_RP(cent) HAVE_RREXT(cent,9) +#define have_rr_AFSDB(cent) HAVE_RREXT(cent,10) +#define have_rr_X25(cent) HAVE_RREXT(cent,11) +#define have_rr_ISDN(cent) HAVE_RREXT(cent,12) +#define have_rr_RT(cent) HAVE_RREXT(cent,13) +#define have_rr_NSAP(cent) HAVE_RREXT(cent,14) +#define have_rr_NSAP_PTR(cent) HAVE_RREXT(cent,15) +#define have_rr_SIG(cent) HAVE_RREXT(cent,16) +#define have_rr_KEY(cent) HAVE_RREXT(cent,17) +#define have_rr_PX(cent) HAVE_RREXT(cent,18) +#define have_rr_GPOS(cent) HAVE_RREXT(cent,19) +#define have_rr_AAAA(cent) HAVE_RRMU(cent,7) +#define have_rr_LOC(cent) HAVE_RREXT(cent,20) +#define have_rr_NXT(cent) HAVE_RREXT(cent,21) +#define have_rr_EID(cent) HAVE_RREXT(cent,22) +#define have_rr_NIMLOC(cent) HAVE_RREXT(cent,23) +#define have_rr_SRV(cent) HAVE_RREXT(cent,24) +#define have_rr_ATMA(cent) HAVE_RREXT(cent,25) +#define have_rr_NAPTR(cent) HAVE_RREXT(cent,26) +#define have_rr_KX(cent) HAVE_RREXT(cent,27) +#define have_rr_CERT(cent) HAVE_RREXT(cent,28) +#define have_rr_A6(cent) 0 +#define have_rr_DNAME(cent) 0 +#define have_rr_SINK(cent) 0 +#define have_rr_OPT(cent) 0 +#define have_rr_APL(cent) HAVE_RREXT(cent,29) +#define have_rr_DS(cent) HAVE_RREXT(cent,30) +#define have_rr_SSHFP(cent) HAVE_RREXT(cent,31) +#define have_rr_IPSECKEY(cent) HAVE_RREXT(cent,32) +#define have_rr_RRSIG(cent) HAVE_RREXT(cent,33) +#define have_rr_NSEC(cent) HAVE_RREXT(cent,34) +#define have_rr_DNSKEY(cent) HAVE_RREXT(cent,35) +#define have_rr_DHCID(cent) HAVE_RREXT(cent,36) +#define have_rr_NSEC3(cent) HAVE_RREXT(cent,37) +#define have_rr_NSEC3PARAM(cent) HAVE_RREXT(cent,38) + +/* These macros specify which RR types are cached by pdnsd. */ +#define IS_CACHED_A 1 +#define IS_CACHED_NS 1 +#define IS_CACHED_MD 1 +#define IS_CACHED_MF 1 +#define IS_CACHED_CNAME 1 +#define IS_CACHED_SOA 1 +#define IS_CACHED_MB 1 +#define IS_CACHED_MG 1 +#define IS_CACHED_MR 1 +#define IS_CACHED_NULL 1 +#define IS_CACHED_WKS 1 +#define IS_CACHED_PTR 1 +#define IS_CACHED_HINFO 1 +#define IS_CACHED_MINFO 1 +#define IS_CACHED_MX 1 +#define IS_CACHED_TXT 1 +#define IS_CACHED_RP 1 +#define IS_CACHED_AFSDB 1 +#define IS_CACHED_X25 1 +#define IS_CACHED_ISDN 1 +#define IS_CACHED_RT 1 +#define IS_CACHED_NSAP 1 +#define IS_CACHED_NSAP_PTR 1 +#define IS_CACHED_SIG 1 +#define IS_CACHED_KEY 1 +#define IS_CACHED_PX 1 +#define IS_CACHED_GPOS 1 +#define IS_CACHED_AAAA 1 +#define IS_CACHED_LOC 1 +#define IS_CACHED_NXT 1 +#define IS_CACHED_EID 1 +#define IS_CACHED_NIMLOC 1 +#define IS_CACHED_SRV 1 +#define IS_CACHED_ATMA 1 +#define IS_CACHED_NAPTR 1 +#define IS_CACHED_KX 1 +#define IS_CACHED_CERT 1 +#define IS_CACHED_APL 1 +#define IS_CACHED_DS 1 +#define IS_CACHED_SSHFP 1 +#define IS_CACHED_IPSECKEY 1 +#define IS_CACHED_RRSIG 1 +#define IS_CACHED_NSEC 1 +#define IS_CACHED_DNSKEY 1 +#define IS_CACHED_DHCID 1 +#define IS_CACHED_NSEC3 1 +#define IS_CACHED_NSEC3PARAM 1 + +/* Array indices for most frequently used rr types. */ +#define RRMUINDEX_A 0 +#define RRMUINDEX_NS 1 +#define RRMUINDEX_CNAME 2 +#define RRMUINDEX_SOA 3 +#define RRMUINDEX_PTR 4 +#define RRMUINDEX_MX 5 +#define RRMUINDEX_TXT 6 +#define RRMUINDEX_AAAA 7 + +/* Table of rr names. */ +extern const char *const rrnames[T_NUM]; +#if DEFINE_RR_TYPE_ARRAYS +const char *const rrnames[T_NUM] = { + "A", + "NS", + "MD", + "MF", + "CNAME", + "SOA", + "MB", + "MG", + "MR", + "NULL", + "WKS", + "PTR", + "HINFO", + "MINFO", + "MX", + "TXT", + "RP", + "AFSDB", + "X25", + "ISDN", + "RT", + "NSAP", + "NSAP_PTR", + "SIG", + "KEY", + "PX", + "GPOS", + "AAAA", + "LOC", + "NXT", + "EID", + "NIMLOC", + "SRV", + "ATMA", + "NAPTR", + "KX", + "CERT", + "A6", + "DNAME", + "SINK", + "OPT", + "APL", + "DS", + "SSHFP", + "IPSECKEY", + "RRSIG", + "NSEC", + "DNSKEY", + "DHCID", + "NSEC3", + "NSEC3PARAM" +}; +#endif + +/* Structure for rr information */ +struct rr_infos { + unsigned short class; /* class (values see below) */ + unsigned short excludes; /* relations to other classes. + Mutual exclusion is marked by or'ing the + respective RRCL value in this field. + Exclusions should be symmetric. */ +}; + +/* Class values */ +#define RRCL_ALIAS 1 /* for CNAMES, conflicts with RRCL_RECORD */ +#define RRCL_RECORD 2 /* normal direct record */ +#define RRCL_IDEM 4 /* types that conflict with no others (MX, CNAME, ...) */ +#define RRCL_PTR 8 /* PTR */ + +/* Standard excludes for the classes */ +#define RRX_ALIAS (RRCL_RECORD|RRCL_PTR) +#define RRX_RECORD (RRCL_ALIAS|RRCL_PTR) +#define RRX_IDEM 0 +#define RRX_PTR (RRCL_ALIAS|RRCL_RECORD) + +/* There could be a separate table detailing the relationship of types, but this + * is slightly more flexible, as it allows a finer granularity of exclusion. Also, + * Membership in multiple classes could be added. + * Index by internally used RR-set indices, not RR type values! + */ +extern const struct rr_infos rr_info[NRRTOT]; +#if DEFINE_RR_TYPE_ARRAYS && !defined(CLIENT_ONLY) +const struct rr_infos rr_info[NRRTOT] = { + {RRCL_RECORD, RRX_RECORD} /* A */, + {RRCL_IDEM, RRX_IDEM} /* NS */, + {RRCL_ALIAS, RRX_ALIAS} /* CNAME */, + {RRCL_IDEM, RRX_IDEM} /* SOA */, + {RRCL_PTR, RRX_PTR} /* PTR */, + {RRCL_IDEM, RRX_IDEM} /* MX */, + {RRCL_IDEM, RRX_IDEM} /* TXT */, + {RRCL_RECORD, RRX_RECORD} /* AAAA */, + {RRCL_IDEM, RRX_IDEM} /* MD */, + {RRCL_IDEM, RRX_IDEM} /* MF */, + {RRCL_IDEM, RRX_IDEM} /* MB */, + {RRCL_IDEM, RRX_IDEM} /* MG */, + {RRCL_IDEM, RRX_IDEM} /* MR */, + {RRCL_IDEM, RRX_IDEM} /* NULL */, + {RRCL_RECORD, RRX_RECORD} /* WKS */, + {RRCL_RECORD, RRX_RECORD} /* HINFO */, + {RRCL_IDEM, RRX_IDEM} /* MINFO */, + {RRCL_RECORD, RRX_RECORD} /* RP */, + {RRCL_RECORD, RRX_RECORD} /* AFSDB */, + {RRCL_RECORD, RRX_RECORD} /* X25 */, + {RRCL_RECORD, RRX_RECORD} /* ISDN */, + {RRCL_RECORD, RRX_RECORD} /* RT */, + {RRCL_RECORD, RRX_RECORD} /* NSAP */, + {RRCL_PTR, RRX_PTR} /* NSAP_PTR */, + {RRCL_IDEM, RRX_IDEM} /* SIG */, + {RRCL_IDEM, RRX_IDEM} /* KEY */, + {RRCL_IDEM, RRX_IDEM} /* PX */, + {RRCL_RECORD, RRX_RECORD} /* GPOS */, + {RRCL_RECORD, RRX_RECORD} /* LOC */, + {RRCL_IDEM, RRX_IDEM} /* NXT */, + {RRCL_RECORD, RRX_RECORD} /* EID */, + {RRCL_RECORD, RRX_RECORD} /* NIMLOC */, + {RRCL_RECORD, RRX_RECORD} /* SRV */, + {RRCL_RECORD, RRX_RECORD} /* ATMA */, + {RRCL_RECORD, RRX_RECORD} /* NAPTR */, + {RRCL_RECORD, RRX_RECORD} /* KX */, + {RRCL_RECORD, RRX_RECORD} /* CERT */, + {RRCL_IDEM, RRX_IDEM} /* APL */, + {RRCL_IDEM, RRX_IDEM} /* DS */, + {RRCL_IDEM, RRX_IDEM} /* SSHFP */, + {RRCL_IDEM, RRX_IDEM} /* IPSECKEY */, + {RRCL_IDEM, RRX_IDEM} /* RRSIG */, + {RRCL_IDEM, RRX_IDEM} /* NSEC */, + {RRCL_IDEM, RRX_IDEM} /* DNSKEY */, + {RRCL_IDEM, RRX_IDEM} /* DHCID */, + {RRCL_IDEM, RRX_IDEM} /* NSEC3 */, + {RRCL_IDEM, RRX_IDEM} /* NSEC3PARAM */ +}; +#endif + +int rr_tp_byname(char *name); +const char *loc2str(const void *binary, char *ascii, size_t asclen); + +#endif diff --git a/jni/pdnsd/src/rr_types.in b/jni/pdnsd/src/rr_types.in new file mode 100644 index 00000000..5ebd2f37 --- /dev/null +++ b/jni/pdnsd/src/rr_types.in @@ -0,0 +1,99 @@ +# This file is part of the pdnsd package. + +# This file contains information about the RR types implemented in pdnsd +# and is used for generating rr_types.h. +# It was derived from the following source: http://www.bind9.net/dns-parameters +# +# After making modifications to this file the file rr_types.h should be regenerated! +# +# Info about the format of this file: +# Blank lines and lines starting with '#' are ignored, all other lines +# are assumed to define an RR type. Lines starting with '+' define most +# frequently used types. An RR type preceded by a '-' will not be cached +# by pdnsd. The next two fields are interpreted as the name and the value +# of the RR type, resp. A subsequent word in parenthesis will be interpreted a +# class name (used for conflict resolution). Remaining fields are ignored. +# +# Adding or removing an initial '+' can be done safely without requiring +# changes to the source code (other than regenerating rr_types.h). +# +# If you are sure that you will never use certain RR types you can disable +# caching for them and make pdnsd slightly more efficient by placing a +# '-' sign in front of the lines that define those types. +# For a list of obsolete RR types see e.g. +# http://en.wikipedia.org/wiki/List_of_DNS_record_types . +# Note that some RR types are essential for pdnsd; these are currently: +# A, NS, CNAME, SOA, PTR, MX and (if you want IPv6 support) AAAA. +# Disabling caching for these types will cause pdnsd to fail to compile +# or cause a fatal run-time error. +# +# Removing a '-' sign to enable caching can be risky if the support in +# the pdnsd code is missing or inadequate, so only do this if you really know +# what you are doing. SPF records are supported, however, so it should be safe +# to enable caching for them. + +# RR TYPE Value (class) and meaning Reference +# ----------- --------------------------------------------- --------- ++ A 1 (RECORD) a host address [RFC 1035] ++ NS 2 an authoritative name server [RFC 1035] + MD 3 a mail destination (Obsolete - use MX) [RFC 1035] + MF 4 a mail forwarder (Obsolete - use MX) [RFC 1035] ++ CNAME 5 (ALIAS) the canonical name for an alias [RFC 1035] ++ SOA 6 marks the start of a zone of authority [RFC 1035] + MB 7 a mailbox domain name (EXPERIMENTAL) [RFC 1035] + MG 8 a mail group member (EXPERIMENTAL) [RFC 1035] + MR 9 a mail rename domain name (EXPERIMENTAL) [RFC 1035] + NULL 10 a null RR (EXPERIMENTAL) [RFC 1035] + WKS 11 (RECORD) a well known service description [RFC 1035] ++ PTR 12 (PTR) a domain name pointer [RFC 1035] + HINFO 13 (RECORD) host information [RFC 1035] + MINFO 14 mailbox or mail list information [RFC 1035] ++ MX 15 mail exchange [RFC 1035] ++ TXT 16 text strings [RFC 1035] + RP 17 (RECORD) for Responsible Person [RFC 1183] + AFSDB 18 (RECORD) for AFS Data Base location [RFC 1183][RFC 5864] + X25 19 (RECORD) for X.25 PSDN address [RFC 1183] + ISDN 20 (RECORD) for ISDN address [RFC 1183] + RT 21 (RECORD) for Route Through [RFC 1183] + NSAP 22 (RECORD) for NSAP address, NSAP style A record [RFC 1706] + NSAP-PTR 23 (PTR) for domain name pointer, NSAP style [RFC 1348] + SIG 24 for security signature [RFC 4034][RFC 3755][RFC 2535] + KEY 25 for security key [RFC 4034][RFC 3755][RFC 2535] + PX 26 X.400 mail mapping information [RFC 2163] + GPOS 27 (RECORD) Geographical Position [RFC 1712] ++ AAAA 28 (RECORD) IP6 Address [RFC 3596] + LOC 29 (RECORD) Location Information [RFC 1876] + NXT 30 Next Domain - OBSOLETE [RFC 3755][RFC 2535] + EID 31 (RECORD) Endpoint Identifier [Patton] + NIMLOC 32 (RECORD) Nimrod Locator [Patton] + SRV 33 (RECORD) Server Selection [RFC 2782] + ATMA 34 (RECORD) ATM Address [ATMDOC] + NAPTR 35 (RECORD) Naming Authority Pointer [RFC 2915][RFC 2168][RFC 3403] + KX 36 (RECORD) Key Exchanger [RFC 2230] + CERT 37 (RECORD) CERT [RFC 4398] +- A6 38 A6 (Experimental) [RFC 3226][RFC 2874] +- DNAME 39 (ALIAS) DNAME [RFC 2672] +- SINK 40 SINK [Eastlake] +- OPT 41 OPT [RFC 2671] + APL 42 APL [RFC 3123] + DS 43 Delegation Signer [RFC 4034][RFC 3658] + SSHFP 44 SSH Key Fingerprint [RFC 4255] + IPSECKEY 45 IPSECKEY [RFC 4025] + RRSIG 46 RRSIG [RFC 4034][RFC 3755] + NSEC 47 NSEC [RFC 4034][RFC 3755] + DNSKEY 48 DNSKEY [RFC 4034][RFC 3755] + DHCID 49 DHCID [RFC 4701] + NSEC3 50 NSEC3 [RFC 5155] + NSEC3PARAM 51 NSEC3PARAM [RFC 5155] +# Unassigned 52-54 +- HIP 55 Host Identity Protocol [RFC 5205] +- NINFO 56 NINFO [Reid] +- RKEY 57 RKEY [Reid] +- TALINK 58 Trust Anchor LINK [Wijngaards] +# Unassigned 59-98 +- SPF 99 Sender Policy Framework [RFC 4408] +- UINFO 100 [IANA-Reserved] +- UID 101 [IANA-Reserved] +- GID 102 [IANA-Reserved] +- UNSPEC 103 [IANA-Reserved] +# Unassigned 104-248 diff --git a/jni/pdnsd/src/servers.c b/jni/pdnsd/src/servers.c new file mode 100644 index 00000000..8549865a --- /dev/null +++ b/jni/pdnsd/src/servers.c @@ -0,0 +1,856 @@ +/* servers.c - manage a set of dns servers + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2005, 2007, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thread.h" +#include "error.h" +#include "servers.h" +#include "conff.h" +#include "consts.h" +#include "icmp.h" +#include "netdev.h" +#include "helpers.h" +#include "dns_query.h" + + +/* + * We may be a little over-strict with locks here. Never mind... + * Also, there may be some code-redundancy regarding uptests. It saves some locks, though. + */ + +static pthread_mutex_t servers_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t server_data_cond = PTHREAD_COND_INITIALIZER; +static pthread_cond_t server_test_cond = PTHREAD_COND_INITIALIZER; +static int server_data_users = 0, server_status_ping = 0; +/* Used to notify the server status thread that it should discontinue uptests. */ +volatile int signal_interrupt=0; +#define statusintsig SIGHUP + +static short retest_flag=0; + +static char schm[32]; + +static void sigint_handler(int signum); + +/* + * Execute an individual uptest. Call with locks applied + */ +static int uptest (servparm_t *serv, int j) +{ + int ret=0, count_running_ping=0; + pdnsd_a *s_addr= PDNSD_A2_TO_A(&DA_INDEX(serv->atup_a,j).a); + + DEBUG_PDNSDA_MSG("performing uptest (type=%s) for %s\n",const_name(serv->uptest),PDNSDA2STR(s_addr)); + + /* Unlock the mutex because some of the tests may take a while. */ + ++server_data_users; + if((serv->uptest==C_PING || serv->uptest==C_QUERY) && pthread_equal(pthread_self(),servstat_thrid)) { + /* Inform other threads that a ping is in progress. */ + count_running_ping=1; + ++server_status_ping; + } + pthread_mutex_unlock(&servers_lock); + + switch (serv->uptest) { + case C_NONE: + /* Don't change */ + ret=DA_INDEX(serv->atup_a,j).is_up; + break; + case C_PING: + ret=ping(is_inaddr_any(&serv->ping_a) ? s_addr : &serv->ping_a, serv->ping_timeout,PINGREPEAT)!=-1; + break; + case C_IF: + case C_DEV: + case C_DIALD: + ret=if_up(serv->interface); +#if (TARGET==TARGET_LINUX) + if (ret!=0) { + if(serv->uptest==C_DEV) + ret=dev_up(serv->interface,serv->device); + else if (serv->uptest==C_DIALD) + ret=dev_up("diald",serv->device); + } +#endif + break; + case C_EXEC: { + pid_t pid; + + if ((pid=fork())==-1) { + DEBUG_MSG("Could not fork to perform exec uptest: %s\n",strerror(errno)); + break; + } else if (pid==0) { /* child */ + /* + * If we ran as setuid or setgid, do not inherit this to the + * command. This is just a last guard. Running pdnsd as setuid() + * or setgid() is a no-no. + */ + if (setgid(getgid()) == -1 || setuid(getuid()) == -1) { + log_error("Could not reset uid or gid: %s",strerror(errno)); + _exit(1); + } + /* Try to setuid() to a different user as specified. Good when you + don't want the test command to run as root */ + if (!run_as(serv->uptest_usr)) { + _exit(1); + } + { + struct rlimit rl; int i; + /* + * Mark all open fd's FD_CLOEXEC for paranoia reasons. + */ + if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { + log_error("getrlimit() failed: %s",strerror(errno)); + _exit(1); + } + for (i = 0; i < rl.rlim_max; i++) { + if (fcntl(i, F_SETFD, FD_CLOEXEC) == -1 && errno != EBADF) { + log_error("fcntl(F_SETFD) failed: %s",strerror(errno)); + _exit(1); + } + } + } + execl("/bin/sh", "uptest_sh","-c",serv->uptest_cmd,(char *)NULL); + _exit(1); /* failed execl */ + } else { /* parent */ + int status; + pid_t wpid = waitpid(pid,&status,0); + if (wpid==pid) { + if(WIFEXITED(status)) { + int exitstatus=WEXITSTATUS(status); + DEBUG_MSG("uptest command \"%s\" exited with status %d\n", + serv->uptest_cmd, exitstatus); + ret=(exitstatus==0); + } +#if DEBUG>0 + else if(WIFSIGNALED(status)) { + DEBUG_MSG("uptest command \"%s\" was terminated by signal %d\n", + serv->uptest_cmd, WTERMSIG(status)); + } + else { + DEBUG_MSG("status of uptest command \"%s\" is of unkown type (0x%x)\n", + serv->uptest_cmd, status); + } +#endif + } +#if DEBUG>0 + else if (wpid==-1) { + DEBUG_MSG("Error while waiting for uptest command \"%s\" to terminate: " + "waitpid for pid %d failed: %s\n", + serv->uptest_cmd, pid, strerror(errno)); + } + else { + DEBUG_MSG("Error while waiting for uptest command \"%s\" to terminate: " + "waitpid returned %d, expected pid %d\n", + serv->uptest_cmd, wpid, pid); + } +#endif + } + } + break; + case C_QUERY: + ret=query_uptest(s_addr, serv->port, serv->query_test_name, + serv->timeout>=global.timeout?serv->timeout:global.timeout, + PINGREPEAT); + } /* end of switch */ + + pthread_mutex_lock(&servers_lock); + if(count_running_ping) + --server_status_ping; + PDNSD_ASSERT(server_data_users>0, "server_data_users non-positive before attempt to decrement it"); + if (--server_data_users==0) pthread_cond_broadcast(&server_data_cond); + + DEBUG_PDNSDA_MSG("result of uptest for %s: %s\n", + PDNSDA2STR(s_addr), + ret?"OK":"failed"); + return ret; +} + +static int scheme_ok(servparm_t *serv) +{ + if (serv->scheme[0]) { + if (!schm[0]) { + ssize_t nschm; + int sc = open(global.scheme_file, O_RDONLY); + char *s; + if (sc<0) + return 0; + nschm = read(sc, schm, sizeof(schm)-1); + close(sc); + if (nschm < 0) + return 0; + schm[nschm] = '\0'; + s = strchr(schm, '\n'); + if (s) + *s='\0'; + } + if (fnmatch(serv->scheme, schm, 0)) + return 0; + } + return 1; +} + +/* Internal server test. Call with locks applied. + May test a single server ip or several collectively. + */ +static void retest(int i, int j) +{ + time_t s_ts; + servparm_t *srv=&DA_INDEX(servers,i); + int nsrvs=DA_NEL(srv->atup_a); + + if(!nsrvs) return; + if(j>=0) { + if(jatup_a,j); + at->is_up=0; + at->i_ts=s_ts; + } + } + else if(srv->uptest==C_NONE) { + s_ts=time(NULL); + + for(;jatup_a,j).i_ts=s_ts; + } + } + else if(srv->uptest==C_QUERY || (srv->uptest==C_PING && is_inaddr_any(&srv->ping_a))) { /* test each ip address separately */ + for(;jatup_a,j); + s_ts=time(NULL); + at->is_up=uptest(srv,j); + if(signal_interrupt) + break; + at->i_ts=s_ts; + } + } + else { /* test ip addresses collectively */ + int res; + + s_ts=time(NULL); + res=uptest(srv,j); + for(;jatup_a,j); + at->is_up=res; + if(signal_interrupt && srv->uptest==C_PING) + continue; + at->i_ts=s_ts; + } + } +} + + +/* This is called by the server status thread to discover the addresses of root servers. + Call with server_lock applied. +*/ +static addr2_array resolv_rootserver_addrs(atup_array a, int port, char edns_query, time_t timeout) +{ + addr2_array retval=NULL; + + /* Unlock the mutex because this may take a while. */ + ++server_data_users; + pthread_mutex_unlock(&servers_lock); + + retval= dns_rootserver_resolv(a,port,edns_query,timeout); + + pthread_mutex_lock(&servers_lock); + PDNSD_ASSERT(server_data_users>0, "server_data_users non-positive before attempt to decrement it"); + if (--server_data_users==0) pthread_cond_broadcast(&server_data_cond); + + return retval; +} + +/* + * Refresh the server status by pinging or testing the interface in the given interval. + * Note that you may get inaccuracies in the dimension of the ping timeout or the runtime + * of your uptest command if you have uptest=ping or uptest=exec for at least one server. + * This happens when all the uptests for the first n servers take more time than the inteval + * of n+1 (or 0 when n+1>servnum). I do not think that these delays are critical, so I did + * not to anything about that (because that may also be costly). + */ +void *servstat_thread(void *p) +{ + struct sigaction action; + int keep_testing; + + /* (void)p; */ /* To inhibit "unused variable" warning */ + + THREAD_SIGINIT; + + pthread_mutex_lock(&servers_lock); + /* servstat_thrid=pthread_self(); */ + + signal_interrupt=0; + action.sa_handler = sigint_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + if(sigaction(statusintsig, &action, NULL) == 0) { + sigset_t smask; + sigemptyset(&smask); + sigaddset(&smask, statusintsig); + pthread_sigmask(SIG_UNBLOCK,&smask,NULL); + } + else { + log_warn("Cannot install signal handler for server status thread: %s\n",strerror(errno)); + } + + for(;;) { + do { + int i,n; + keep_testing=0; + retest_flag=0; + schm[0] = '\0'; + n=DA_NEL(servers); + for (i=0;irootserver==2) { + /* First get addresses of root servers. */ + addr2_array adrs; + int l, one_up=0; + + if(!scheme_ok(sp)) { + time_t now=time(NULL); + m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j).i_ts=now; + } else if(sp->uptest==C_PING || sp->uptest==C_QUERY) { + /* Skip ping or query tests until after discovery. */ + if(sp->interval>0) + one_up= DA_NEL(sp->atup_a); + else { + time_t now=time(NULL); + m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j); + if(at->is_up || at->i_ts==0) + one_up=1; + at->i_ts=now; + } + } + } + else { + retest(i,-1); + + m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j).is_up) { + one_up=1; + break; + } + } + } + + if(!one_up) { + if (needs_intermittent_testing(sp)) keep_testing=1; + continue; + } + + DEBUG_MSG("Attempting to discover root servers for server section #%d.\n",i); + adrs=resolv_rootserver_addrs(sp->atup_a,sp->port,sp->edns_query,sp->timeout); + l= DA_NEL(adrs); + if(l>0) { + struct timeval now; + struct timespec timeout; + atup_array ata; + DEBUG_MSG("Filling server section #%d with %d root server addresses.\n",i,l); + gettimeofday(&now,NULL); + timeout.tv_sec = now.tv_sec + 60; /* time out after 60 seconds */ + timeout.tv_nsec = now.tv_usec * 1000; + while (server_data_users>0) { + if(pthread_cond_timedwait(&server_data_cond, &servers_lock, &timeout) == ETIMEDOUT) { + DEBUG_MSG("Timed out while waiting for exclusive access to server data" + " to set root server addresses of server section #%d\n",i); + da_free(adrs); + keep_testing=1; + continue; + } + } + ata = DA_CREATE(atup_array, l); + if(!ata) { + log_warn("Out of memory in servstat_thread() while discovering root servers."); + da_free(adrs); + keep_testing=1; + continue; + } + for(j=0; ja = DA_INDEX(adrs,j); + at->is_up=sp->preset; + at->i_ts= sp->interval<0 ? time(NULL): 0; + } + da_free(sp->atup_a); + sp->atup_a=ata; + da_free(adrs); + /* Successfully set IP addresses for this server section. */ + sp->rootserver=1; + } + else { + DEBUG_MSG("Failed to discover root servers in servstat_thread() (server section #%d).\n",i); + if(adrs) da_free(adrs); + if(DA_NEL(sp->atup_a)) keep_testing=1; + continue; + } + } + + if (needs_testing(sp)) keep_testing=1; + m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j).i_ts) + goto individual_tests; + /* Test collectively */ + if(!signal_interrupt) retest(i,-1); + continue; + + individual_tests: + for(j=0; !signal_interrupt && jatup_a,j).i_ts, now; + + if (ts==0 /* Always test servers with timestamp 0 */ || + (needs_intermittent_testing(sp) && + ((now=time(NULL))-ts>sp->interval || + ts>now /* kluge for clock skew */))) + { + retest(i,j); + } + } + } + } while(!signal_interrupt && retest_flag); + + signal_interrupt=0; + + /* Break the loop and exit the thread if it is no longer needed. */ + if(!keep_testing) break; + + { + struct timeval now; + struct timespec timeout; + time_t minwait; + int i,n,retval; + + gettimeofday(&now,NULL); + minwait=3600; /* Check at least once every hour. */ + n=DA_NEL(servers); + for (i=0;iatup_a); + for(j=0;jatup_a,j).i_ts; + if(ts==0) { + /* Test servers with timestamp 0 without delay */ + if(minwait > 0) minwait=0; + } + else if(needs_intermittent_testing(sp)) { + time_t wait= ts + sp->interval - now.tv_sec; + if(wait < minwait) minwait=wait; + } + } + } + timeout.tv_sec = now.tv_sec; + if(minwait>0) + timeout.tv_sec += minwait; + timeout.tv_nsec = now.tv_usec * 1000 + 500000000; /* wait at least half a second. */ + if(timeout.tv_nsec>=1000000000) { + timeout.tv_nsec -= 1000000000; + ++timeout.tv_sec; + } + /* While we wait for a server_test_cond condition or a timeout + the servers_lock mutex is unlocked, so other threads can access + server data + */ + retval=pthread_cond_timedwait(&server_test_cond, &servers_lock, &timeout); + DEBUG_MSG("Server status thread woke up (%s signal).\n", + retval==0?"test condition":retval==ETIMEDOUT?"timer":retval==EINTR?"interrupt":"error"); + } + } + + /* server status thread no longer needed. */ + servstat_thrid=main_thrid; + pthread_mutex_unlock(&servers_lock); + DEBUG_MSG("Server status thread exiting.\n"); + return NULL; +} + +/* + * Start the server status thread. + */ +int start_servstat_thread() +{ + pthread_t stt; + + int rv=pthread_create(&stt,&attr_detached,servstat_thread,NULL); + if (rv) + log_warn("Failed to start server status thread: %s",strerror(rv)); + else { + servstat_thrid=stt; + log_info(2,"Server status thread started."); + } + return rv; +} + +/* + * This can be used to mark a server (or a list of nadr servers) up (up=1) or down (up=0), + * or to schedule an immediate retest (up=-1). + * We can't always use indices to identify a server, because we allow run-time + * configuration of server addresses, so the servers are identified by their IP addresses. + */ +void sched_server_test(pdnsd_a *sa, int nadr, int up) +{ + int k,signal_test; + + pthread_mutex_lock(&servers_lock); + + signal_test=0; + /* This obviously isn't very efficient, but nadr should be small + and anything else would introduce considerable overhead */ + for(k=0;katup_a); + for(j=0;jatup_a,j); + if(equiv_inaddr2(sak,&at->a)) { + if(up>=0) { + at->is_up=up; + at->i_ts=time(NULL); + DEBUG_PDNSDA_MSG("Marked server %s %s.\n",PDNSDA2STR(sak),up?"up":"down"); + } + else if(at->i_ts) { + /* A test may take a while, and we don't want to hold + up the calling thread. + Instead we set the timestamp to zero and signal + a condition which should wake up the server test thread. + */ + at->i_ts=0; + signal_test=1; + } + } + } + } + } + if(signal_test) pthread_cond_signal(&server_test_cond); + + pthread_mutex_unlock(&servers_lock); +} + +/* Mark a set of servers up or down or schedule uptests. + * If i>=0 only the server section with index i is scanned, + * if i<0 all sections are scanned. + * Only sections matching label are actually set. A NULL label matches + * any section. + * up=1 or up=0 means mark server up or down, up=-1 means retest. + * + * A non-zero return value indicates an error. + */ +int mark_servers(int i, char *label, int up) +{ + int retval=0,n,signal_test; + + pthread_mutex_lock(&servers_lock); + + signal_test=0; + n=DA_NEL(servers); + if(i>=0) { + /* just one section */ + if(ilabel && !strcmp(sp->label,label))) { + int j,m=DA_NEL(sp->atup_a); + + /* If a section with undiscovered root servers is marked up, signal a test. */ + if(m && sp->rootserver>1 && up>0) signal_test=1; + + for(j=0;jatup_a,j); + if(up>=0) { + at->is_up=up; + at->i_ts=time(NULL); + } + else if(at->i_ts) { + /* A test may take a while, and we don't want to hold + up the calling thread. + Instead we set the timestamp to zero and signal + a condition which should wake up the server test thread. + */ + at->i_ts=0; + signal_test=1; + } + } + } + } + if(signal_test) { + if(pthread_equal(servstat_thrid,main_thrid)) + retval=start_servstat_thread(); + else { + retest_flag=1; + retval=pthread_cond_signal(&server_test_cond); + } + } + + pthread_mutex_unlock(&servers_lock); + return retval; +} + +/* + * Test called by the dns query handlers to handle interval=onquery cases. + */ +void test_onquery() +{ + int i,n,signal_test; + + pthread_mutex_lock(&servers_lock); + schm[0] = '\0'; + signal_test=0; + n=DA_NEL(servers); + for (i=0;iinterval==-1) { + if(sp->rootserver<=1) + retest(i,-1); + else { + /* We leave root-server discovery to the server status thread */ + int j,m=DA_NEL(sp->atup_a); + for(j=0;jatup_a,j).i_ts=0; + signal_test=1; + } + } + } + + if(signal_test) { + int rv; + if(pthread_equal(servstat_thrid,main_thrid)) + start_servstat_thread(); + else { + retest_flag=1; + if((rv=pthread_cond_signal(&server_test_cond))) { + DEBUG_MSG("test_onquery(): couldn't signal server status thread: %s\n",strerror(rv)); + } + } + } + + pthread_mutex_unlock(&servers_lock); +} + +/* non-exclusive lock, for read only access to server data. */ +void lock_server_data() +{ + pthread_mutex_lock(&servers_lock); + ++server_data_users; + pthread_mutex_unlock(&servers_lock); +} + +void unlock_server_data() +{ + pthread_mutex_lock(&servers_lock); + PDNSD_ASSERT(server_data_users>0, "server_data_users non-positive before attempt to decrement it"); + if (--server_data_users==0) pthread_cond_broadcast(&server_data_cond); + pthread_mutex_unlock(&servers_lock); +} + +/* Try to obtain an exclusive lock, needed for modifying server data. + Return 1 on success, 0 on failure (time out after tm seconds). +*/ +int exclusive_lock_server_data(int tm) +{ + struct timeval now; + struct timespec timeout; + + pthread_mutex_lock(&servers_lock); + if(server_status_ping>0 && !pthread_equal(servstat_thrid,main_thrid)) { + int err; + /* Try to interrupt server status thread to prevent delays. */ + DEBUG_MSG("Sending server status thread an interrupt signal.\n"); + if((err=pthread_kill(servstat_thrid,statusintsig))) { + DEBUG_MSG("pthread_kill failed: %s\n",strerror(err)); + } + } + gettimeofday(&now,NULL); + timeout.tv_sec = now.tv_sec + tm; /* time out after tm seconds */ + timeout.tv_nsec = now.tv_usec * 1000; + while (server_data_users>0) { + if(pthread_cond_timedwait(&server_data_cond, &servers_lock, &timeout) == ETIMEDOUT) { + pthread_mutex_unlock(&servers_lock); + return 0; + } + } + return 1; +} +/* Call this to free the lock obtained with exclusive_lock_server_data(). + If retest is nonzero, the server-status thread is reactivated to check + which servers are up. This is useful in case the configuration has changed. +*/ +void exclusive_unlock_server_data(int retest) +{ + if(retest) { + if(pthread_equal(servstat_thrid,main_thrid)) + start_servstat_thread(); + else + pthread_cond_signal(&server_test_cond); + } + pthread_mutex_unlock(&servers_lock); +} + +/* + Change addresses of servers during runtime. + i is the number of the server section to change. + ar should point to an array of IP addresses (may be NULL). + up=1 or up=0 means mark server up or down afterwards, + up=-1 means retest. + + A non-zero return value indicates an error. +*/ +int change_servers(int i, addr_array ar, int up) +{ + int retval=0,j,change,signal_test; + int n; + servparm_t *sp; + + pthread_mutex_lock(&servers_lock); + + signal_test=0; + change=0; + n=DA_NEL(ar); + sp=&DA_INDEX(servers,i); + if(n != DA_NEL(sp->atup_a) || sp->rootserver>1) + change=1; + else { + int j; + for(j=0;jatup_a,j).a)) { + change=1; + break; + } + } + if(change) { + /* we need exclusive access to the server data to make the changes */ + struct timeval now; + struct timespec timeout; + atup_array ata; + + if(server_status_ping>0 && !pthread_equal(servstat_thrid,main_thrid)) { + int err; + /* Try to interrupt server status thread to prevent delays. */ + DEBUG_MSG("Sending server status thread an interrupt signal.\n"); + if((err=pthread_kill(servstat_thrid,statusintsig))) { + DEBUG_MSG("pthread_kill failed: %s\n",strerror(err)); + } + } + + DEBUG_MSG("Changing IPs of server section #%d\n",i); + gettimeofday(&now,NULL); + timeout.tv_sec = now.tv_sec + 60; /* time out after 60 seconds */ + timeout.tv_nsec = now.tv_usec * 1000; + while (server_data_users>0) { + if(pthread_cond_timedwait(&server_data_cond, &servers_lock, &timeout) == ETIMEDOUT) { + retval=ETIMEDOUT; + goto unlock_mutex; + } + } + + ata= DA_CREATE(atup_array, n); + if(!ata) { + log_warn("Out of memory in change_servers()."); + retval=ENOMEM; + goto unlock_mutex; + } + da_free(sp->atup_a); + sp->atup_a=ata; + /* Stop trying to discover rootservers + if we set the addresses using this routine. */ + if(sp->rootserver>1) sp->rootserver=1; + } + + for(j=0; jatup_a,j); + if(change) { + SET_PDNSD_A2(&at->a, &DA_INDEX(ar,j)); + at->is_up=sp->preset; + } + if(up>=0) { + at->is_up=up; + at->i_ts=time(NULL); + } + else if(change || at->i_ts) { + /* A test may take a while, and we don't want to hold + up the calling thread. + Instead we set the timestamp to zero and signal + a condition which should wake up the server test thread. + */ + at->i_ts=0; + signal_test=1; + } + } + + if(signal_test) { + if(pthread_equal(servstat_thrid,main_thrid)) + retval=start_servstat_thread(); + else { + retest_flag=1; + retval=pthread_cond_signal(&server_test_cond); + } + } + + unlock_mutex: + pthread_mutex_unlock(&servers_lock); + return retval; +} + + +/* + The signal handler for the signal to tell the server status thread to discontinue testing. +*/ +static void sigint_handler(int signum) +{ + signal_interrupt=1; +} diff --git a/jni/pdnsd/src/servers.h b/jni/pdnsd/src/servers.h new file mode 100644 index 00000000..fd263c0c --- /dev/null +++ b/jni/pdnsd/src/servers.h @@ -0,0 +1,68 @@ +/* servers.h - manage a set of dns servers + + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _SERVERS_H_ +#define _SERVERS_H_ + +#include +#include "consts.h" + +/* Number of ping timeouts before we take a server offline. */ +#define PINGREPEAT 2 + +extern pthread_t servstat_thrid; +extern volatile int signal_interrupt; + + +int start_servstat_thread(void); +void sched_server_test(pdnsd_a *sa, int nadr, int up); +int mark_servers(int i, char* label, int up); +void test_onquery(void); +void lock_server_data(); +void unlock_server_data(); +int exclusive_lock_server_data(int tm); +void exclusive_unlock_server_data(int retest); +int change_servers(int i, addr_array ar, int up); + +inline static int needs_testing(servparm_t *sp) + __attribute__((always_inline)); +inline static int needs_testing(servparm_t *sp) +{ + return ((sp->interval>0 || sp->interval==-2) && (sp->uptest!=C_NONE || sp->scheme[0])); +} + +inline static int needs_intermittent_testing(servparm_t *sp) + __attribute__((always_inline)); +inline static int needs_intermittent_testing(servparm_t *sp) +{ + return (sp->interval>0 && (sp->uptest!=C_NONE || sp->scheme[0])); +} + +inline static int is_interrupted_servstat_thread() + __attribute__((always_inline)); +inline static int is_interrupted_servstat_thread() +{ + return (signal_interrupt && pthread_equal(pthread_self(),servstat_thrid)); +} + +#endif diff --git a/jni/pdnsd/src/sort_namevalues.pl b/jni/pdnsd/src/sort_namevalues.pl new file mode 100644 index 00000000..2014f49f --- /dev/null +++ b/jni/pdnsd/src/sort_namevalues.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl -w + +use strict; + +my %dic; +my $maxkeylen=0; + +while(<>) { + if(/"(\w+)".*?(\w+)/) { + my $key=$1; my $val=$2; + if($dic{$key}) {die "The key \"$key\" does not have a unique value.\n"} + $dic{$key}=$val; + if(length($key)>$maxkeylen) {$maxkeylen=length($key)} + } + else {die "Can't find key-value pair in following line:\n$_\n"} +} + +my $linenr=0; +foreach my $key (sort(keys %dic)) { + if($linenr++) {print ",\n"} + printf("\t{%-*s%s}",$maxkeylen+4,"\"$key\",",$dic{$key}); +} +print "\n"; + +exit diff --git a/jni/pdnsd/src/status.c b/jni/pdnsd/src/status.c new file mode 100644 index 00000000..4240069d --- /dev/null +++ b/jni/pdnsd/src/status.c @@ -0,0 +1,824 @@ +/* status.c - Allow control of a running server using a socket + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2011 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for offsetof */ +#include "ipvers.h" +#include "status.h" +#include "thread.h" +#include "cache.h" +#include "error.h" +#include "servers.h" +#include "dns_answer.h" +#include "helpers.h" +#include "conf-parser.h" + +#if !defined(HAVE_ALLOCA) && !defined(alloca) +#define alloca malloc +#endif + + +char *sock_path=NULL; +int stat_sock; + + +/* Print an error to the socket */ +static int print_serr(int rs, const char *msg) +{ + uint16_t cmd; + + DEBUG_MSG("Sending error message to control socket: '%s'\n",msg); + cmd=htons(1); + if(write(rs,&cmd,sizeof(cmd))!=sizeof(cmd) || + write_all(rs,msg,strlen(msg))<0) + { + DEBUG_MSG("Error writing to control socket: %s\n",strerror(errno)); + return 0; + } + return 1; +} + +/* Print a success code to the socket */ +static int print_succ(int rs) +{ + uint16_t cmd; + + cmd=htons(0); + if(write(rs,&cmd,sizeof(cmd))!=sizeof(cmd)) { + DEBUG_MSG("Error writing to control socket: %s\n" + "Failed to send success code.\n",strerror(errno)); + return 0; + } + return 1; +} + +/* Read a cmd short */ +static int read_short(int fh, uint16_t *res) +{ + uint16_t cmd; + + if (read(fh,&cmd,sizeof(cmd))!=sizeof(cmd)) { + /* print_serr(fh,"Bad arg."); */ + return 0; + } + *res= ntohs(cmd); + return 1; +} + +/* Read a cmd long */ +static int read_long(int fh, uint32_t *res) +{ + uint32_t cmd; + + if (read(fh,&cmd,sizeof(cmd))!=sizeof(cmd)) { + /* print_serr(fh,"Bad arg."); */ + return 0; + } + *res= ntohl(cmd); + return 1; +} + +/* Read a string preceded by a char count. + A buffer of the right size is allocated to hold the result. + A return value of 1 means success, + -1 means the result is undefined (*res is set to NULL), + 0 means read or allocation error. +*/ +static int read_allocstring(int fh, char **res, unsigned *len) +{ + uint16_t count; + char *buf; + unsigned int nread; + + if(!read_short(fh,&count)) return 0; + if(count==(uint16_t)(~0)) {*res=NULL; return -1;} + if(!(buf=malloc(count+1))) return 0; + nread=0; + while(nread=buflen) return 0; + nread=0; + while(nread=buflen) return 0; + buf[count]='.'; buf[count+1]=0; + } +#endif + return 1; +} + +static void *status_thread (void *p) +{ + THREAD_SIGINIT; + /* (void)p; */ /* To inhibit "unused variable" warning */ + + if (!global.strict_suid) { + if (!run_as(global.run_as)) { + pdnsd_exit(); + } + } + + if (listen(stat_sock,5)==-1) { + log_warn("Error: could not listen on socket: %s.\nStatus readback will be impossible",strerror(errno)); + goto exit_thread; + } + for(;;) { + struct sockaddr_un ra; + socklen_t res=sizeof(ra); + int rs; + if ((rs=accept(stat_sock,(struct sockaddr *)&ra,&res))!=-1) { + uint16_t cmd; + DEBUG_MSG("Status socket query pending.\n"); + if (read_short(rs,&cmd)) { + /* Check magic number in command */ + if((cmd & 0xff00) == CTL_CMDVERNR) { + const char *errmsg; + cmd &= 0xff; + switch(cmd) { + case CTL_STATS: { + struct utsname nm; + DEBUG_MSG("Received STATUS query.\n"); + if(!print_succ(rs)) + break; + uname(&nm); + if(fsprintf(rs,"pdnsd-%s running on %s.\n",VERSION,nm.nodename)<0 || + report_cache_stat(rs)<0 || + report_thread_stat(rs)<0 || + report_conf_stat(rs)<0) + { + DEBUG_MSG("Error writing to control socket: %s\n" + "Failed to send status report.\n",strerror(errno)); + } + } + break; + case CTL_SERVER: { + char *label,*dnsaddr; + int indx; + uint16_t cmd2; + DEBUG_MSG("Received SERVER command.\n"); + if (read_allocstring(rs,&label,NULL)<=0) { + print_serr(rs,"Error reading server label."); + break; + } + if (!read_short(rs,&cmd2)) { + print_serr(rs,"Missing up|down|retest."); + goto free_label_break; + } + if(!read_allocstring(rs, &dnsaddr,NULL)) { + print_serr(rs,"Error reading DNS addresses."); + goto free_label_break; + } + /* Note by Paul Rombouts: + We are about to access server configuration data. + Now that the configuration can be changed during run time, + we should be using locks before accessing server config data, even if it + is read-only access. + However, as long as this is the only thread that calls reload_config_file() + it should be OK to read the server config without locks, but it is + something to keep in mind. + */ + { + char *endptr; + indx=strtol(label,&endptr,0); + if(!*endptr) { + if (indx<0 || indx>=DA_NEL(servers)) { + print_serr(rs,"Server index out of range."); + goto free_dnsaddr_label_break; + } + } + else { + if (!strcmp(label, "all")) + indx=-2; /* all servers */ + else + indx=-1; /* compare names */ + } + } + if(cmd2==CTL_S_UP || cmd2==CTL_S_DOWN || cmd2==CTL_S_RETEST) { + if(!dnsaddr) { + if (indx==-1) { + int i; + for (i=0;idomain=malloc(sz))) { + print_serr(rs,"Out of memory."); + goto free_sla_names_break; + } + memcpy(sl->domain,rhn,sz); + sl->exact=0; + sl->rule=tp; + p = q+1; + } + } + if(empty_cache(sla)) + print_succ(rs); + else + print_serr(rs,"Could not lock the cache."); + free_sla_names_break: + free_slist_array(sla); + free_names_break: + free(names); + } + break; + case CTL_DUMP: { + int rv,exact=0; + unsigned char *nm=NULL; + char buf[DNSNAMEBUFSIZE]; + unsigned char rhn[DNSNAMEBUFSIZE]; + DEBUG_MSG("Received DUMP command.\n"); + if (!(rv=read_domain(rs,buf,sizeof(buf)))) { + print_serr(rs,"Bad domain name."); + break; + } + if(rv>0) { + int sz; + exact=1; nm= ucharp buf; sz=sizeof(buf); + if(buf[0]=='.' && buf[1]) { + exact=0; ++nm; --sz; + } + if ((errmsg=parsestr2rhn(nm,sz,rhn))!=NULL) + goto bad_domain_name; + nm=rhn; + } + if(!print_succ(rs)) + break; + if((rv=dump_cache(rs,nm,exact))<0 || + (!rv && fsprintf(rs,"Could not find %s%s in the cache.\n", + exact?"":nm?"any entries matching ":"any entries", + nm?buf:"")<0)) + { + DEBUG_MSG("Error writing to control socket: %s\n",strerror(errno)); + } + } + break; + incomplete_command: + print_serr(rs,"Malformed or incomplete command."); + break; + bad_arg: + print_serr(rs,"Bad arg."); + break; + bad_domain_name: + print_serr(rs,errmsg); + break; + bad_ttl: + print_serr(rs, "Bad TTL."); + break; + bad_flags: + print_serr(rs, "Bad cache flags."); + break; + out_of_memory: + print_serr(rs,"Out of memory."); + break; + default: + print_serr(rs,"Unknown command."); + } + } + else { + DEBUG_MSG("Incorrect magic number in status-socket command code: %02x\n",cmd>>8); + print_serr(rs,"Command code contains incompatible version number."); + } + } + else { + DEBUG_MSG("short status-socket query\n"); + print_serr(rs,"Command code missing or too short."); + } + close(rs); + usleep_r(100000); /* sleep some time. I do not want the query frequency to be too high. */ + } + else if (errno!=EINTR) { + log_warn("Failed to accept connection on status socket: %s. " + "Status readback will be impossible",strerror(errno)); + break; + } + } + + exit_thread: + stat_pipe=0; + close(stat_sock); + statsock_thrid=main_thrid; + + return NULL; +} + +/* + * Initialize the status socket + */ +void init_stat_sock() +{ + struct sockaddr_un *sa; + /* Should I include the terminating null byte in the calculation of the length parameter + for the socket address? The glibc info page "Details of Local Namespace" tells me I should not, + yet it is immediately followed by an example that contradicts that. + The SUN_LEN macro seems to be defined as + (offsetof(struct sockaddr_un, sun_path) + strlen(sa->sun_path)), + so I conclude it is not necessary to count the null byte, but it probably makes no + difference if you do. + */ + unsigned int sa_len = (offsetof(struct sockaddr_un, sun_path) + strlitlen("/pdnsd.status") + strlen(global.cache_dir)); + + sa=(struct sockaddr_un *)alloca(sa_len+1); + stpcpy(stpcpy(sa->sun_path,global.cache_dir),"/pdnsd.status"); + + if (unlink(sa->sun_path)!=0 && errno!=ENOENT) { /* Delete the socket */ + log_warn("Failed to unlink %s: %s.\nStatus readback will be disabled",sa->sun_path, strerror(errno)); + stat_pipe=0; + return; + } + if ((stat_sock=socket(PF_UNIX,SOCK_STREAM,0))==-1) { + log_warn("Failed to open socket: %s. Status readback will be impossible",strerror(errno)); + stat_pipe=0; + return; + } + sa->sun_family=AF_UNIX; +#ifdef BSD44_SOCKA + sa->sun_len=SUN_LEN(sa); +#endif + /* Early initialization, so that umask can be used race-free. */ + { + mode_t old_mask = umask((S_IRWXU|S_IRWXG|S_IRWXO)&(~global.ctl_perms)); + if (bind(stat_sock,(struct sockaddr *)sa,sa_len)==-1) { + log_warn("Error: could not bind socket: %s.\nStatus readback will be impossible",strerror(errno)); + close(stat_sock); + stat_pipe=0; + } + umask(old_mask); + } + + if(stat_pipe) sock_path= strdup(sa->sun_path); +} + +/* + * Start the status socket thread (see above) + */ +int start_stat_sock() +{ + pthread_t st; + + int rv=pthread_create(&st,&attr_detached,status_thread,NULL); + if (rv) + log_warn("Failed to start status thread. The status socket will be unuseable"); + else { + statsock_thrid=st; + log_info(2,"Status thread started."); + } + return rv; +} diff --git a/jni/pdnsd/src/status.h b/jni/pdnsd/src/status.h new file mode 100644 index 00000000..1d249f79 --- /dev/null +++ b/jni/pdnsd/src/status.h @@ -0,0 +1,59 @@ +/* status.h - Make server status information accessible through a named pipe + + Copyright (C) 2000, 2001 Thomas Moestl + Copyright (C) 2002, 2004, 2008, 2009 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _STATUS_H_ +#define _STATUS_H_ + +#include +#include "conff.h" + +extern char *sock_path; +extern int stat_sock; + +/* The commands for pdnsd-ctl */ +#define CTL_CMDVERNR 0x6800 /* pdnsd-ctl command version (magic number used to check compatibility) */ + +#define CTL_MIN 1 +#define CTL_STATS 1 /* Give out stats (like the "traditional" status pipe) */ +#define CTL_SERVER 2 /* Enable or disable a server */ +#define CTL_RECORD 3 /* Delete or invalidate records */ +#define CTL_SOURCE 4 /* Read a hosts-style file */ +#define CTL_ADD 5 /* Add a record of the given type */ +#define CTL_NEG 6 /* Add a negative cached record */ +#define CTL_CONFIG 7 /* Re-read config file */ +#define CTL_INCLUDE 8 /* Read file as config file, disregarding global and server sections */ +#define CTL_EVAL 9 /* Parse string as if part of config file */ +#define CTL_EMPTY 10 /* Empty the cache */ +#define CTL_DUMP 11 /* Dump cache contents */ +#define CTL_MAX 11 + +#define CTL_S_UP 1 +#define CTL_S_DOWN 2 +#define CTL_S_RETEST 3 +#define CTL_R_DELETE 1 +#define CTL_R_INVAL 2 + +void init_stat_sock(void); +int start_stat_sock(void); + +#endif diff --git a/jni/pdnsd/src/test/Makefile.am b/jni/pdnsd/src/test/Makefile.am new file mode 100644 index 00000000..81da0882 --- /dev/null +++ b/jni/pdnsd/src/test/Makefile.am @@ -0,0 +1,35 @@ + +.PHONY: all clean distclean + +noinst_PROGRAMS = if_up is_local_addr tping random + +## Dirty trick: I demand that these objects be built; then, with the knowledge +## that the object files will end up here, I redefine the link chain. + +TESTADDSRC= +#TESTADDSRC= netdev.c error.c thread.c helpers.c icmp.c +TESTDEPS = netdev.o error.o thread.o helpers.o icmp.o + +TESTOBJS = netdev.o error.o thread.o helpers.o icmp.o + +if_up_SOURCES = if_up.c $(TESTADDSRC) +if_up_LDADD = $(TESTOBJS) @thread_CFLAGS@ +if_up_DEPENDENCIES = $(TESTDEPS) + +is_local_addr_SOURCES = is_local_addr.c $(TESTADDSRC) +is_local_addr_LDADD = $(TESTOBJS) @thread_CFLAGS@ +is_local_addr_DEPENDENCIES = $(TESTDEPS) + +tping_SOURCES = tping.c $(TESTADDSRC) +tping_LDADD = $(TESTOBJS) @thread_CFLAGS@ +tping_DEPENDENCIES = $(TESTDEPS) + +random_SOURCES = random.c $(TESTADDSRC) +random_LDADD = $(TESTOBJS) @thread_CFLAGS@ +random_DEPENDENCIES = $(TESTDEPS) + +# These are Symlinks we want to have in the package +#EXTRA_DIST = conff.h error.h helpers.h icmp.h ipvers.h netdev.h thread.h cacheing + +$(TESTOBJS): %.o: ../%.c + $(COMPILE) @thread_CFLAGS@ -c $< diff --git a/jni/pdnsd/src/test/Makefile.in b/jni/pdnsd/src/test/Makefile.in new file mode 100644 index 00000000..2ad86412 --- /dev/null +++ b/jni/pdnsd/src/test/Makefile.in @@ -0,0 +1,464 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# 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@ +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 = : +noinst_PROGRAMS = if_up$(EXEEXT) is_local_addr$(EXEEXT) tping$(EXEEXT) \ + random$(EXEEXT) +subdir = src/test +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am__objects_1 = +am_if_up_OBJECTS = if_up.$(OBJEXT) $(am__objects_1) +if_up_OBJECTS = $(am_if_up_OBJECTS) +am_is_local_addr_OBJECTS = is_local_addr.$(OBJEXT) $(am__objects_1) +is_local_addr_OBJECTS = $(am_is_local_addr_OBJECTS) +am_random_OBJECTS = random.$(OBJEXT) $(am__objects_1) +random_OBJECTS = $(am_random_OBJECTS) +am_tping_OBJECTS = tping.$(OBJEXT) $(am__objects_1) +tping_OBJECTS = $(am_tping_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(if_up_SOURCES) $(is_local_addr_SOURCES) $(random_SOURCES) \ + $(tping_SOURCES) +DIST_SOURCES = $(if_up_SOURCES) $(is_local_addr_SOURCES) \ + $(random_SOURCES) $(tping_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +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_alias = @build_alias@ +builddir = @builddir@ +cachedir = @cachedir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +def_id = @def_id@ +distribution = @distribution@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fullversion = @fullversion@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +packagerelease = @packagerelease@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +specbuild = @specbuild@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +thread_CFLAGS = @thread_CFLAGS@ +threadlib = @threadlib@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +TESTADDSRC = +#TESTADDSRC= netdev.c error.c thread.c helpers.c icmp.c +TESTDEPS = netdev.o error.o thread.o helpers.o icmp.o +TESTOBJS = netdev.o error.o thread.o helpers.o icmp.o +if_up_SOURCES = if_up.c $(TESTADDSRC) +if_up_LDADD = $(TESTOBJS) @thread_CFLAGS@ +if_up_DEPENDENCIES = $(TESTDEPS) +is_local_addr_SOURCES = is_local_addr.c $(TESTADDSRC) +is_local_addr_LDADD = $(TESTOBJS) @thread_CFLAGS@ +is_local_addr_DEPENDENCIES = $(TESTDEPS) +tping_SOURCES = tping.c $(TESTADDSRC) +tping_LDADD = $(TESTOBJS) @thread_CFLAGS@ +tping_DEPENDENCIES = $(TESTDEPS) +random_SOURCES = random.c $(TESTADDSRC) +random_LDADD = $(TESTOBJS) @thread_CFLAGS@ +random_DEPENDENCIES = $(TESTDEPS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .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) --gnu src/test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/test/Makefile +.PRECIOUS: 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-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +if_up$(EXEEXT): $(if_up_OBJECTS) $(if_up_DEPENDENCIES) + @rm -f if_up$(EXEEXT) + $(LINK) $(if_up_OBJECTS) $(if_up_LDADD) $(LIBS) +is_local_addr$(EXEEXT): $(is_local_addr_OBJECTS) $(is_local_addr_DEPENDENCIES) + @rm -f is_local_addr$(EXEEXT) + $(LINK) $(is_local_addr_OBJECTS) $(is_local_addr_LDADD) $(LIBS) +random$(EXEEXT): $(random_OBJECTS) $(random_DEPENDENCIES) + @rm -f random$(EXEEXT) + $(LINK) $(random_OBJECTS) $(random_LDADD) $(LIBS) +tping$(EXEEXT): $(tping_OBJECTS) $(tping_DEPENDENCIES) + @rm -f tping$(EXEEXT) + $(LINK) $(tping_OBJECTS) $(tping_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/if_up.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_local_addr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tping.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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 +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + 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" + +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 $(PROGRAMS) +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: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +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-noinstPROGRAMS 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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic 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 pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + + +.PHONY: all clean distclean + +# These are Symlinks we want to have in the package +#EXTRA_DIST = conff.h error.h helpers.h icmp.h ipvers.h netdev.h thread.h cacheing + +$(TESTOBJS): %.o: ../%.c + $(COMPILE) @thread_CFLAGS@ -c $< + +# 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/jni/pdnsd/src/test/if_up.c b/jni/pdnsd/src/test/if_up.c new file mode 100644 index 00000000..af6ec976 --- /dev/null +++ b/jni/pdnsd/src/test/if_up.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include "../helpers.h" +#include "../conff.h" +#include "../netdev.h" + +short int daemon_p=0; +#if DEBUG>0 +short int debug_p=0; +#endif +short int verbosity=VERBOSITY; +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +short int run_ipv4=DEFAULT_IPV4; +#endif +#ifdef ENABLE_IPV6 +struct in6_addr ipv4_6_prefix; +#endif +pthread_t main_thrid,servstat_thrid; +volatile int signal_interrupt; +#if DEBUG>0 +FILE *dbg_file; +#endif +globparm_t global; + + +int main(int argc, char *argv[]) +{ + if (argc!=2) { + printf("Usage: %s \n",argv[0]); + exit(1); + } + printf("if_up: %s - %s\n",argv[1],if_up(argv[1])?"up":"down"); + return 0; +} diff --git a/jni/pdnsd/src/test/is_local_addr.c b/jni/pdnsd/src/test/is_local_addr.c new file mode 100644 index 00000000..fda517d6 --- /dev/null +++ b/jni/pdnsd/src/test/is_local_addr.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include "../helpers.h" +#include "../conff.h" +#include "../netdev.h" +#include "../ipvers.h" + +short int daemon_p=0; +#if DEBUG>0 +short int debug_p=0; +#endif +short int verbosity=VERBOSITY; +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +short int run_ipv4=DEFAULT_IPV4; +#endif +#ifdef ENABLE_IPV6 +struct in6_addr ipv4_6_prefix; +#endif +pthread_t main_thrid,servstat_thrid; +volatile int signal_interrupt; +#if DEBUG>0 +FILE *dbg_file; +#endif +globparm_t global; + + +int main(int argc, char *argv[]) +{ + pdnsd_a a; + + if (argc!=2) { + printf("Usage: %s
    \n",argv[0]); + exit(1); + } +#ifdef ENABLE_IPV4 + if (inet_aton(argv[1],&a.ipv4)) { +# ifdef ENABLE_IPV6 + run_ipv4=1; +# endif + printf("is %s a local addr: %s\n",argv[1],is_local_addr(&a)?"yes":"no"); + return 0; + } +#endif +#ifdef ENABLE_IPV6 + if (inet_pton(AF_INET6,argv[1],&a.ipv6)) { +# ifdef ENABLE_IPV4 + run_ipv4=0; +# endif + printf("is %s a local addr: %s\n",argv[1],is_local_addr(&a)?"yes":"no"); + return 0; + } +#endif + printf("Adress invalid.\n"); + return 0; +} diff --git a/jni/pdnsd/src/test/random.c b/jni/pdnsd/src/test/random.c new file mode 100644 index 00000000..a447e80c --- /dev/null +++ b/jni/pdnsd/src/test/random.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include "../helpers.h" +#include "../conff.h" + +short int daemon_p=0; +#if DEBUG>0 +short int debug_p=0; +#endif +short int verbosity=VERBOSITY; +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +short int run_ipv4=DEFAULT_IPV4; +#endif +#ifdef ENABLE_IPV6 +struct in6_addr ipv4_6_prefix; +#endif +pthread_t main_thrid,servstat_thrid; +volatile int signal_interrupt; +#if DEBUG>0 +FILE *dbg_file; +#endif +globparm_t global; + + +int main(void) +{ + init_rng(); + printf("%i\n",(int)get_rand16()); + free_rng(); + return 0; +} diff --git a/jni/pdnsd/src/test/tping.c b/jni/pdnsd/src/test/tping.c new file mode 100644 index 00000000..734a25f7 --- /dev/null +++ b/jni/pdnsd/src/test/tping.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include "../helpers.h" +#include "../conff.h" +#include "../icmp.h" +#include "../ipvers.h" + +short int daemon_p=0; +#if DEBUG>0 +short int debug_p=0; +#endif +short int verbosity=VERBOSITY; +#if defined(ENABLE_IPV4) && defined(ENABLE_IPV6) +short int run_ipv4=DEFAULT_IPV4; +#endif +#ifdef ENABLE_IPV6 +struct in6_addr ipv4_6_prefix; +#endif +pthread_t main_thrid,servstat_thrid; +volatile int signal_interrupt; +#if DEBUG>0 +FILE *dbg_file; +#endif +globparm_t global; + + +int main(int argc, char *argv[]) +{ + pdnsd_a a; + + if (argc!=2) { + printf("Usage: %s
    \n",argv[0]); + exit(1); + } +#ifdef ENABLE_IPV4 + if (inet_aton(argv[1],&a.ipv4)) { +# ifdef ENABLE_IPV6 + run_ipv4=1; +# endif + init_ping_socket(); + printf("ping (v4) echo from %s: %i\n",argv[1],ping(&a,100,2)); + return 0; + } +#endif +#ifdef ENABLE_IPV6 + if (inet_pton(AF_INET6,argv[1],&a.ipv6)) { +# ifdef ENABLE_IPV4 + run_ipv4=0; +# endif + init_ping_socket(); + printf("ping (v6) echo from %s: %i\n",argv[1],ping(&a,100,2)); + return 0; + } +#endif + printf("Adress invalid.\n"); + return 0; +} diff --git a/jni/pdnsd/src/thread.c b/jni/pdnsd/src/thread.c new file mode 100644 index 00000000..84c34f6d --- /dev/null +++ b/jni/pdnsd/src/thread.c @@ -0,0 +1,85 @@ +/* thread.c - Threading helpers + + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2002, 2003 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thread.h" +#include "error.h" +#include "helpers.h" +#include "conff.h" + + +#if (TARGET==TARGET_LINUX) && !defined(THREADLIB_NPTL) +volatile short int waiting=0; /* Has the main thread already done sigwait() ? */ +#endif +pthread_attr_t attr_detached; +#if DEBUG>0 +pthread_key_t thrid_key; +#endif + +/* This is a handler for signals to the threads. We just hand the sigs on to the main thread. + * Note that this may result in blocked locks. We have no means to open the locks here, because in LinuxThreads + * the mutex functions are not async-signal safe. So, locks may still be active. We account for this by using + * softlocks (see below) in any functions called after sigwait from main(). */ +#if (TARGET==TARGET_LINUX) && !defined(THREADLIB_NPTL) +void thread_sig(int sig) +{ + if (sig==SIGTSTP || sig==SIGTTOU || sig==SIGTTIN) { + /* nonfatal signal. Ignore, because proper handling is very difficult. */ + return; + } + if (waiting) { + log_warn("Caught signal %i.",sig); + if (sig==SIGSEGV || sig==SIGILL || sig==SIGBUS) + crash_msg("A fatal signal occured."); + pthread_kill(main_thrid,SIGTERM); + pthread_exit(NULL); + } else { + crash_msg("An error occured at startup."); + _exit(1); + } +} +#endif + +/* This is now defined as an inline function in thread.h */ +#if 0 +void usleep_r(unsigned long usec) +{ +#if ((TARGET==TARGET_LINUX) || (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN)) && defined(HAVE_USLEEP) + usleep(usec); +#else + struct timeval tv; + + tv.tv_sec=usec/1000000; + tv.tv_usec=usec%1000000; + select(0, NULL, NULL, NULL, tv); +#endif +} +#endif + diff --git a/jni/pdnsd/src/thread.h b/jni/pdnsd/src/thread.h new file mode 100644 index 00000000..12d17dd1 --- /dev/null +++ b/jni/pdnsd/src/thread.h @@ -0,0 +1,143 @@ +/* thread.h - Threading helpers + + Copyright (C) 2000 Thomas Moestl + Copyright (C) 2002, 2003, 2005 Paul A. Rombouts + + This file is part of the pdnsd package. + + pdnsd 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. + + pdnsd 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 pdnsd; see the file COPYING. If not, see + . +*/ + + +#ifndef _THREAD_H_ +#define _THREAD_H_ + +#include +#include +#include + +/* --- from main.c */ +extern sigset_t sigs_msk; +/* --- */ + +#if (TARGET==TARGET_LINUX) && !defined(THREADLIB_NPTL) +extern volatile short int waiting; +void thread_sig(int sig); +#endif + +/* These are macros for setting up the signal handling of a new thread. They + * are needed because the LinuxThreads implementation obviously has some + * problems in signal handling, which makes the recommended solution (doing + * sigwait() in one thread and blocking the signals in all threads) impossible. + * So, for Linux, we have to install the fatal_sig handler. + * It seems to me that signal handlers in fact aren't shared between threads + * under Linux. Also, sigwait() does not seem to work as indicated in the docs */ + +/* Note added by Paul Rombouts: In the new Native POSIX Thread Library for Linux (NPTL) + signal handling has changed from per-thread signal handling to POSIX process signal handling, + which makes the recommended solution mentioned by Thomas Moestl possible. + In this case I can simply define THREAD_SIGINIT to be empty. + The signals are blocked in main() before any threads are created, + and we simply never unblock them except by calling sigwait() in main(). */ + +#if (TARGET==TARGET_LINUX) +# ifdef THREADLIB_NPTL +# define THREAD_SIGINIT +# else +# ifdef THREADLIB_LINUXTHREADS2 +# define THREAD_SIGINIT { \ + struct sigaction action; \ + pthread_sigmask(SIG_UNBLOCK,&sigs_msk,NULL); \ + action.sa_handler = thread_sig; \ + action.sa_mask = sigs_msk; \ + action.sa_flags = 0; \ + sigaction(SIGINT,&action,NULL); \ + sigaction(SIGILL,&action,NULL); \ + sigaction(SIGABRT,&action,NULL); \ + sigaction(SIGFPE,&action,NULL); \ + sigaction(SIGSEGV,&action,NULL); \ + sigaction(SIGTSTP,&action,NULL); \ + sigaction(SIGTTOU,&action,NULL); \ + sigaction(SIGTTIN,&action,NULL); \ + sigaction(SIGTERM,&action,NULL); \ + action.sa_handler = SIG_IGN; \ + sigemptyset(&action.sa_mask); \ + action.sa_flags = 0; \ + sigaction(SIGPIPE,&action,NULL); \ + } +# else +# define THREAD_SIGINIT { \ + struct sigaction action; \ + pthread_sigmask(SIG_UNBLOCK,&sigs_msk,NULL); \ + action.sa_handler = thread_sig; \ + action.sa_mask = sigs_msk; \ + action.sa_flags = 0; \ + sigaction(SIGILL,&action,NULL); \ + sigaction(SIGABRT,&action,NULL); \ + sigaction(SIGFPE,&action,NULL); \ + sigaction(SIGSEGV,&action,NULL); \ + sigaction(SIGTSTP,&action,NULL); \ + sigaction(SIGTTOU,&action,NULL); \ + sigaction(SIGTTIN,&action,NULL); \ + action.sa_handler = SIG_IGN; \ + sigemptyset(&action.sa_mask); \ + action.sa_flags = 0; \ + sigaction(SIGPIPE,&action,NULL); \ + } +# endif +# endif +#elif (TARGET==TARGET_BSD) || (TARGET==TARGET_CYGWIN) +#define THREAD_SIGINIT pthread_sigmask(SIG_BLOCK,&sigs_msk,NULL) +#else +# error Unsupported platform! +#endif + + +/* This is a thread-safe usleep(). + Implementation of the BSD usleep function using nanosleep. +*/ +inline static int usleep_r(unsigned long useconds) + __attribute__((always_inline)); +inline static int usleep_r(unsigned long useconds) +{ + struct timespec ts = { tv_sec: (useconds / 1000000), + tv_nsec: (useconds % 1000000) * 1000ul }; + + return nanosleep(&ts, NULL); +} + +/* This is a thread-safe sleep(). + The semantics are somewhat different from the POSIX sleep function, + but it suits our purposes. +*/ +inline static int sleep_r (unsigned int seconds) + __attribute__((always_inline)); +inline static int sleep_r (unsigned int seconds) +{ + struct timespec ts = { tv_sec: seconds, tv_nsec: 0 }; + + return nanosleep(&ts, NULL); +} + + +/* Used for creating detached threads */ +extern pthread_attr_t attr_detached; + +#if DEBUG>0 +/* Key for storing private thread ID's */ +extern pthread_key_t thrid_key; +#endif + +#endif diff --git a/jni/pdnsd/version b/jni/pdnsd/version new file mode 100644 index 00000000..c400a378 --- /dev/null +++ b/jni/pdnsd/version @@ -0,0 +1 @@ +1.2.9b-par diff --git a/libs/arm64-v8a/libtun2socks.so b/libs/arm64-v8a/libtun2socks.so index 9d5b3dd9bbb4cb9b54479cedba99df03d39d7059..a505b69bc921f2372ab86f9023212586ebb716e0 100755 GIT binary patch delta 28284 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 b^-|j$W1yz{-BlxddCG^LwY~bNe&PQg-tXp< delta 28050 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 diff --git a/libs/arm64-v8a/pdnsd b/libs/arm64-v8a/pdnsd new file mode 100755 index 0000000000000000000000000000000000000000..6fd98cae384b35c73f77952b832fbbef03924849 GIT binary patch literal 202752 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 MTV5dEHJ%3l52P_9TL1t6 literal 0 HcmV?d00001 diff --git a/libs/armeabi-v7a/libtun2socks.so b/libs/armeabi-v7a/libtun2socks.so index 041746943f11f0c4a58b58453d76d4fe7aad62c8..26b6d08d89578390c0d602d167669073b43ad4c4 100755 GIT binary patch delta 15423 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 delta 15270 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 bJJ{|_e{w5bgl|Q#tufPg%`d-0-_ZXD+NOq! diff --git a/libs/armeabi-v7a/pdnsd b/libs/armeabi-v7a/pdnsd new file mode 100755 index 0000000000000000000000000000000000000000..88d8c8507bb713218f8c522816b706c083a86a8f GIT binary patch literal 153252 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%0A=)O}&rd4sT-=6ltP442n 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 literal 0 HcmV?d00001 diff --git a/libs/armeabi/pdnsd b/libs/armeabi/pdnsd new file mode 100755 index 0000000000000000000000000000000000000000..902c4af4b0dc11c50d89ec753d9dcfd13faf1bdf GIT binary patch literal 161312 zcmb@vd3;k<`agbdnzo^o?n~NUYMK-*v_PR{Eu$p~SK5HGjh2FtZkR4WX^WPEV*z!j z;tVv1ZBhk=aZpfEVFni*6lTV4oEyOTR0?C-Qo@MKb)|cL?{jmC*Uabpdwu`-rmrXO z=ecJ;=Q-y*XSwM^^A`#n$B~gw07)ZMidjfVHqct5qE3O?L`O7m(~@`+ga_1ZgyaAS zq{cH!0n`oh2t`AtMBQlIl$0Oa-6}#UkUos?xtFe0k<$BpbT)*L3rR#ym%7s&#Z;+C z%vK+bL`w5T(^%3|R|@#A4|S&>q+h-2LynA4BOEBvu#}b}yfXc^QG`$$iGND%=GwZl zbyJGV*H5V`Utd{PLu38rM_I-wIE_&_Q#sL3zQs=-?(rpS;6Qe%w!P_LCic@^g?sTh9^NPEqK&FZ#K^ z>LY(FF*N`pWNjqf1!}6K7ON+X?x!Alf8a&kUR{*BR?eueR^OIljlVA3eU-y&W@RQH_$shR1|Klfr z?k8XMlfU$nfAEw0{N!Ojc{CmL*@w1Iw4a>hC#U+!ll&gh2 zqAJR*sUfv>HEZREwbeD{>+9AcXl-3lN#&XnTjiSjHWk&BQZH3y>q+_gvbr_v>o!!A z+V%g7-?c^MRiwJkR#R3~x@O%bB)tadRQf&IwEh>> zmK4?2-3%{3exL~DSzok%Lv2-ASv9$@td8b=!`jlK&A;?WAD7C$*Ojd+soso2R8v^H zp&CV5`#?>3T^Wj6R#UTn11%t!4K-wKN!5m0)D?oPtETlJw19shX767FDg^w2q2(8>(cn+ExUttu87lqq&8#Sw@{pY&GQmo3Y3>TU57!)p0fD zYEgG(b)0*z$7oJrOcHAU-7H>@K_cf$iPXVJj4xogTw?q64X zAJqrIn)UT{w$hrPYYOE-HB^XF3=d%W~#&l@*EE97#b z;m{`Vh!$E;>tna`EJx-3(M)R<)MUHm=%mAGsf9K1I3u(WRhA>uBZ5!6>uNU3x{P4e53DajvzOJ~S6+&KQeJmo z4Z_#bC!6S#+WTsXs!@lmk?z0Qfy#Y~MAp)@<&xBGkW00;291e_G&s#{Es^U^PK!R1 zAE7g0@j}pl%GOoaZKm}DzNn&xoV*mY&4 zWKCIVQC$&y7uVL(!H>oUZAZT-uB|IANl%|#yMYSp7?vKdaf(k+to5$Pa<;XU{D_Gw4^KFwk#6BkNKu@5w!&2SN0++y`V8 z@HS8?s1)=Fs0uXl!LnTbl;hg~`mIkSj{%z)?+?{@u!%ivV5nvI0K+A~rJ%7)-pY`I z6|{&liqEgX*DyIo@tm@oK?NWi$OxkI`8LqwARVXzGz+v5q+GW{{D1lhQN-q(`3Z?- z&k_`Fp$dM49oe6tYqycT47#WDfBP8?j}w?@#nMiGlC6m3R`3B#ru!`;pNtVkfpfvn z0A(qjQI=UIN36#lXJ#Y#r83Z$k%mIyj?gn!g=nl{d_HYuz5ts~S8mJgF4^#xA zpWA&v)&a3iMan=apy{9upm0zch_jH71>Vbe3Xg*7L3E#t zma&Rq9mA~*A7;3V;a-Mq3=c6p%J4YDw;7&g_%Xu^3@I@-vKK$TLi3n87fc;arAhh6@=kXSj-CDZ?s;bqu#Me3;=b zhI<*dF+9ZZD8u6n-)4B0;l~UwFucU@3d1iM{=jgMp?WhbKf@S?Ji}Cm84R--&Shw3 zxRBv;hN~EsGOS`)$8amdhZ*i-xR+rY!$S;@GCa=kZH8wVe$4O!!%GaWF#M9?4-5wx zsvB7O8OAW=8KyGKV3^HtE<-cJg$x%nT+Xn7;VOn!hNTQ`467JcGpu7+&u}ZlMurbF z+{thk!`%$`GHhYk#_#~cLktfyJj(DG!{ZE3GJKoiX@+MRzR&Puh9biY4BHuAV(4ag zh2b@ZUow;!{=l%8;UGh@#n)bHh8l*U3?mrEFw`>S8R{6OGE8Hb!7!6yHp5vA=Q7M? zXlA&8;X;Os87^m7z;G2qE5lNTHilIUs~OfYtY^5DVI#wb8SZ4bi{WmDdl|McY-4zU z;UR{H86IVLjNx&HCmFuY@HE4-4Buz?F+-8z1%~YmFEMm8yu$Dr!!H?13}YVjwX>EX z&rruOm0G|mLsUxVLa}p2xE9JMHtd86k*i1 zQG_vjfZ`NF4pD@We3;@?LXJ{|aea&;jP&CaVa%SS2*dkriZcm0O%V&2vlM3&@;*fv z)gM!Yfh$skv3`N#uLx7uuiVVzfWSC1`(&OVR!m zVVGx9T#ojq_-nL3MJyENQoIN4Pq6^)PZ5iT1r!U>{uEcD{VA?O`%{DgUqEp++Mgnf ze=9{R+Mi+(+Mgm87gZEX(Eb!l(f$<6(Eb$HqWvk}hxVsvL;F)KNBdK(K>JgyMEg^$ zLi(KrbH=+G0-jDXD_yF3UA{HWN zDQ-slQ*1!{Q`~~~r??gEPw_#tKgHjm{V6_#_NUm0_NTZF?N4z#+MnVMv_Hj%(f$-4 zLHkpD6zxy(w`h0wq#m_t^x?&^vddb?+Y*C=?R;Clyu z_9H3yYYN`2;M*0vsNmmM@TV30Nd!e2NZmZg5Ry+cPjWs1z)e=s};OW!CMu4 zfr4MG;1?+PTm?T%!DlM?GzG6y@LB~Qq2M(No+$X<0Y&{Q_-hK@t>D`gyr|&cSMaA5 z{7D6WOu-*k@COupi-O;+;CCwcMg?E5;Hwq9O~G3ge1U>rtl$?Y_*?})OTlL<_%sEt zQ}9{^AEDqi3Z5wV-hM^>EBI>)-mT!<6}+h6-&gRb75qsBe@ww2R`3TDe2aqLt>AYm z_(la^ui&c{yiLJd6?}n$U##F4DEM3jKTE-9D)=-7uT$_^1s|c{H42_6_})H6{VVuu z3f`^Y+ZDX1;NMs9rxpB31%FJzA6D=O6nu+<->u+xD)>ePU$5Y+6}(NsTNQkPf?urQ z7by5#1wTu{XDawK1+P=^S_L1W;57=KDEQvqw|k@$YlORnMS@w7j{oCWvvBu|Q9IvR z6wC)S7dRd?PqNvC!WX0JwY;i%r6ZINY+mJ9@yu>vqRk{&nnP@(Ur;xPN#FJcKer}I&^&@6{>^tp!&k57NvG|M)DPmsPIB58Ms%Y<3hvDO@0zR=2d;2DpVx(_4e=0nV0WeH!`fl`gIHey;&L-SqD?!0{bgTUO_-k^Q78{QL@jwt4lo9NRH|uQ07%l~rO+tgfjq ztTxyjydJfy%4(I%AA=N$>o=Z9c$(&o&PA3*d3Vb3O;*Ggi}+S}uXX-h_A$~8Zy-Vz zdH&C(|CQxedAG@N%}~Vk%|Nu2<+TWsHpkYA)*mVT80ix)Hi=!c5aav=su4QW=>lPz zb_IW4uGf{?Ue7k6$-D?HHNi3=Z=xLcTt(dPBJM!c>{OoWRh~IU-zLONr@CbvyceO8 zEw|*|B8S?~Laijx((?%Q#jwE^lVz|z+DYzK5mh%wX1vUiOSsH+4s`V;j_d;N1sw)| zCy>eygP#a20A+)}*vXL$@YjxVmY20!TLh_CI=Th8ZQkaJ^Jlwl2W zb8z_oukC!gJ4Tuz*Vloo2HPV%t1n%a)>&`lsTQ`Nw$AXa!qd>hw=8exy)CEoyrSF_ zk<$9%|JK7X(kL(0irT9_P5jdRvgMV$SLE=A72!h={?6gc?v+9iH1V+Ig}fJJKSvaP zdi$fLxk$s;B0*>m+8SF147Ouq9bE8-Io zU(E19w^9>d8>X7bqaOadAMTd>;cqQF^LEN{*;rh(U%!aBz8*R=f6Teb5%H{4147PnDYDL4~bg^`lXGv^Dwvc#e+i_8|Y!D>TIs8JI&mYTd;Ikq}QYPE>% z&qDzQ^|)4{%Cg0*vD5ES_S$>7tgp03=8tYKw*=_u*wbLpw2pGn9Iil^r-wMhN@JVQ zX|@O?-Qya`!9=;u6Qoc34YulpFSN8SM>J!CT$lD9+J0j`TW(pN_iH&n?LwYOJJx?3Mr`#c3K=sHiwZD6Qn=& zEjl*$?cGAF@SJc&kWQTzdQaRX2m(nxeLRrgDeMt$;SU&Z5lzBcp1+r5aN?naUeD~Y zO$lkX7-`)=KysQjQXFfWCxlKfNU#X%u>p;DG*07nm|MlZ0|}beIp99(<8+~ND!r$q z6ZZ&r3iE}>1o!bsJ`N+oQbBESn4)=APNA`IULdcTx?6}()`%okDWCXv;&Yxd{P{qnrZLG+8y7YNWQe&m?f;NV-}aN&oS_G@fUrq-CTwhFP{U zq~lK<)9&BebS0Skl+(TBj%!<+JZ*Acd%>dn3AHxrRt9IN+f~_z$lQdrwqUnr?)Z!^ z+J`F0B#(HAtX)AScZ=EOB*QI^ZeE~o6)cvJJ)?GSF(=uat2B0EXc06{)BI@Bz|R+w zY}|B`KHxeakVzq^``rEse7rO;NG7PnR2w(D-vbvtmlDs%Iqd?M(`vkD-t9rRhmnj| z#W?3{O-bscP=`=!YYrZD;Z<9_V`-wx^g(<`t~2qX>0Eqt?oxrXljaiJI9_Gv3~GCV zQ!_o_$v}Ieb5u)6Ymj}k!y5<|1b^5O3EoiPsddl$KN@>rAb!@V8%9yA7v>9-^y ztvK;3Et&L{E6PnWW{TWQ>D~nCDQLnDp&eXv-;ViTxVX8gLEOyLFv<0~C&sy0;MK9t z)KIdQv&T8}1eHDBIm!`W*E*AelEP^H(Ygz=n@}6a`$^hZv_iZisfD%!X`UzOdG8I| zuqnA^UWB`HXB=|&hO3&NQBNjw;-d+Dp7_={M}qWpFG+jJ#py=>qV!Y;sf|l*-Bw|N zK{`HRVbif7eycgv7S8vq+6^6vMGuI?B*ihh&69YsU4ZKx^CsF>OEV&2vJa zJErYLLFJBdIs~2%FgOL0p%bH=nLM#aJ7@Epy~Jij2@Sj^E5MF%-XU;efXyl7jBUYKvub|YMH5<^jB^Of zgw^+2gq8QcZcK2Y54*B;R?{r4I#cWBrY{o;(3VGgEdsZja)0dQoI8wxF7CD&LEQ8i zVPB(Nvkh$mm+dxR@DN>qU*3Id3p4T}9S^cK9SgA7go_qAXKLudNns|R%&VQN?yZI9MY~AG5|Nv(cGA2Q^#<>*2Hx8n?8_6? zwdtv0-?*-NviRHhJA@WN&fAPm^Lfv0{5VS{Psa&$O1AzUAx6sSon<9y@nZJ40F0(w z4$oJah(Vp8&L(yppUA7Eqv*M#Tx9nwgqg^%M3|Kb6SH8fTgO9B>`_h*ZLP8gwgx$3 zodJ>_E&7c}bYtAvx;HVVFB42ANgLx-Xa4N>n#aF=59Fzc*NeSAc^&4ftG_R77XDz4 zcyX^V+WuEd;2!nv66E}B-g#k^{Ut*Op;D1K+)~DhdAD`oG(bUMcLzz zgjk6_*dB8v$o{4!v{}=<#T;#qc=3o~uRueG`sSk!B7HXy>{Pb|wi0`gvk>FiXlJPO zCvQM9ClaY^V6-F3Hfkbizt}yxHDpeRwNO|g#9{R`y}qVilQ~HhYkG|ju^zAgu6`z; zs){j98yjMswmD>GSaZ$h-NI{|BbvY4tg&V`>=kMnh$`HwGBpb{&dBDa^U1kax+hFp z>`baB>A@n=A6ZQ>UOt|;*&HRkIXuS6H)d^4)x72u$qgKT8Edx zhQg|)d&K9e?)#bBqtmfpQCe~*wS zggBNKL^c}<+^)ij4S8Sk&L+FySWS^#&nx7;)OZmo=OZV5n@cdDZ-hc zS|)^=V(pW$rajOVFRkvIg15urx_DGAM43RIGgiz@PImEl}nEf=C?-QujAHaOtFdbJsnH)hN8)pl%7B5na8d9y!^!ta_QC%87U}*8Y2F=SpZNjWzB? z&Q9}KEywEWjB&;~R9Uob-gFzgcJ+I`rGYr709Apa(1*-kulG$4)?&b)dN|?+k*gd@ z1TDm~xFcbRv6YtU734~;hcL|0q0((g;~p3KDatggrR663!WaK}3@fukiRH%lBkL)}749JlZH z<9#KLwU6W|;z%3Pyq~N!!=Bg|*y_vG_t+^3b;axtLcV@VP`X@&OQ85qi#oZ@NW|!_ zNVJ@<&Q&vMt-sbuo-zrWkcU9z;hoNVj%fMWe2~6H&`R$NE)#;}+TNq6?Fi(K!#GCu zB5q%(bOI?5F;1@aAX@9<&Q5|>wsihnd$C8T|4?cFP(X5!c+|qBwit=)<4!gIVdwUg zm}g=gACQv?`x1U<3~Y~U)k@n2p?y!KcZN7_;h)7grM45j6TO?bUhPcd$4D>qKb@yS zpPR);Nq-&WQvcYgHY^ch>;Z-t#~veTFYLUVe{&U=^CxZ0K9c@}>oMU~BRO{$N;jL= z^3!-)y1P(1XHqP3>Xdc!FA0irJryeD$>n;H>F8QnN0U0qK9lfoH?$D7b!(^8@LBSh z8L@lf_64M6wZ}=Dy`QLpLINg`&)#=yJHvrz-7%e+e6;iqEDa)_a^G_#!cKLT>JKa% zxo^cFrTbmbkNvH}fHoit#v1bXz(7!PgSZm&TVlPcy0G3@?X2HXeTJX!4sooq1oP($ zxYVEPWxQN3WBUu_dLg+Wdj0p#WZ*Z-E6PX3IiJ;{pu!;z?Yo$L9ggM(2(%iH7 zB|@|$AO!&_g#A}(pGFF5F0@@=D}-A{wFI})SpGYXH!z!*i9wbYqfXT9wz`Kg=hCraANG3Q#M+V0 z!K*NqggA@}?JN??Ic*RQSA8_9^sbGoMjX@c@@eNZ?IpVCR_v`xSp!Rj z(at1WnBAE;+7WGCDHNg}mYJiip-wI<)b70zJQ%xBjhw37nl|F*QfUoES#&)10&P(U z=`aR~T4`OsJSU0`SN`Q0ZF$m+Qj&E;C@U$XQnq}h<5A8>oueJl^IX07yh zS$@O)5|jS|xm-NLq?3?}#luW`71B8Ic_zImhm7k!$mHi_`C0b?COaT6auo_sTe#`x z3l7gGmu~6S@{YX2nR=u=VAV?805|>c{AVu}3j0vHM*UK*RZH~hGmjew5w02K(%SY| z{#CHYG8O$Eql2MUcmsPpMrbtbP-#jZ9bKMqpDd?k`l_o?*p7I3{&02*YN2>AL`U(H zfdHLWDjB3{Rb0N){E(%_w#A%iJ?(jr<#axB`l7gnNw-1D7wefc6Ou{1pGldJh}eLX zDv{EFb)KQ$CNAgn8<5w+jZb+Bg(Azk1zgJcf_igRKF=@DHXsKt^;O_my*V_qJfF&c zz}|yaN<^#PZ7E~Et@+Edv{H-gG6pVpS**;ZP(NTj47bPn?nC^GknTJ@;S7DY$Cnr6 zH<*`gT#4r<%iVeB3pShe80imZYNciUG>vNmOOP`sEJY&z(Tx{UFqizjD{CFazjVzr ze77ne?upwb8h%_wCaFb}j6^)(Zo!Jf47aze^m~gnix=o>!A3`y-?{VKz)%`dSzgRz*}Y&727^4c*BNr@B>yJbr8@$ zr<~d_)#j1Ud|A0qp|44+{N>BOxG)?LTtl0_a0f zFX(GfBA!=(>fv`a@GS6vQAJh(Pl5#SXW?%K+%iBDLDhIBg{sJ?07Cv9u9Exgdyvom zfOzrp?|9(9fPVrN<7H$WsBs^{8t7>TajnH%HxYF{Z-AiACl8o}V?r{2yX=}I9}@>1_V^8(N(0(5#lQj)y1a&g1RK#m zK6bQQW7}>FIoCpG$ysDv?ivl^D(mE?kqO_rqNKa&tnIp`Gg?|iHPn^Z$r;`%;tjo8 ztrRps^cG=^E>Cb+wNfy05rW)Q_7bFA-TSIM$_D5nrQ_b)k*>Gjmv162f|ehFwjIge zQq*8xo^{@u>npGLZ#OYK56z3-o~C~t_DN93p}a%+LGo!(q_o@n+`_Hq2pg) ze#D~Xw?G@(`_T_D3SH_CkPZwupjjH9g(EuPk4t?DKDQL{jdVPq_~gxy2m4ca8uIV` zDmjKT{XsJRrC%fCTm9iO{<$CPm~s^~?9Ki{;ZX}gU)1tBNc&B>W*+Q}mwxnayIJbl zUOHl8F9mxVl-u9CWkEg0#n<6GM2wgI$4hMS(k1WxatJl*N$0IwL{c6!r@{B(el?GM z2iNv4lA?uuMq~I*ZyL`*axk~GT~u-+-_-Rf*-uq(F8Ur;^{@w5c((DHO=wq zS&!5@qYx>5JWSi`C3!VB-m?(CJLLYa^Kgb+Jn>S69A<;}j+=Gy`Y_eJPx`dd+kI-} z)kViw7g`&da=vf()nCb@V7&AaR`CR(tb!pY;_k3)6sSV*4x<#ISuJw ztPbia6yhwIY-G#UAI^%Gl4X6j_eDuAZ|l`U;Z}sZ{pJWa9(s1Z`im>$&?;d)T0WJ{ zAMsL`9PWX>)509|;Rq1z^Ub%b$ZtS9(MKJiV#?$B9N@=55p)4`05l%%F$hOMS`ZyS zGM>cw)2~$IU*JCh-iE%P`7KArgHl0s9Jv$EU&fCV!~sKqt0j({)*rL|GjA!;O3$F~ zpcA6*YP@uEnD+2^>FwbU6g}KKB#-}ne?^^SmF4uD1=d=#dd{#q9HJ{aS3u`!CjThQ z1MX8y{))En7{Ux1zijV|tcr6)%E zL%#`H5s33I;(Fix5>g)NfhXOgrQBgMDadsgPa{~re4=w9_VCn5?{Rm1Ih{`hXvI&i zH!*q#iTkO~l$CN%FY4r^_90GM-%s6eu@5@Xg8U`gxM?a;i(2@0_{p2;1&VZrN8iNr zp5a1ax8*{C4kM)+W78kxRl_0oE;;r>>^G>z+x4%lqOoRm(lPc@uT~1_3zYj_>s4AC z^Ln(>s6N^kb2_!sV6RGcJL`TOaS~VfRa)MU+?(YZjFLV??;dk8Ub;3!Y$uR|FNbQ; zJ`;I*q8%ws8REv#{@99oroKLfFWQQq4OJ>yk%uoj2JGvNmp&dUyV;8(h6u*qdQWkl zT8>RKq)vIW{QNDCn^fXsSdG?tRza81KZn+P;^e(p;+p3fEo~oKC@k{OnIuYDE7!mj z4;?Yq_7)1cs40SWHe%NQ5cb9*)Qn@J_r{umSm~^{s3%|Ep^22<9Ae|H%hV&VXUB$q z)e|q(q711h!vjO}*cd_Qnl}d*dTwJ{^`5-)`!n`5sjc?BdxfC4+-a`CyzQ`Z`sqk9 zvD$lM{6M_42yw+rONXZ3Ec3oWs?m|CiQ8p2^HBOtx1F+E0Nkd^ZZn3)-E?b!8y%0w z@+&a!zl(c*jo)$P3-q)1KwqM7xk2q9+V8%|QIXYneiHZ`s2*g)^98_m;3ZHZ_@(HN zXW{P?koJ3yOa@H@kvS?d5%Et0T?IY%70#e%s|XK&1eAer2eFS9Da8%7Tx~}guVK|j zI{u2De14FYxqYxr&O4n4_`x@>I`YymZ%0bQgA0WX@O4`D_1D2CZ(Q}WOxJ9h&K>=5<-_D^caNx9Cqd!OF0X3yBy|rIn43lQWj=E!UT!M zOlpCYfEa#_7;Cp)lDpkCnnCm*Ua@)x#yjI{sHF z@zOekFo<*VOngw%X0whTgPg}p&*3TO8Z+4-X6J?Lef8S{OFaoGlC)%3_+;KSWdSVn zl*3v1`g+v5I{(96@HVd!Qe`T?Ee^j~sh4v6-Npjnusz^?`UZKjHxz79PG|2}X5kh&T1{BMxe z;0gGh;6DL2vaU7nLI*&w@-M4s=sF6mkY+%4@)< zQeH>HS-KK_^j=qsmM*gM)V1SNRU{K-%LdH?%?0Ix5Km{QZhucG+25nm{oYN;@7-ZP zdcSx$TP5#PM4Z@ujHKNvk_qEQV&Jepx&szZxY%ZU92g-wZEeQLOA%IB-+1#4UXIZ9L=}P_1`HMwW3rSlc(%F>Ga|^`@ z*tL1y+jusRf8O|`OMj%zm@1C5j>jn?NzZZx996YGZwwT~ra$!3kC} zf$sVfcLG1!mT#rG>~kf-WrbCL?B^5Zc#AgQcUNK?_6R#j14gMceUVb|kp77N$!Cm_ zI6o)pABpq~c#5?JIegiLygfO7>^mNsmwzKKUwL?b{MbKvR8L;>3}>lGR1?nmfm=au z?!;aPNOK~eJJx4VCDn+6 zdS9Pv`b(rNK|MVUw(nT9v&Io%4Jf+9`lxmLHcnT9J4z*1Llc)}*cNb1I;Hv5_(`Gd z?h1@U;!9+H0*zyS9}U~-BD$|U5thijNZkAg&=EVm%@%IK{EvF79i(A;Ty5|_sgL8` z#Q}WVRMdM~x9HoUD6zF6r3)zAYro})4O9c#i0kD)@Av#k-tS4|Pb_>Kr&S^Ly(SZ-RBdV^6f@)c~tjKv~Kc|V7r!&NlAy_l#j?)iI{q1*wT8z+W18Z5sS&KCq?7dp`4B+dd2h?&A|?hGg7*a`7XU<5_(*ZYm_q#B^hP68y|PYqh?l?lk`ch zHE>bOdynkSO0>~^LzG%P+O^z& z$4`iUDMqfLsVMaa*c~n`4|SqmE;e>K5_2sGb@{hlcc6wEy0m<(^uxdv5~1?_{hssT zQ{Jb%5h^YBEzz=X`b4Xu-}G-4_muZ>?gBYNsI&{;sqi_mp}gTpLzF7S^q+<#Re>Xhf5sSdd6|%^HB{>iCDkh2rqU+*?o_#P>vDU-v;4ILsvrOA1X{Kqul`)NG(Idd5_@_-T+QGc^_pzl z_8_#k{B@u}h?5$nrN=%GE#m<>etcFLM-mdDdd&p%VM`hu_)x9pm6SLq5_DkN5~;cIcbqeZCYztUQS z6*g|}6G&xBXRa`npTiqaFO#6>U`m}X^CwMuTBumFJLE+ z?^I=wOVOQV(s@y*e~WLZ=H`Clnb=U-P@6~3h<&Z`fjlBjMr$O?`Q;PSphr{r5VT0( zKqen2ogUU1jC|Jey+|t&Wj)d`+OMpyYM(_%`pL!Y%jlyKUgWQss-q3CyHG|gR_uAF02ImQLaQcCM+@Fik4-V_} z^8^zgvV1@C(cbgE)|;4xnpTTk)=yf>^}A~86N6r_Pf|ylrfrTkeODi)iZ<13jtqKj zbCf#7G_@hb^zG(R=xL<6rU6eI zF+7N;Tj|q)W<&mLz5&`iZ+Ia5z4(*HWjF&T;;tUFOvmn?ojqyLWU6Z#)MHWqZ+mFH z$1Cc6j9l+EJ<47{>)g`6u}70L9^?6zo^Z#x3aTsj_c%#gL2M5looDnc!amTf{?$FF zg>w(%{094*89Q*VX&Xn5gF+lSiw+|o-8cSuEDm-=`t~X>ZtnScbR}ZPmHQB1L|eHn zQ^rX>Q5fR}t}Mb0vBc_(o(M=kTnVQ$!%^J+z`PJA9j4mnn$=_M3BmL4JRz8^G=|3t zp1-nE=*H^z^bj2%W*{%`G;-t^=tWR7XgQuooEU?hL>;fmjFVm;>c$MEy4-E!a=NV= ztf0?84itmHQTHQ55vL-6uMGX@IW$p4c7e8oB2GlzjAIX0=CW0RIU-o>F4tFl7XFcT zWrQlrZVb6N3Ng_bem4}%;@pNfb$lwG?Hc+4^Sl-D%>qpZRiB7o7{7?-?m_cpIfunV z-Q}q>xUBA?AU9_?STq3|shJul-H+$Wl%$S>NdFsG3BJF?s;%3m$wVk?cR5N{6ekHo z)wmBBgfvugI*|(_f054QAwxw3(lHdP-6Lt3hiGg!T(pjUaB-MBONtB?h&RVj94C!M zjL%F^5eG;*5x=NEmF79_t{uk?5zUN;%waga^)C`e~MA%fs9&WJ-Bn4-+Qu0tH zA0hQ&tQ#X%B9&{d>qw;ssbun%$nV!!t58de=mtP3eQ8~m<|wx#8JjX!oI+DulJH4)F! z#Kl&vl}rkANmdTGkz$~o%iv1V<3+7C67dwkRT9(ST74=EuF1Wv z?pse?`B_hd^{QvF^?Oe+e4Y2KzEwr;N8aaxCWDee5ujc?|9Q<&y71v+WSp;Vf?R35 zT4A|2VjQGxF=vprK%BI8P+mI2mQ zm8=61;&fg!eHK4~&&PPUXmEX+ zX3t^PpM{mhz2ZC}LdqI$G;lLJ$bRE0aTZFS_yn2wwRjP`d@5HGEYWLX_9D6;PILYF z05Mb+9VxnwyabEa%O@)O*c}(sSs%MJFaaUZZ)VV0;~xY0xZxIU9f#fe1;R3GoODH= zP2Lztui&!Mi*>SJ+`zc0?;j8RQs1ezFUAcus_oC?{DtQISyu$cmyw)5=Zdg!<8ZqT z+DKgUJ>DDN4H-RYa_@e6;Lo1-(LT+fOi&bPaJ-6K0DTCey8I0AZcxOD7^c&KuBbe^ zUl<|94@8{u-dKuJ`bRNBl7_lbCn}erlB9nphM>N1i%{N8y)J4j8tlqp2c}}PIjJ%N z_s2S+?-7W1@m8E0r>KZHPDK`g_uY9ueLS>2m=ELk;Oq_ehcnb-X+jyFja$$C(3&{O z-9HN}nepO8%))W79W+j&-?ELv?fC5J4_fDJ8=V{F8nEURZ7F)IXrL&kcuVnH#RJ7& zL#F<%j@fRo~~mndLF5^q!~57KoenrDjcboK)4Hmi&{8>c)LIFQMb%tP`dtHBWRM z!Tg2b2}zfGaNjvzjI^`~Mdl{54)<&$#5BYii#Y%3#p$pb1m#O*1#9fcdsZ+L(8scQ%`fG`_-dp(*H-Wx8j=F~`gnwkRn zCSkYG5u9;B%?I5~Lk<76-b$M`(PpJ7{owkhf=r1PZ{z3kZE`NCk7D>pN~~l)W+A=* z>8rH0Z++qZutUf&L~PbQ6aO+cxp zp;Tx3mf@YcxzeXQH9Rd*iiX+S9vxyDMNH6wg9mIEp?LaRR+zLX@b%+}w@R zj7af-F<1=E3(cpe4h`nf=${|;>d+Ja<&8K+Y!TAM{_CFLykO=Y1oyXkzxM2{hs||A zhYpC}ECBx)_;KKS74IXg!@VmyitWVe-6&S(tHw8&_Xw%(=B7Afvg@*~0+{GZ!s`A! z_9q%~D*$^8mk+w>4#RaVor%?=KE=@#iPO&Q?(`Z|1joNk#(RM8J&>>>Z&_ zE8jFmUUt|}FBAWXm@Au-jbFKFh%a1~P1u6?G}*WucfosH^xi^J<$j~-Vjjk0;yZ12 zJ>(YTxtgTU6r(DiGG<>i<(uzRjcYLP7Jg$+M2=&Pk+28$2us0*x)RD4pj}-kmn28vM=^TTb7yWZpq!AdVQy-qP*VFED)W;94lS%(s&Cz%RIw3 zUc=i^hQ$6jNDXi`s1WobWIFD(TBH+O%!_an&G-IET1q}{qCaWb zh5eak{r}*e(m+v??QQc?QjB|3l|oK2K_46_egfxpWwtczZ~P6X))j*9-1@wHZmosg z;Y3eK>3u{#w}!pZn=kCZzSNdt-%Ob7YQ&tLj=5OpdWhNt()`|>il>D%eY1S$@@+G{ zfi+O>+k-jSbxQd4FZx$4X3@>&Lf9trdOyQlz85{Uu`hVt*tJ{q$`!-Q(yVe^?mD^ZcJk8bWMGh}W<~N_UgeT^V>& z<~r`Ea9P)_vC{qC_?_AZ9|U%VLS`)OHsqOG~xVx>F1WHNDW@eqT-IuCcxNJ{Vext*(qY75H3A6yw{@{{})d$MwvZ*#PF6pU$k~wge|ypw?oLW&U5!B z`R*UnGmE=1#uNZQOjeNt7<0lPAKrxXhFTv|dn+6A;X3*rsBf=xUFQ_s&Md^6B%#yr z`#8Eic(+hDH#m)4`k>Pwk1#5|lkPLRYC5@0^$c}(?)-0DG)LCH9r7%9SLaIDP%E0o z|O`-dRuGyVrJV`ku=yHN5kV~67={bN#RHeSu#LdVs2DnOvvU+ZM zSv5CRJx!gp(|G+-DRyv@nqJ4={#!OK>n&>tZmM?Uc3x15uQm1!bJ$f%r@7Uyly^># zxl`)#1DWExH+O#B?kR=_+gn9{M4w8)tl5B(=?~xw1>CYxXpJDuDcUJ?3$gCm<#aUO zg}L%xD)Yx565|N5bOZjf;nilu^tU{ zd-v5GyzN8Bh?lTyGSh|A{oXAVzVVW{dU~eGV_vxQ{?O+=8r_+z1%evC4xpjT0Z`(=7A33Jl!!_RlOL-u8)rBb-0nf^SOF^BFTE3|0*3#LMuELfG z)cW|sMQ2@dv0lGNo_AX@bKWtyZT`P6a`gQU*K2Ot8@kOjo(|V4;TkOPU>ALpz~_F- zy$bJfZD=Bs$GKDpp%({&BQE&d{^sU%xyD~wf$)<`&mVRCTfyI6m|R{z8EKEl9*T~> zQ5-9c8hq6FdB=t(>fU)F&BoDQ?t0#>;z#pjJePG&8(q&~r?bzMX}G@1n?6B&-B=~A zJNJEJkSo~DP33ZOwODD2G~5jrNeP!KpgH%7CahozF9e|X-6JMqmA+hbG&Ki@Tv%hP zpMo6RN^K6WHdgvz;I~GhW2zkYBE(%NPB@ol`zbMy#-7F9c3Mj&tHc1T3VgBWAa<=B zd+dcBh&@V-Zn(rq?*27;46rL{@@X2LJc8JF!%e-$f{CD6j60nQnjf4#WU)?lV3D{c?qhGZMUtsTOGNiGi)}( z(%L_QJ*r^T&&A--Pl?`Gq{eBcX`5CN)5)RUQ)enLQ>W9D%Zzcb;qkt|`qp*E(CkTx z!4qRHpQ%VnSh<2)%tb=0wYBLDQ|mTvnmYS6<2No-)2FcSej55aX4}v48xVA_EC_jV z;~(72IuXwDGX{GfF)T;LgX-h}oHU!75=`^91uJq=JEY^y$p_}mLdpIywAO@~xm!$vuDHc9iqxZq()iv}bY8j8POTRgW))|_H4hng9VJ{cbjC9odFhY9 zy`C7lZ${t$u3LEeIDHrO4BkmK;EmLI_G%U*5p8a~Rf-&aF@RP46ymCI6GM({g{*he z+nAi*d*c(d?KH8Jg<0dG=YzC`@4>pAhW%I$dpp|27jm5(k|5-(2synY4LZB3H;||I zE=M#&9GvGczzTNYr0_|%>6mZ5EuEr%1^A`6E~($^(4v;XYuIz+UP`Z?XsE2N#0gEy z*l>yS`s(tDfk3pB3APfM^qz~1`v~>$k3nC~9`cn+-0LBeJ{9-D<%hvT_}(zs=E=h8 z4@v(}d=+bQE~^!{=6m|hG=YAR>$Fc zrvyDcL(v+Zfm~r^$Ag*AAZ*xo<|Q$mvRsoF0SwM8MsYhr6$To<5#xdF0qOfol91?Aep_IW96u zE3c$UN*Yo~>gVt_)dFGY#(HlMpQvcL5bXB`-b_{X$}IS<8X)7<$=5{=_n@gwO>mZ- zf;YxTNz*Y8;Oqyh?-YLM#sd5jOM3?mQ8}Pa{*UV%YCUt{U5xwmU4rkRWAB5c6L(<6 zu#7mgjmM!+6K}b^)j-B^x3&nu#xdfvM%6i!V5sJ@ON7-4S@nkM+WL~}Kh-~99grO` zJy-K0?Dl72vE#N0Z>Uz|cN?TrnFi{g?jQQzOZNRf)UrkNmjdFP^p_eO0^VfjV_RB< zbe!>o@pfSpS|O-cjef8hBUFGj*11G5Srf5y9xH9fJLGhKB?)8Z?P8)$Z{@MS##-a3bO@sYTSk3$)WA9^G-4# z@8X1EzDKT#Xg*&Tk9qnra*q`gEZ@s^*4Oy`0_?lnr{Z+ngfzpDxPN-^%P zgJ>Pm-*BM6;6Ux@ZI&nH{upR)WPOc@54xj{sPS7I3vr^Lv#DFdrN#J#E}R?V_j^jP z+DyUNnuy;yc&`HMTYC4vtxB1K73MA>bf#}_p-J9b2oTo_O-*6OJ6zaZn5mw&!zf{f zRJYRor*ocXG56q2F3f__{l)p^u-Bq1S0+Ydca5!;TrKX3rkIq`xrwG?>>X$7ov?3% z#OGFdk!EEV=F@YwuBmu$MfrS%{QT~&JM&8rV`L?M^`m5=CD1|Nx6;}|G8)8(e3pZnvh3WnkCSROP?+fhHtEgtwdbYI;s6eKK*y+6ufQb zTX&4_%D|17q@-IhGHVQ>Gs$>|Fy0;5ItjOOUFDApkrkIQ2afCHumXF0K6i-#%Y;cm z#Ff-J--a6*7jNxsE`Jg_X0)pGiP#mOHBDS$o!kud%sb~3*V)eC$>b8(WfZzAIucq6 z=$yS&*a2T3iFOmw@7QLvc6z25Lh#15Z$IRt&QRFRhp;bH+%(1>WY-~wcrVrvn&K2V zL!Nn!5WL5M+h1n)X(17MvkGJOzwu7fE)d;=sRjm5A(!6jq^DKC64k9M3dn@nqDpt9 zNsAn+#_wzjGRC_ikl)E-gzmAX2%}oe)oG2lx+09@M2oE+x25V0zk{X!OhSxwaOhEE zVn=aPkdvFK&I+=tvFok22je@~9^%A3jE?e7n%++AYp7d0D()>Hldj$B zJi|A_1{MpI*waenk2EFlTI205T36Mm2U=S*a3YY%)4UQ_e&-mc=1DTX6*qlW8tLBu zZs85#R_xx2t~RA9j{=Ot#+K#Ue~VJ6|qZ$@+IwBx(h8K&ceyr z@C~saEs?FBF3i8&F_*tf&^%pXd!gwF_Wa16*_dMv!5+dXvte?1q&h(;lSf7i1@=)9VOlZoLQTQTYo@jq8-9UaAKSd4Ue@N>^R>t|PK zeg4PYU7>cg6le^OHf14>qwWXLBU}Ybg@2Tfu9yZbJA%Efr*RL4=%b*KhulVt|EiA1 z%hAU!o2)8Bu^dkCQ5m8UKG~Ckn?u7l=EqP5WFki zsCJEVTvmN11`uimsXV}vuy<8mKqG^qm4)-?V-G#TVUb(7)?#y*%=Lfbn6}(>_Qn4MS zRq?v=?MBt5$I5p@(ib^{H5WKN!CRtBjYBuyr?}vu7MV)yMAV z`QkG@&*0Zj9^GcLmU`|$uWP!R&KF?6=QGSKtv$1Cbv+tr=&QKB6=Ki4N_(woo2uwz z&s6=v<$r)1cGx|c;O#R1>HkOCx4=bNrT@P(3|F}cm;=1PFr$WoilT;)g)qJen4(xA znhl~hT)ew2s1=p9ShkA{7BXgTR%_VBN?U_!E8FhvzT>48FD>_JyY0JKy>p-c_ndj> z1(o0ac7K2U9NshMJ@2_b=Q+>woaa2xK#)1!I1d)tUKk8ECmDY|_&U=E9@SvYHhS?+ zZ5(4ItKrD5Uj_|WuV+Gm?AQ2oz6qY!hA7eSAFkN#T7W7l&43Hf3=X<4T!x*V>yU1Jk#?y+RYt5x73NzZ~^L>3s>(}@*vfN#*5na+wh^j;&&>2oUx zW*++e7S7ZeZEjUvRZwbzp&T+rQcj<+ZggAOwDC%Wl;>jEHY zGpqOI2VK|)935osT~U&JQ`%2m_s~ASWsDTQwpT;e8;A2-aDtXisNoB1Hl)+O(*8tB zvvecJTNsmfk%zJTvAYVnstT**c6?}`Ke!#5a|A*vc(?Hty^rOjBc!8ey4)-{o`> z)(QCgIsKb$T?#l^f$$^3PYAt$xz7>KAUulS2k?9z!3fyejpt^BZ3qkSTaV{XT}?-Hz}YLIcw4@H8T9Ls){4kFXSBA;NqFJ_R| zh=pUPemVGtL}T89V4UD48lTgfOoSd@dFFj1?7vM~%)^Jklm$373N*#y-a_e-HZJHT z@b2J{intIV1039~;P4m2Qtv8Y&|CQJyCD5B0T*Z)om*_d`#I1lE8wz?yLOcuRdu@| ziC3gj%_emPtD>4st2xCUWfRkq2F&FZLvUWH;d85?IbG3Nb)>>8K8`a+^6N;2Thw_7 z7526z5LN?6p|%Uy(>tq)G)u)NSFva(Gvx*FYyptwxy5h~qgl?GsBNzh%U)pbE3J88 zKeD~cO?P8$yS-k&d?uWI2r|d9p#GVOck$#VByRUixr@(|cFE)5pz?vQ7*M)e*tKI) zb6ExM-K(H!A18ch)3N2rrny8m%%mrP8Vryn9gwW^%+#OxT=4t>;QT>vLNheEFszl_ z1d9^{P+`#*h^|PS(2N`Val(@}bs^JK#D(GBLKaH@J97MRp3#MYa*8!rkncX4?;%^% z75P3xzHd>|yWl8&?SI-5LUvb3ncBcx?glJu1b%x2&zlf_0De1z01GX+T6)N!TXX1cK-?3lY(RSeEW9Ln*FYO99vY%Sn4vUw z8OHEdjD^8+5a}HMJQ)p~l?U)~&?O+yc?kLlaYBJD(~yQ9T<<-IzK`>2*2Us}{-F&7 zvcmXe^f?%PPD)aILHZo$eIEC-pa&&Hd0~$mc}CGZWL%PxAc3CY6?b@B>9~+wF2JF# zEtgU-k93ch;X$*G!R<+M$1@)F5uMv4%LB!|xFy)iT|n+p{C#L$tniaJ)9{LQ2aW%L z_zRG#YOA1ugB*1ExDktnf6_%dG{&((j<@ zCZsR4epcIC+XlU*Qku34X?km{aNJWuAu|!@q283r31cc9RxSxmp;2Xr_u!cWJnaLa(p6fPwG^p*P^VL0$ z^_grb>@2kOEW+*1NMRiPW@XQEnmVZ`TDaetBb75~2c3Yt zY)|I~ddomq?1KFK`ZjKQ@gbZ%*69{1OaRQ2Ly7m+0(7(HWe>J z-`X~G;s!v2w#>K$^5S{6R8|Q-K2lgAjY)I2;)Xls^)~#C_6eE; z_cDaz&P1b<>ev1rIN{FXfW6!GL8cWLw_uZ!O70fJGG- zf^XI38;F#+vTw08BT0B$D!)x&8>cUUE+=Ct>5DN!TM@VL>av#C!}4R-BYljnRcq#a zZ2I{dn>P#mw8FmGs+gl{tJ|W7cx$9h*5FTT{To-mE%4S{n|G z(r)wFlq3DWh_7NU=-B1@L|CHwlAnqa&suBLQws0QO27ya2>ld!m!ExvtsARGD$(b_oFbC1oZGehb*Ov^Yt&|^(NF82WWJ8Cc;Uj()La@MG%&js?xN`WMjTw}MV5bB>SzSaAXVmXyP81>)xr zcP)dxcEq2>Q$YHCc-A3oMyN$th2R40wCd(TH*QD4dxaVC&p=m-^zsf;-}&9vAYC_b zUb&-FUdu)F&HdIBbfllbtWtU3`FpIrWVS9g_r500!AzR7+S;m7q4bvv)8k3m301A2 z@UN%uR)F?s$}$6*7=C^4^XTvM(zj#j`vulkT|8S~P_3RneMvn^=NI+*Q_7^2sgR7d zj%&iaZZBx#zE!tEBeNVW8O!@{dW1k_9_J^ZE;6ftCs<7VMx8zVaavb|(1Tr_Ie(qi z50~l<_Yl=>bad`@#JmGu`>!k8urC$vW z4&_=-+QFY1hPxw#12os^VY$pS*IPY4j+~5Lgzy;6_3p4-7ig~Mdsd;wRZ@+0G}lXV zuDYzmdQxN4FpM1`tf9HuhUHpLa#^@HtO9teC1iSfW z@T_|x_?hV}v3`{fdz1el^4asrgNhk{v+9uZA6A^FJ_UQ}gQ^3Uu(oW##or-(gU~I7 zjxzWiL0mu}&oc<^cL2BJ*?{N!c&^0r7@pa9K7(fro(J(kOE0kh^~ zJ>pqbf^U$16k!s6pST6_#;pCuZ<&5|YErZg{DwUhw@5;!6>-rzr6yJg zwi8Q6^{^^B9iwzRt>v)+#muj)>oG?e)^+$BidEuoT@x@W+Lm4}*W4zxJJ3{$n%lV~ z_Q<@nOM&KEMQD3d)=FcTW?H;z+7#W4_*j9*uA^#-L+w*^VW|CM+wD^AsbozJ9V2yfq zVVtxVL{(k^%hZ2isL@%}92YwfR5PcOVx&ha|U@$7)LKMng$Yi1!@x5=$!9~~%V zV|WuA!KdM?G^us_Y3{WHeE&G4zC1ww3RWHdes5KRBQ0{JN;!YyCi}7Cf>*r3)!CmU zrS72LZ|pzXzZH0$Lnyfo`~OnNc0dCV`acKp-FPP88HW&q@Lefv8XdY{!ZE<~hX}%P;{D)@Hp=uZGbMuT$5tb zbzSg(Q1<{gCH)p&@k$6g8mC?n!hCQmvHV<03vibFVQqotmXvEBW`73qeQUvenF&lr zD4!4O)HCAOva9uhH+pXz2MxKOE%~r>7Y(cUM8XoHjTH9UeD|m#;A7wd^8s$_>l#YA zOt!KiMsRynH)^1*7HkOv&-y1|GU#^Z?Biau&c+E~jPNTjqd8`c5hi-yP96>&>%TLB&Vl`NAH z$FIov!m_z;3p98b%VXWlz8CU^u4r~`c61usRmc^|Ilm$LVo$#fy&iI3rS!H^F4=IU z?}aUOlhVKAr>1{u`G9mW7y~Ps#kIoM2%Mf8v*cWLioQQtW|_aeGSO(zW3B2MG|n~K*LJSW zy?c~lIhV)S))IQ`WOoeg)!EiyPQc%-hfPQFT;n+j{J4E}Na}8GsrD`XDt*qHIMiQ) z`a_@*|EB(9+%sCmZCj%rA=R-uT-%JiE!^uxpX+;Z!_ZOrDy$iA(;KI6TeXBc&zZOz z*E(vMX4r9U&R$o)j(F_()YHIauO;mW5bnagY;|3X@G|x{^1BMZSFks(9bY#AGZze< z;uxXHt(XCwV#{5Ve}uI5mjq(R#8DFjThH%7w~u_a##zp}Yjf8tnwh;h>+V|@jj@@= zlDb+vq$b94wkM!&JNAw&@(wK*Gb zB3&B;8!&{fxTl*LXImE|Omb;h|NLx~<|e_oy@uRLQ}8O`CgJlvhqm4 zYYHoKCln59>4?v>LMs=LOxnNHU4oNhV&R3}JHy<*2Q5=Gb4DGlYtR8#A@e3Z-rjD8kNF*~Oie#16ndaA_=d{}|x|QYu=z%W>_TKJU7APK!7)r+;(! z=5*TsIH&Dy-<*Ei9Z)xi&gmDhhI#dzKI!(&={f8^3$p{^Hzd{?Eo6J=sNz&H-j4&G z3s@1b8%h&1f*GcK5NBS{r%)k&ALuImSCGGS!xqXq@Zd;ufi5C;QW_S6R>He~Hzv-C z&dMi>J6Fx1V~{V6!QX5%Anzw|P0kz$RFl2=XTbDj{@KJ#$P%_y!^fRa<{*AG1B7<; z-sOYnmMbATo%VhmZeaNOzDVkO9#$CB;)D8lw{L}&^NZ*zpW-f|&wE_APGVGG{SpbuOK;YN^$beWTSA=~{iqMQ4n!u%5~>lw8B(zx*~Q}=_=Ez)2m`Dw*z(oxfSVv+{u94`B}NE{jj?hrILB*7y)+Y zJFkV^oZ1M?UOhCu$ybj$9GJT+vECv&0tDxVyZv+b8{{K!du7fXIu0bK2yDY;N2b96 zdf$A`DgM#>>HvX30*l{N!N0%-1(OSl5~R+J&P?Fz6U9e~gcBP7xvQPE`*5b}TZd*D)&uF_38X0>L=kL!=>vqstCAW13oW7Mf!RqUgQV8+F4uI67 zRLpHAommU;G{LVi)~{32uo4#zL<_%hzsogW$1p)-8Hi}$n?8YI*f@qch38I$!($j` z34%?{FzpD2c!qf<2EOPM873RyM}!4PS0V4qc(;T_I?DMFQ5{+U)K8?VJo>c{(Y3A=p7IRU zQIbm581ae)T$0+zjRSo`Qda4iWFz!X$ zH<(9bmb0Q1bGV%Atjt~a8sx^M(i*9Sl$zkSSKX!8%;rM-&>AV_eo838EdvKM2?B)s zy$#TQBj26yl2u>EG0hz{ist%tIkjGKDea@eq7YU~t6mAK%l=j0QBwx2?aO&H_Py-2 zBqmC{HDaR0C83c2-C;kw4&{i8i-yM;(rzf52TBGGpW}T!brQfVAk8 zG{44cT6BDb7RAdgDxocMR=i=&txW`tPiC>){@?9OxcdM&C3xt#%?GL9IJZcUIv-kH zC0fQbPM5DgrB*aU+qSl&rn5Q-y0v64*=BX%jDpnqrMs?n_6DzLw|Ca64Ym!ijfUI! zAL&J8Cj36;IjI(tKD5o0PXuB+V!jYhBdPg*W) z+Q28l|83XhZ2nz$n=@DH-#P3IWY=|&Gc!x9RmslYPzQK>LaOaBtnhs4P)-1T1)gjI zj+}+?4e(?K!sZnCph;#Ja7T<5!G_-llNd&gv{}f12H_EeTI5YecptcQD?;n_z||-d zBg?GPF-#l+!M6wS`+exf{HI}~hGDj?pG{{#Dg4z%T0R>sXU3^PP8DYAcH3B^x!o-#%N)scli4G89c^BHUM|I$I>rWP*V}!R z#y)PG?oIvYz_t5ugUt!cA&hBuEzxUoifNRF@QTYE>Fjzgg!*u}3|kng7w2-5AnO_} zm^=)zw{=^Du+*Vok7MT~?c;IhYI?e&ODR0;e!j?7y_|Wl%v|14IfbTecf+d+-reFP zH^_?hM0!fTdf9m`%`wL2!?347DQ8d&`tPc?D-Qi4BLp1A@N-ge+TnokEM* zf)+_n>L;*)P=Y-yBy|^eYa!us%<2#H<)C|sZ3Kd!zOy_4iwK}qO@wQj#uC2CCH|Sf z1^Tnve)ZVnPKlR{{TPYjRYG!o?Z|sXJ$4U2PJIuWi>E>5ec~#z0q{g} zCB7dm1YI!;K73#8^5gsc4ubEuSG?}$G123v?4(2oZE=9mcon`LEnK>S%l4HxS1xg* ze+Q}91=&dp&Nzr&R~Me|Kn6nS(XZ`Z?-0&>-FfBA#k2n38sJUXRsmFGQn>ic)hXf5 z71jmZ>}8-r#(O*II-ZDo*km2+0W%CA0gEzQZGjVBfsSxL2U#-Y>!ja9(7NdwF1~Zs zNPN7r!XvJbTeaAILEf`QYE`Jzs`DO&Hoa~ebak(TF6B1kl~DT`h1%02KT-;(Pp zmRseqE#v%aN3qA>{y)e$XCbE_1NGS6gmsM3!hJ4BZ9rt!#(?lG8w0{#-zaRny8pkC zzrRkdsnh1KX9zob#LaR}#ju(V*!=J}1krC+V-LXWRye8V383@=l!$h0LOV909h-zr zSGS`;F8!3P(mF zd|j?nZBuFkBD1!l&aJ3(>vp5Cm1&O4V&fGp1WN~{`mpqmght{g4|v2T&%2x-R}HP( zy;tEXH9PXU^@tBR{kY^F=Oqc^*EwOCbKJAoX?~O_!coFhg0}(v3~>I{<4{a{$5=u@ zYm+@WK(LQE3O7jke(E2Z>q`=JM>&1`oL}k}5SG62NS$$`j}n;aQlyq(?+ej1aG$Ds zbjRlVIklafSxxpca!T>NC1Co{jus`2)e1URPxfPVyTd2U?q9$?S48OJZF=x>E*~y- zz$T$b{Iz>%1b=ccx+EFH`|x|`D*yV3mM}h98^ofdvzCF4mcuwFnA+`4Q(RICsm{lX z(>5wH$Eo*2s;PuV-w??Mu%A4^u3;VGKRq7tvP&ng#l$Pe2Z{WRQ99fuzH=m)e8v$D!FzAgX%dNS%Hh2AN zRt@NdUWq6EzXHtQP?8EI zDdm!?T)8!^D9H%ggUY@@Ys3(ltQWGLCAhPI;GYG+hwDmd$F;Mt$A(#0MP`Aq%mK%C z2{gwgndZ38>ElE^VvviBfkA3{;x#QVxTfVw;SUmzs}urUgbJIdon7;oKYra%g|KLz>tqZcSWPXXWsAehH~n3rCF~=3YIqn#kye(rBS*gtA{oi3FRwacY)R6Klv_A2)0sHjX%Z(ZXah`pE0) z|IcCEE#~1Y*$3lW9WO~RehPTDj9MgyJy&;~5qhbxABi+#>xlmXd%4;{Mhy2$=nDAa zsyzYrnmyN!Sb^KeO)7=sb`z{~oG$CE^ywNt+fQ&&o`j1I{8#Po_V`*q#&NII`YldJ z^^W3uCC^(cwVjoRv!daHBzOI${vo)F`X5H|Q9#?d)w%1J_mdtzCiO7znjWqnp@*kj zewg^)wp{9=PxmpaUztt%m@oA)gOXx{Z`oAeH6CuJYf^ z_$?m)jBmGRN@LdLh=W`gdyQ>Q4Z&0O#!0ZDU+aDm8aJ!;X)_Li+wqF0oMcQCQmgB) z8IykZwX;57ZgmCa`1NwDj|{`~E2%_uI7TA4ELu3}4wc4nIg#l?PW(H-rut#hn#Y{) za#OI*$^N|+vV%H=ud$Z@o3VJ$?H`MuZ9URhlsdZo&?(h<8|rM8*25B)Z#{g7U9c7F zfwXC!(H)ib+fgfV)<>022Jq0LKXmXpUQ{;FN=-|bg! zv0U!WZ*4D2z4?yNhq&*hfX(=yoW8aj(RMY_+d$i`4v#p^M&@-4Z8LEHHPC2-SL>_s z-wLVCN@1z3#Xm>T^Ce}zO{GP1(L1>Zl!lKIIlwR1)BqQYr+q z%!>}4O~JN+>p_{zFhZ_=qT0;4#AK|abldRtTsF(MH-AJW-wIeIy|%TmHy}f&zqJu^ zYhQ7b6}3%j?H@ohM?+pu_ARt+gwh@yp)}n8NhwHPoc!oqvg0d+cn3M@Q3z_svixOp z>$RQL`!EvqwCv5aY)EHq*S2)&2xXtJ`=Rmg6sy-sEnPxOE0#+8Y=qJ#k5JkkxwO}4 zY1^gJ(yc=~Uz3ga-x#jf&;M?bXJ!c{QT%z(5&ANk})5Y_{Td&=*h>9YiBUS9+)Nz)086pm+A)X=a3SYKpXTFlZ89l zA5g#9L?_~BcRyV{j8N)L!7iu}=HOJ?s4LR*YM^55LSNfEVdbCfgu1P{>mQbBaD|ZL z8Qucl$oR){4MswZR<5J{Un}*$aD@KPAEEy*QqGs`$(c4E?eHsUF6Ytm$Q?SueI$-h zo@RvdcG~=KrlgSZYpJwkTH07zngYDtwNPsx#z*?s*PT*n3V2K+>+2q=G!b+ve8G#9p$ zeGqgA{u&AG$>5%6sRTjOJpzF`sx#Eab?DDPXDE-uJ$hjw!M7NX@v!NbNF~@Ye2?}N zd?S`n&B$g>U(})J^?i`IuK*89Eb;lyiHL3a6r87#bJ>%V|$5w^~xR1Y!9HiMo0RUbs4zB^>DwV7JAFj zu^PUkHQI^PjIp%#H)w~j%pTeT=z;dVBh{bkCX_aIQHiqKO=Y}3OcN!%4l5(Rki_J+E<)C^g`CL4>b+)!)ZB^%#n-`>vD45!!rM+mc2#{zTE?@AnQ2JrL&{Q;!lx&OrC)@0y4@J2jS`xXcGlv{V?myL z`c(!S&>ba^J9PmTUx}h+b)pU)GkjVCrxX6cK~Dg7REXCMEv%T{2Tg$`+zDgsZHqy9 zMR>meet7}DaY8f&98S4Y850X##<%np`j6FP3JWl5QNl&S`Jo3-cu!!&zHpzYiV`06 zY@=EijL_xvQJVMCllMC0c*~s*pMZp(dmS66}+(IS#x3PwFR+9@}>>?vn zyHemKXI5XHt~`lWwp0jCAtI z2py0^VNYmL?1dN8b@|A3zntrL_6BXPu>>bYrx=&`8|d6KmN&a^rjVxY&19#-ZuMHy zddsZ70%HG17qGDaXF!Bf35DN|xL%)3!*}vS?6nd7?n*2$@LE`De8})?*uDSH zC=5bve+hk^ZryZHGr5L+oU?Www~|vXXvH0lX|NYc@WMf?wI_S#LpRDLenu%IMrd*6 zbL5P(qlV}T)Y%U>=JYSV=BYnuZvgp>#ww5Q@crzrqCY6LZ9bf zgnz?5h)E;#X@lI-`{h2xjM%4gIcGKcMCi|nuu9+(SGkm+K>utp{nxW{b?cv|t)EO= z|JQCZA2DcsGg{B^pY>fkAEV_KrP8)D{IR}~X2UI=yhFe9ik1h`mVacK1q*9-Xu&i{ z)V)hw2|0z@;1W0Dbdva*t>!~=&9K_<7LU2e?1ek;k@L=%WEw89+>=||#&y=1xqCCn zcy9)k2TwgK;ibs(NM9ZB>uG3-Fnm>Cy%Z0HRYkr$fQ`#dR3(N36Q5&*c36w*s6GRW z?JC&Q!HpDru^Bso8F6^30G^oTzOmX-tx6?tZ!6BOC7QsUm0?1cQ$u9qmdm(r9AI3Q zJc=zXcvr2;e6u=A_{4G3`Wbb;c1?6|0mQn*1MUELKgDgCYDQ;+%_agRZt)h^e9k6* z?{$er59#X@jyZB)PvNAPoGG}(em8m7=(s_C_ksNGOX-Zpk15E`MW}`pr*lIf^6R*!M>xgxI`s9#W^eHa}Kc|79VZmz39UjPXYI5vHt&Qj=V4H)#F!c#?XUt`3Qwx$;~e zzENzKidD(*Ab+W=_afojF1f`XkE8m0@%cjHJzUGG*~6Kgl~KZ2NPf-$hGuVoUvN_v zds>>W3g{82VNuT}7P(#GLMMT@dG3M!VhSmL?^WXz2X@e*y$orhr2sd48OzJP1U8?r z5xZc4(1dh|he6FVmd}xH6DPO{_D&hdt;&Ptn@C}aSHqr0dIHKn>w1IC_7ghD*a@^~ zY3(jC#@UI{a*MM)6BBVNFMQ}B+AtpRV{i~YsZFFX1=a+yD?w`G5$^=tJa-i=wmW_g z9P!-%`TGyx(9X&`VR_aje&vGx7W+Chb@H)?5*_`E1NHD2M_}gZ{wE};KQ*uyH%`eN zWB7gnx6fP{93(d|V-3B7oz;mo(%#m;Tgu-t5Zh?4eiWAG9TlgH9hF!^meL-w8#3ch zmn9pwL#ovX+z%gu7w_pW!<7A^?UlPcX`De=X$9HF0n#7$#)UYg;n#Q%>`|;7N34} zG}R`vi!*Urod=shzwS z!peBqoeDU(0|^Q-pi)dx;iyYLMp%@cf@5 z&yG|DqZo#DdL3WMJ*|{_`YU^Y)(xC?PJVN{^u}mEBd0Bp(xCSV-L`jde#E5DzQjOk zGbDX&g`Z6#k7p(v?U1GGRQR{KPLlF^i(%RiqVetr_Wg$c=t zHk#v!*N!qnd{U{g*kCd~W>Cz^tyRnjpLqx#Di6TRLUFI3N(=y%NNB|B!J|^!;BU;8 zhV!>TVCmC*AuKjTYeR+KI_%Xi6f4=!%Id3p7%URDq5w_O`}^?z_w@an^84pKC#?$Y zExOq?pDy*{v?73gAEzs$vF6EsMNahYf(*hT?sS`^x}D;?&~5k8h^K77lT(jVjdz#$ zk?k=#?TDQ7ZQCPq>Ond6HQVeB4?xf60ZGrsDISyGJ!`vH`ob$d?c6TM_c`n3lD5ma zAGawpqf_l7(fecg!hvE)3KEUvhWYk2YRngrSDeA=473lKP+^Q6>$Rl>+OHww4st*0 z))bLByp`_ImHNm5fs@SHCa2DjQ#spha_U4mHP==m zrzXp(nYIOTYOI_(-gb+e8X~7A*b3xSx6D;W*=~|kf0R>I7~8PP@zlpXe3=(z%VVsR z%5#c8di_|yDV~+Sbc$B*R6uXPb*fzINAkNa?<6_(Ejjfs-U)K*t8(f|uRzu<*6|P6 zr?um8A8MR}xeiaV{vCMtG1hPf_VM-D-(MVycP#8uU_GZHlpyViiP+N-&Rqwa(h2a< zgtVIwwjysE@WAJZup5N0ai!NHrFq42$6w|6QpXo^-dS=9^Sz(Qsp)d+9PbBmszy$o z?tNEI9V4e+@9mUR!{k)f`$sv|D{-VwakTeV?ln36GUaLsUE;AhMWy$}Veq@%-Y(_y zilY6n9RHX7c{%>A{aHCaV1GuA|J{C2j(1^~ARdCkwOOnxHB|Tnr#3#hPPbp;V^Fb& zAlV;UJ9F%j!am%9pTdr3Z-n(rv-7t_Oj8!<8Q2fdJHO>#cs z+=-m&a?WRIPABYR6m#*3@CfC+m+qDDhoEBO7-1oB+%_K$EL4LoIh>ihIugG9pgn{2 z@GIb&Ulsc(@$J}Q(>+^;welO=#$mtukbfQWuN#&>)>AVq$0?g}*ssrQYlr>%z*afz z*W0#=VZYu$$tzLv%3&oBx|a{j@f@(q(C8gN{@aoN_F?(|;w~MQ<8j;KB7(gLRpJ~Z zHtC@q<6J1s8CJB!xjRL>yHHNOD5w75o+qbT3VA$klKWWVE|XKU?lG*M>QeLk(({`&IpK2?X;}bF4^D*1=C47yWxHe9Hn_$z+@i<$)6nBch zNL->*3~>+b2H(o5ZsK_c9EB+U%i|PZ^vsf>#|8g&KKVlw2Nzo{~cz+(RpJp6>yi;7o+;stD^^)+w@c6(|I;q1a2S% zqocGGbG8+E`S7W5VHCfXJvz^Nk9f1X@gWN@{(fG49hd|Kc+RdECSlc?1V>o?w_gdH;{?glK~=iBS3ZF$i9Cvi(7WI?2`$hHGIGr*U& zO5%?x7gpgRDL-V06xwXjZ@NqH&LD7yL!R zyE-iM`1rT)yUSsdaA$GQD`795E>j{;8#nq0W7@Jop^0bHrV(qXufc)_IKA#t?qo#( zn+E$?daIS~bB~wLl$YCb60Hqb$ z-hgl2@M+=H%62(4U5N!`HOh#?ZOT{IwHddpBez^l`BN?xL-)aKoDc7xCPOL8Ev<-z zz5=YSay6?K76%?aUAC}DVT#9IlaB9KfJSWO={Lx0LK|-Dx&@`TqVx#Z-!FiDF!*uE zrDf%oR?NjLokY%)6%oQ$-osYxC$<2iD*X^oY%==$vHu+5)TY>OpcY;NG{M4VZ?knK za-4?!vD5I3p4+9+DchFkmvFJ@p9Pj=mT^-sH&eh5#~2d~lZ!tqBUa)k^8w~PZHxx< zl0V5}!Z=^)*C9f1dUdoG6>7QJd(f((eqn-z+1_Q=JZ@5Ei0~p{mEpszA;Pa5!B+Ud zh7Xfq*xY*?DYcHjSR;fg*xyq<<+C4j44fI^wRR$$dK$P^a3~Mp*@)lsaDP4z@o@-Y z2zub&uMfaxBi=P3v>*`N{w#t4f!GEkmcfXfy-kZY7ysty{d#8^EV{sQoe%yxy4Mv4 zraH?MfIOnbL*SdVwyoP(T(wa35;PF?DouoN&Z9~m$Ai|uErv*84{ZMxus2&GgsomO z`oa8NWc1<9Ds~ltqD`=uL~P?Sx^x4ioAA+DV~7wYcu7gGqonherNiceIrnHctRP}G z;K2a15e96$u(+elNoQg~v6IdOv2n_1g0HZmoQYaadkVSYb-UKR1`dNjVA`eEjW|Wh zdfl)EaIyt(@~P*>;yFbDhn;2H^b8bW?FcgvqK}6xh!A?+1hYlJKf#rlEkc;=iGG_m z6Z}j(Kld#EzLAXF6= z78)5=pqL(`iVcg2j4cS*k{DL7MR5gozhAd|#{L2jB4~R9q#P=KIhPIJrWwX}tc>O# z7^~qvD_>Z+k9(o`KE3tmH=kqD zw^|g~y~Ck*0m#-x!d{}r6d_D=rx5G%mYv<(>vHN6m9g;Yrp!?C9d%2BVxk&SPcbI$ zH`?I(!u+UlQ3Yf3%DJ2Z+x27f^6P^)-NKD7_?l9rHO1w*IffORfsC=OMHhF>mAIlO!Wvq#aKs8Tj3hA-wc?VyT0 zDXs5Ymr12P3+aC=x6{g`>nx7C(jeyS4r^@i96r>{q%KFjjO7mNqQaP9MiUc7%HNGP zEwUCDF`6O#Y(6(%!jpSlDXlHm@$iip&t|hqfk^R*mYj-|NBc30*7C(!|8L@5FGp(2 zO4^p2tj_w5dNR%t@>h&yniX<(+QVX+E8V(%Th2C;D{fe>WGn1L(_Gm!m)bgk{?6xu zg{kiMtT}A>^yFqO8=jNWysdtAeX1!&8CDPj7wtaCO;n}6kQhE{Po#;luzh8qU(H}Su7QKEL?PWnpnV?TJxcdf0b_ZuFJ2d~(U=|@BzdCD z(NCGV6mxQ0E7w^U(QJl))7QFF;fV!O`R?t-;U?#{4mt;ks)VpatbB4-OUCZGZh3zB zrM;Vq!`tAc&(hKzVa7-{$HRAI0@iYT`{?F`_L%1CqHxogC${OY!_C{nxOY3Yc?s9S zrNE!c1T|RE9GZf3pN-fi8?u+gy&oVLlhzkY1ml zDCI8HB?c!(k(APgntD@1d;RIq$2R#_R5<@_eT*`ppj5^1qkEYtDt@w5+E-3RYJxew zEqu@8@SxsGXQXr z&SWDqc?z$Z`IFVysD!?4cvDSdT4RJsDZBv9mx+y$O-q=lJ!whN`-0))D6%bTpRx%y zz4kEB+zD@sFb4~JoENMf$e`7L@pFLPjey-}5L}4=f-riouMH~)nDJ?B;$C)d(%uMR zzazY2Y)W?lwUQdoOxhbVZnYmM) zirZBYfFG8wn(Use#&K%ZO$lMzjg=cOHztHVv$1buu2GexR%aWMTTj+MNHLWU{u74n zfe&p;3_H1rcqN0C&{@Z=sZZSw8$jfaLVD7Y{0=U1KYYsPG2N;xCOwf)Xe>!q0Ao*| z7kX=$)kG6*#91=~3kpt0>*@tPbzOz3EBO z@Z}t18jo?%9JvnOfg@W&pNxVpYO+%Q*%NJ!XuX4rPYQ;PT%0btJ=WC1>2P~xjLEAV zgLerVquWL|!uCmXc$?A`2dg*NwW)-8L@$Z|v{$n~rmbSvW5E~3Cgeq%W115iTRCrf z0v`y@q&#^#+V)V-XYiHW(6b*NBrn5q5wtqGj`R>~MSW^wt%$K~?jiDg#@y`wTR}y2HF}PNGAL=0MbIPC}D=oByx4b?O zWu5_lc^nu0RI)h&xSL1r(2detxql3$@qOJeZQsT@j;2U}$msvdKz&s9mmHf$p&N_nS|1=Oz zVduR8MfxNe@1U%%ng*j=oC(T~=<7MxX8dx)0I^Bbm;xCFaMMvdzk=){N8{UjYw_HT(28(ne?!frzdm{d8rarP zr14F*-*5eQIX7DWB;^dXSHsd$XcHNS&jyRR6cd?+2?K%98VWZjy`;qMyqtp+0bbVG zBY~!%y~&4XvnlNn=F8CKCF^S2;GV&uy2c#%47)IRJ!=yC%Rr%7AZ!t$~_a=z~;pEkZB=V zLCtKtqA6fcaPzn7(ALG^>@SPk(DI9x*9OU42f=H1IczhAdo7@&#KdK-Wyh*6ZI}o}*WCnPm7E%1(6`0)3E3^f> zV)NHp-iLpYDg0>2Q_^|mxTamDMooSwd{H+WA57p2-W{vVGbfxcI5jplkIa@r>z^-J zO5PJ_BK`2q*gf7zZ~!^5CI5@~1I`b_g%oe3S&ufoHPDWEm`3ZE@*mW}UR8&$hUCMS zVHb?}iTp);hnD|OoS(xlFna79P-tt=n@?dw_!sdN`nDS!X4H5k8)Z)3M{r{Rs4jvX zi|Z%lMeaX>RbRX*05Ge5v|J;nDiLl|3!mZk^76a9Bb?AB={V{dLnvXgucB8znN4~oaWMC zgu>tvG#|d!8Oxt~38pS{XU&|JA1UeXPqDs+B_!0si&r%*g zZa_T%J=yB>3}1kPufd@j$DOU*1Vt#r=L+}9m6{#NTMz|xJdS>sMOT1fg&XM7&$pYJA~g9tz2o4Ka$ zv|{CWND8dcZ842aTp->#2EF(z4(4-KDk+XZ;=ahjGqQz$wRjur40<_4(}C z!Q;i3%ibFd8vmz3($6eD0loCM>TxTfq~INvw26Pj8Z^Go8j>?%QslYrYWVTwo0*uh z{WRsPb3N6}#0yASQubTghXa=S!Sln)y4y-h@t0+=K3N=u(c3wg3CR8Zpawk4l2_Mcm{d@b!#~$Q4B~+d&{0UZw{L3^Qk6AAEQi6tm~Zs`0@vfwocyf!Ccl zOVR8nxZu#>$w40kmXnVX~_c&D<;Z*fw}ZVvod` z$UY1GM(A{seRdgiVu`KBuN*4+g|a1RuWwf_MgBPRd@j)B&s#wCXa6?f6+d$L>k0l3 z>lrWA(~i3#q-FoEo+v4Aiz8HbjLv&4h3Pf?RNbti<7La4RxTO0fKt%c#3P6Gai+1| z>5YW9CFRbB&lN&d#F^pmhSC*DM}kbGuYC?B?pTxF-tCw-Z@{v7;9&~0xdZJ4AM-a1 zq*o=kM>b z)+BbXmB9Ucgrx|3>6wcjw6M>oOg?1Ydy1bs8qA(9YbwlP(QDZ5(U}UWRVH#y5@-rP zqGlntgl2a>x2yQevI5;@s!R8CH=}!GLCi~LZihY$66|o{CFgQ3-SA*Bu|!>C2p9fL zFcjc;JQ@GIL%;$cMa|HN3q_Qc7f3-WCRlSgw8Q30l z#3R1pR^cq?Q|uq>i=$r7L>skiJR5*7|LIbh&0L__JTI^ddhA?ky~-3;pxvZ2Cp8ip zY+H9Zr%oM(JuX_KoDtR%b|mJ-Lxze9h3=V(q&>;av)K@>!EmCg&ydobbfm5#dYa~N zxK>vY^JKX2fRmX#+hVJNHxX^P@ILTp$^{kZoX{h-Dh2L+sk9+S!i9HSkejEH_az*8 zzJs-;gUplBK+?i*=^lTD%=6}9=PkYG!i5dc5(pQz!h@y~XZ-=1AmN1LOKbd*1a>w& z+bT8Dx^Q8@;q#`*;O!o#Qj*`j#*;M@H;woi3x^Na3|fK$dG2>UYt_{UwVH!3MJa?< z`-H-DmT4;Id^E;Jl#tX&Ms1TdpVJfvzi_%tjW$#hIgO>jdI+;}h@3}s&9R2Vr>sx5 zPFhyum|=z0gv=n}E6R~7twF*c+}=S3^_RNBh2O)jP}4&`Ioz0UedjUnKH@uzA#%C> z2yG8TmM)z|H{&@A;ULn#!ucriZ=|Olj)Y^M74AJ6c0|br{Xfp$1iYy#{U1L!dzZpi= zj^jA$IQOzRWpmP&HYzR`7t$ta^Z%Tiv=+bf`~9Bh|Ma=dO>%PXS>E%W_q@yJ1r_SC z+JLtl_`AK8>qCwUqhq8ku-j9@eK6-Rs4w9qGB%x!l4!8j|DHsD*Hlvqd`RMYi~L~< z{Qd&fQM7Vb)1eB_nCE{LIvb-yK1_#h*jO|#9cn1y&aKH|E14697IH#=f-o7H-7%tv za;x*lJc>i@$R&)7pP-X30~F=xS&yZ0jLaB4rsPJ&jWI;X>70s{!S`>GqLY(5TW7~& zJvou#y^>3!`93of@oqNO*CPQ2kwfL&e|zQx^yN9}ncF;eZn`lQ*&kz|+oi2|z>}$e z-qv+~CZ|3C4T44e#GuarDVzvvJhE0wnd<`ycxE0lKS8%H&JU>FhKQZOT4#)|ty8=A zu;iLDo@64f3bk3%kJ>aRzSjE<^eG$hl%LPaSp~ZXbiLbytQV;BrT`<=4Zdv}brq#A zv#So!v81$h9c`hoXasGQgSPtn7Y$SW_5HIYyPrxtEa?lAL0cPwiQrr$^CPc3Lh~BF zgk8ta!5W$)oyb&Tl%G;xa$sbM89av)T%<%_KQr!I*jEjW#3CCfhc3chU!^j}CmfjF z&|q%lqM*|{M-odk>>o0iVr@xZhPHSHr(JK~Kr+LcF2+LTcw+gqLA%AiW#^XT79*o= zfJHCsCdg))dUJYg-qG`K1CRWmAx6S)`1$M+^lwW)UE7ZUS>&zZ9z2iOdo^!D`@&j7 zmH0yclPFs&m90bBAMtL5^lla2?eNl!r9<}D#*So3zpoOX?c3^2irnw%yWe}LI~1DQ zz!2L*;q`W6Gjhz~`uxGLPuW?>IX~li3)cx;Ik+Cg<=6s0l^FP-<39h5l1;KrR3A7} zi(F}|oI&z*LQ3YNw)r!XRB?iK+E#YHKDizdb>o!6g8G*FOqsbP7ZOqqn}3XC1#m*S z+5#2JUWQ$%?v4C8jfZ8X`%5z&GDHR?n$^&j$*}I)`;~~#nhN<@{_>IPpQ>e+?AZkk z8%vWMCmlvbYMe1zTXIi>ZWYP6r&@t%M)*2|^G<_>I2LC?;2&Y#O~*TnpmtdtIjqZ; zBWMoS9g7kF(nsgu!#)`+HzncZt`aqUz;Mip5%2C_WAkFHUzSQ7>5GZbqEhsQ&f)WY z(&x|jsUx3v;@f_^qj8$@H5Vwi9%|m2HjOPjEdASE~G#vy)exyffTJmp5R}+@zNSlifMSi%>S8p1=>$- zywr~SZ%^2+OJ)8K(HCmpRel)?QM>==c;AGp5SRGIZ8&F@ah}(e?DU(r9-cnuL1aSL ziZep@tjdRl_NP_%!*Amr$DiS4q7`ol70d$e7bs~RIMv*96VY0|Bj4UzF%gs&LQhn} zgh+{{C~@66t9_z_mWdHX>D!#hx4*-;20(3Pw&V%}5*@%pZiIIAe@vG0y()D=d0ocDb zV*O(bp23(e6qt+B$04jSK0?@oCSlGToVC?oEBZ zVM|&1nN#}EICAEgr<$8(Y%qMX*uMbMh|Mod1oqMeFXOrwQX(>FNm62>@cWs{tM(km zwRXh!8i6r=?+t5`mEzBXj+tI>*mkQFzZ+ys9`6c7@aMBB&_4ggy6y}a_c?quk_^pd zXV2Vdo>{LeHp=8BZDpk651tY#g;*HK4Rav(N7vigg!CJ8#-I61-uyFeW4rDBGYuxW zyO=Nqa_2VaUAA~`gpI@wd!nwS-KOif!}FKi>!p$}UR81pf1@R}xV%0}rbW5(Ge7DR z>&saU>hA4W%{FrzQxob)&T2kY|3~ACw#UxQELEn5#*gpN*He8*LS37!U-+|^Wvh`* z4RVBg7ha8q8br1u8+Ua)^gW|^wwjn$dsQss8arZih_KE(V?rLE4X#MQKUQEwZi9Y$ zAx1gvs&ZA{26LLUo6aXnaURN*piJ^rWoE(ag36c3QIGEnygJl+5~ZTADmBF$7b!I! zrA*#xjHYbr)1bxD4WL8N8r2`0L1PPWb;Lt&41c&OxNgRM175><`zZB^umAI~+PT@T zsE=x*a>hUJPwV`weci*g~Shw5Zvvd?1Q#E^P z0aG|W_5LNYW-?C8H$bDm(^CKq`OxPy!{twc%sr;w&Cy)%A9$<>Tev%C6Zph6W1LB* zZ1+;`-wT*)Yi8BVyqJ3Jk`1NxrSiucxSiY*NK(;!!}ztl6==b<4E>&d`m=BVtM>>e zdy3{qezlC8k?qC`u}*~^*IvpLX*D zJizUP3`g=-K$>BYv6CrEihI(4I6dwKaI!R(@o;6=^UMt|EYZTZ0vgpD6>JCYO@j~F zF7tD_1)LnZDVbA+=Mp}xS}nb@)f%_mC2OT#Tl0juSFJ2NCpQu24DJ-H)JpM=pb{~_ z1*`)Rko5Ce+&K%*qGBaJe=1~UANE>V*fF@;^fqo&x(iQ}x#-Gp+TuDCZOT?{Ju^+w z46PkrmCY_&8~?iZHq2?SmnovH!?-~5lR01Z#@CZ<$QjoVzF3k4WzJ_JuY0j)IfBvm z!msOJgp`6d=HdGMb3(oZt%&p*=2PP9Zcbjm{jiEvG%H(}EQ*SMNxvk5h~HqTB2U`p zc2se!gN$25cWkGNQ{m*VhL!`Gzp)1}rZI&Xkn!_a*v5SC4!&iJK4W&MvEHW4rv6j% z4wXyIwtzQSpxY-_vw(QJYYH%@?d+VgnH`EfG(X%_>?*egi_P-3`S79Jsc^$mKb@Ul zTC_mNF2Xv`0D4K(RpWk9PsV*9ba>Ndr(>ssCss?^>vz(=8@!}b;g3nZAuQFQ2<$PMegIm}UaC zI^x)7XS=%v`ktxm3|Od$sG+O?mzJ@JaLdN-pNG8bL@XpBym#jibg)o)<#n;eBOrLnC zLSOfv0DWKI_oSOK5$kb2@x^(l+l~O`lH@vqXH*_j=HcD|Fv_L=e?PvvE zmEm?jjgtGJy#<<Qz=x0o%9i!2Xqdc-lptORgWvQkI zEe>a48PQ@HNwG1N!l>;54)1YuE#SkOiZA&Q z#g2@PvFQCP{q&Q&puec%$|X;_<-)?NR+v_t>n9GaINv`(%Jr^nRlBsJ+mBOx&V{o| zH(Pzy8*Q4!sqm?X`qZ9Z?oB|OS+w~XFU3RBBFoLl-Y&yRqkY|uzP>Jm`z3D*_e;@A zdq#Uzjb61;E@x4?NT#m(dCWWf%h8fpf9!~s+=_@iWIVP$g|_Ic-Cm`eWa_J(D80S^ zIQJ2F_q;mz#z*5k8ilyWsgs61%#DuY6+<58wzW8S;d@B7R>heRMo$Uv(z=@zv)yE4 zX=_ElSC02ryoD&!T8p!+RCbb8dnPbdfg08Ju+KVKRd*BpWx%VHewpNGt@s6ep$@PPN>J7`k?+)lu1~i8hy%? znQV&@PN-C;O=d$~iMg__)a2Jof6BgrzU04wZ1JWA+ZDwa z_i^I|rU;o~thpVdXI7E=QsOYeFT`?2gHN-q=^Ye1#0dL!dj&0>!sj*a->xgMHY|74 z=aIAZ=KT(h zz<#Mhv z#)Bto`1xE7tO9nSW|f;-2ZY0TNOHj!G1|SZ+f8L96$}rI_ZHtsnu&RYDRJo_a(+D=c{ z2j~wTvx8*NJl~kxf)jdOJu{K+2~n!3IGif$7QnN@y*>2h?3qt^;e}$7Tb)8N&H}mv z^9gY%#gl2%V42hcR+2vRMEiYH`4mPgyiEls`_NY2#`*g^0|;kP)MtZQ#o;F2}p{$tt4>rM>v{UT;AojhCN|*(S)K zO>JNmkl#aD(CGV)gU%ImRzN@H_eFGv1!IyOnFB#e!r?jz))GJ{u?;><$N zEkT@H{I~+RUc~!kHDbDP9mf4LDy$1!`+g!MpN(oWOETm*@Xxn+YT;ae>NZeg6n2m( z7o;W0YwL+&Yd6li+grGE>ZsGPuBGm!t!Ls-j^1js&!98w;(qN-o0r-u>-lRkqM9c* z9^e|en2a5qDPxxHQTS~Xu=`4Hg}tx^8Kj?qmi;Ywb*epNya65_%tXZ$#iTY{3a`$+ z<3a+EAAaVyZD&hL9M?63*Fu9M_DQ3jF&(1o-$Ybhe5|v}djoqDw-*#S7iXaroLj9q z#aLQ2jH$AiSQ3h(nq1u5z2SLqaVv30X(`HWhDL?112tB`!2yaJs{u+E{0;{4A!(V} zD183Zz_0zfAW*u0wD;Fv%2DEvkI8 zI2PpNkUHH|J(pKv<>+chUb3 zoV}Zv|5zQpe)jqu>pxkqZ(F{tb9o$2*HMn`Yug(3tza@u?A7rdYCFlKC*rV{?iYc+cS1-uye^|BTC|p!?VdI}~hrI;A9qRnx&_v=wXFsEkybR!G5rr2q`G5{6e> zy0;=$Yjrf@Svv-&_`iIhYsdHAU(e%@T41%Qc=)iqsS%l7iM5>9J8WE&1^OCL z0sg|tKqkHVKLS`F)Io)9L%KD>SYd1;i77$O;fPL z_KRTS9<+1q68wp%XL z5S6rR!bfQAeop(6+S!oFaVumma7!SwGS^YP$660`q5k~hhiz9b9D+{sFsE>*>r0>; zse+f33VxBTu$CS{n-DSQiH0w}+_4-UnsVeTzFlCheXH#H4(J97_XEE{(Z0CsI_$@X zsxLt!Z*8zB4A8{uN@^SKSw+#}63n&L(ZI(nVbAhvoKM`Skr_7=zDHH0-4;C06t!~C z!0$hMwn92zX4w_utROK}aq*HQJ4HymY91KVWv|Bl8rEYJtdmV%*r#SGP%CKHC3h=C zYtVzw8ervp11B%y)Xhq^)0*eYHi5d?pnz|Q!wn4K&w_Cgy|_Y52>uQHy_LHi{9s=2 z4$O@M7sc_o$UujWd3s+4JP*8{#rt<~nQ;FrU5l@;n^X6@ZQQfSN%f{Xs(Ev1wDZsI zCQj?DMT`~IIURDQSUgMVp7CuLIUCo7jQ1C`T`NH)E^Y<>$2jSK?COw2lh4SqG}(J= zd$&f5?+55=dM~hlbMIDqE~~z)cd{#bw1ngE@(jl_)YiSht@=K3#;USkLO3 z8esXN>^~%YMXp|+}2%FYt+}&JPgF4 zL)~(eCzhI;%$Gf@CxX*O<7w1>18r)t=knTEHrVkV>6RyD(@ zBK(&g>PL6Z!;Gi(Ob*hqqGj`gduyqskYTB==%i& zbT&2wXw7k$@9TPFES7BwvGKn=T|ucEl&ip*RVGkO26JzC-W0I?Oo>Ra3h^_)XU7lT z0#MzOb)CHvMo=FSVtS*+tvCxui+_mtWnjYvKRGIDLuTJ9su^s)3w?S z8upx8f4aN&T>ZJIWMOEYxGu)5-QX4p6_sBbArCwRzDI3k+2Db)@fx1aw~`;S z2@_t6@qU$aZ8#@ITEJhfv-?3AMsrJNxL(>9E+{u!EL{s|FBwZTo^L3QZ;2M|{fGq= zEBX_fmObXFCD~eJ{z!8o|3^W(GZWDg=0lmgvvz0ij&quKTXx$v$fd{}y0Y3iUEFd` zifBq^Fdlomp^=Sv2~7d-QahtXwqM=4(5nEQWJ7}j-^RY$16w#xZOE6~_vtLsMDe|d z$qp`axxce^U9Sl-DU4Z#*b+Op|GvA2=l5oeXbzB)21D;j8Vq8hoax{Fduv;I<1A6G zOeeKjo#~`!CW?o~WL2c<7MHP9JEqIeY@#D3gB3gt_rSXB+bdzEf9p|*<%7kR%^AO? z^nJDPo-VG>(5akI4J<(-tncdHY=FGxn!%W~8@9o_Si636238sB zD9$KH9p$LQG<=sZd>21_SH3>VwZE1|zmSZx>)YVf04llLe)rS0JMaD!|F!qn?}@RP zrG75!e6BXCEsu?xLb;;9&$9X6RN4+ZPM-#a5ho#I+@!jD>fnECd9CiJI z_;f*+++o7&JiM+$jUV8(X2qi6l>pv=nWM6|0&#Z>hF4~&PmT5W0cz1g>XbXM$NF`{;F&(ONJVSlT>D_Y#! zR}`U(JXRro+V=(W2uz*Xy>)c&tDJ_75<5bk+9>ffFmk)M4pHe%f@ED06us(Jd2j9r zKB3_AB9i%YeM-7spv(QS2l6#qu4HRgq>m^|geNWzwI&c$u{q!^i~5X_)=WZc9_oAK zq7wU86!Nq6)KGrM^v8{?fp74{&JFpF2ZqM%-@&lY1LaLC`wn6KT<853YyUIw0m>5$ zgM{=&^1v;}{pYxUiZEnNeQ^qmfUdgxxDdi`qz=|1#o<)C=@SIDdNUoPu;rqr_K2yM~`E7te-5zVpLnZVWyap)tAm&(PDgN<^3c(+{;k;Q!CxZ+|z5 z{Pq)CEB$m5q5O(~UwsHf&K!3CegCo{$B5= zQmOCwWsyGL6Y_fL?=JF7BcH4eeJOo%j<1|mr82}*c|1BdOWq$dT4tVO6{4C_T;eLTen{{v1NAifvNd} z757A9QH(LNmdt~|ZRs<+Qx(zR5>dccr(EJv4>A9#=T+|M+FN^dCMIh^kM%bcl{`Ej z_XU)o_RoP75CuGg@sWAUW97gc4EYG8!tejW8`myepWvcl^p6|q6PlU$>m z1JK>U8wIDm@ZP$Mw?Xseh*n)1 zcp9ai4=jLg#yiw4uMx+fP+8fgr<`&ca<-^bVSbEmc zK$MsWB(eQFGFufH@y~e0*?jzD^=`R>-+eZ0D8v8wTcBA!&za2aH!NzU> z>pLpjRt{uRKM7%Sr_nJAnivn&kNYq@HCNlcun@QDtL=rK@NZdVWFb`tC-#Em;^U)3J)= z+{NqJ{QMc~liC!y(Pz#Y$(2a5W`A>5;$Gf*d%5G;X|5pmspS%|ouA!2eq2?DiAt z>{C^+9whQ{?)(Dd2E+&Rt?+@M@AT_`ElJyzcxveV75z{6O_cPTs>p9-(r+r(kCwDd zZz4lWjnw+RXA zNMuK~+|49Ra_JKaQd&kkCqb%d=ctUG+7d0v+AFwIoS`MwtzSeX4I55lNlrCNjk`7u zw3pPZuEgvwr!l&#d16vW}6<(>g4y3e_4E-*R zN6EH3@*Ha%n*8O(ql#mBX5uJUv+bvI`gWt^EAJ@hKd`U-h&4jvH#EqB)mj?nNh`QS z^kqzhQ_IC4LWPz%mx`?{(XkEY^3n=KlFTP^F*G=X+schSNFxQJ#P|GraUz-oez*a; zN4e;LA2@O_qMd&j*uPqVlT|9Bfn}iX%vRcCe~%m^4xED?MgC8|g1#SnC?8_1-*qsM zH6DY!oQe4AF=^S57?2$R^(+`jkzQvHXwh#uKN+|+pDxzbO$C3^^)cYAa@4MN(`cnn zrP@$G|4~mOD3IzK!~FJIp02h@pk-j>q%m1;ZtN>%W#i5ceQ)8XL5o#^9^4aZFsoQA ztWr^}aIaug{imE4Jr}=14!9HER_-%z zBD9W6xr{^6PRjG5oX`hbXCn4X-9ouuA>w5Zb1Nmjw! z!v{?c9}4E$!pWcDJo~fnyuZ)Oam*C?gja=0J!y=my6ca}}XGinleM>IBH#ll|-<#v7G!p%!6$n^rXB1+^32>_}!p@_17J|+y`@`Nx zM0lq&(_LszO~d&JW#BCVokKGA04o2yi`RQ`&B0zEw`v3(o{T7|PP4Sv5q=V^o}-*` z&iCza!N=49Ke(qkBe>Wom%Bm-9tXPgP;RGle*hXJmXEnJ@a~JpPBB_qnP)xlGIG$U zP{Oz3+)6nc5k7`Z^&CB=3L8;>vNINIKHgQsm6xQ#3ik>3K6KE@E`$4IWhFNsypNoI z)s3i<@ZEM;olh9zpZ5fV}g zB&2dlLRtw4Nmh7~N=TERwSC8H-4&3G3jAufiluiG{ExuLuSoJjixGgpf}9Ysz<5Fo zqh&Em@yk@aF}2?t(jWJ3Vztgsp&cils#LXWiS%v1keiy)st}v}(eT%x93U1v&yW^V z@R6QIeG`7b6S5$Nc8dINSn;4Ah!Vf;i*v)X8+#})XMlf!2w+EobE`LH&rXRWt2!#B z93?WzGPll~?3NWII~AzQ4*U4WoB(S?JZgZHf|=+p9pfG4{*+S`yw8nt@|*_clwPBI z4kB0&B36I2Q|)Ck`0Y$_oNyg{8m3mjqoIk;MWbXj4et?zf2=nnLPgtq!?cbPy_u#0 z@F^9aEOECFds9&R`@K^TsaYtTMy%dM-U<#qfzMeb`r7+y9jbI-Szky822OZ2B*I5{ zz;_5MSIN?qOL@-CL3$D=yD3kh=a2Wm<>FmH$t$5glanylKl;+8n5oj@ziB666FA*+ETL_H=>}13`URVKdgzzpvspp!&tLqw&RV>vVhka{kpUMo3 zJ+PId=MA|i3+A$e61UKGXdmbfaf9J?4uyqi!B+TJ4;4 zF~#|aciCganE-0kl~Bn!3Eo@Thvd!__pg$(v5!j5ByT*$v=JUdWZ96<%{EV*yQ=Y! z%{07wB@NH)TY)%moF$Dp$Om%A05HKIQ&9T10@39LpfXf7s{pc zb%}qh-BmVbxW)w7R~c&|FSB05o6+{6y{0jc3%`6A{4x0EbFUWvKgAwI&mueElR@{P&%Plf z6IY{1Bn*?7uL)WH6(Q$wJ%a0P>D(<71!#jca8Zw>6UHEgOi5 zX?__NdKq$^E&VU!pLNyv|KO_%g~xyBJ<`bq7*RN-jiJ7USdYuS^i+Gezs*k1 zRfE25K_Z>-kTa^^WMMKo7tqt-m+={vUgbRL6{B{VEMC@VsLY?kjNrgOISQ4fn0M|5}*0 z>J08XR%wd$O6BlXn;wRjnlV=X)p-uXp29|anL)D8(NnkU$);Q?FsY=hy9ab`4<*XSsluq z03IAAA#M%e4!M6{5JznC!F%tic!p?yh zApQs60|Wni_lSY?H?(UM^oLO}iKzf<=9z)1G?LBrqwiJ!{s$$?3#T!kgD)OXZ?}Zy zGdg>Ph!0J~oXiajQ6lZj*Z$GK^oVKORC=<4(j@%dMQ^`uSe}%LzsGod0kov>jH>#~ z=KTw<^seTv%P?E!>yzrc7W{y7hW-Z}!Ex1nAKqUME~}W9;Wzi*!yTy zt{bs4kj9_~14qqe6;7Zz9%4lQK%D)rdIou@sXdNH;;CCHIzjAdDp|_;iI~s7;zaPH zPwQ6$4eGj}+;qvCUrkJ3VO=VrB^c?i^X!~wOB0)aXw$VMv+>Ph+rHUxO{1GHxBd7O zV@huRsck2>2dgcid3!~)!`RGZbhlJ)PqY~XGaHz$$QyUY%res_f>PgaY6J($#!Tmx)bmqu)F( zeWT{HyQsInnzu;1Z*o^SlHg|{!LBGrpwVJItphsQ^ zty7Np#s)Lc>*)ytJ1x^!g;g&qE`1?S^CQ*(QCNqad9*tbm_|Cciz{LYqFxby%~dX;n!C}EOEV?8)EIXcE1UeC zJ{9nx4OvmRe(TF|Jtxv^kXYdi*PyAanqQY9ok8xDN?*$%)Kvy{lIRls{>`8Aq zJkxNtM4!iv=<^#`HMB?Y>la%?V5a5NLMM2x=CHI|~Ql?am+fu+kbKr{DDa6`Y0$uSNVcUk1ub+KXu| zRK_5}*Lb(QI(*;jaXa=`%i+oWBl703SV>R#tKd&Wxks8qE799%Z`zBu!f&+S?v6H?hE{K|yiT^8nZPhtLIA~dTNv~FgKqVOr( zap7OR@bE%TIk}_Qamu^@0J3(QWny#4IXtUl0$w2f-i8xc^A6prEhPz?W114!`J44E zJ7>RBaTByLCzjl1yKTnS)$c-TQSz#>{OvcTzcr)SCMzb*(6Tkhv}sx@I9ap4ZL(S3 zEXz>fQ)TlqPSu>!rf$xF#Nva0{~~xQ=@Dsk+4pgXj$MC$f~#%>)r}RxV+pCbmzcFJ z3%x+A%lOH6AMomEl;@xR4-_JkP>e41YJdvcgc#;gO)0yQT4J45y_AZJk$YAqP96-$ zzEk<;dH*LsnbbO2uMGcFy%yk%8Xe1lqt%3!V&R{WaJOQ?bw@d;^)e>Pp^9xZN{a|D z^kX1qL-KXYa_Bv zjsKE_TSLz5>^Xz;5E1^+L$Pbt;g_+_Z+rA^J?M08PlAia5f1Sq0Vk>b;6{pknfUTx z*6=J|=l{@asb9{HY6|y5IpS>F1YDRf8j^*Njo^xU&THD6f*dZVN74kcT(LbNoQ=)0+Urh3yIKU*Hnpzk*5qpOSV=(9AM z>AQFI#H6d{?eCg5!6U3_<-hFj=({V9t}r@u)$P!+zoXYx?={o^8stm=*gmx;FTJ}W zb#4E0><`_!j;gi&D>kjb=$^l!JC%KuI|q#cJLw$RShLG~bb0vqZCqew;Lf9WY+BiB zeh4)N^oHtoO9P%y>rKWPxfQEfmPK>^)Bri~Ab0f6jdyKYvy1cJRa1Jj=IBajB`>_Q z^5`1>np9TDHp3S@rgIl}n)uhQEM1BWWZx0ZUb3Y4G#FI`&I^l(!#4L0%4?%EuMCB zE83sr_-Zp9yImZUL(ZJ>eEk4oi*g@;wwVa+p4!d8OftwP%_l9~E;IF@r@z=*3UA^v za-LX>Drny)Oclrk8{aBD`Lgeaf$*J1Oz+z(eFl8pzV^sna^K#_Otecgk({x5X?$Lt zuzEAeTf@hiYqwsyuZlYeKOc(d{3rhHbu|B!OuTvE_F?)x-?t5DCzpNiz|&YQUJ3zM zL;Nb#w@wXwefsQl2Ys#)yBF2yP@Y@I)90g?=D?jL+|fJAIXYW!dxvTtGcavk_(bz^ z-`(DC(K1AzWRMnQt!$aTRt6LwdCPL{QBKjKL5{TLrOK8jlu2|vDwXU*=I-AIWa-or zv10J6&9$3Xc#|_~;VHFRsKpumPT)*cdG~Qi=0i(0(4_TaW|8OGK>ZsiZeL*KrgiVE znK_v$*mNiLP-DD-HAgtyoqe|JozO2eSogwX?^E_ws|Tmgi3X3BtXNB_*imu-DQ8Mk2_$(?rL zMNlYs1>3jQoUf?Al}%(BM4e9r{(Uq%Gyjn7XJI8ra(j^_wdIC&o36L;YE4_O$j)@9s$Tbe^5eiite z)DPs9?3}*lBdoKBB)Zf^e6+LqU1pWEPIR_7UdIAo?o@WC4!&FD)C#;Bp@FRJe0$FQ zrHqIEui{$G`m|*HLeNvX{W0)*M7si6SKJ(GHHT?$uh}lqV7oc6?j8MHV1MqCC^XiZ zeZHKl+I|-GeuoH_bE~gGOf2-ro#Qg$%Wr$eFb`1z#G=Vwz{TXNrTpk)2bOVNtCRHe zD+thUo3~FaY2LyVC@@;zBMNN#UG&o`&i$aSnvAdItym8$`517iR&c9lFlO(TzN7ab zF1>`?xVEyo2C=pj<*X7qy@{5j)xC=!wi~dYo%2u>*wVporFKF}qS1-YqP6m-9Go=5 z{6_&_?O!<$U5i9~KV-AnX8aE<(=Ki+>>70E1d>f&iLf3g5vuz}9z=oU7723rH1>F? zjA-s8xpXy^2B)uChB?`F)tnIC@1b?G)g+6_oQn(}SpNe<^xutq;;kqjsHJ%?-bFcs zwGqNjGK6sce5RFKw9vxd}$YPEe;`qYId3IM80_z*R~)uAsXLJ9P!<2 zHs-`c^HU4RxTVNDa@lup0Dk_!TOyz=mc51BVOtD+zNLg!WyXa$pjvDlZl802j61@= zE|JD0(JRPUMb(`!=#y7~L zPJKe@lT0^1Sek<~%bMVr2*phT#c_kjARArwWd_1rSuK_igr7n(Qy|;S2cKCn<9V+R zZP?q(WN2p})DP9T*BggVAMe#<9gp}=ME64P(nHAa!3RS4qvt^du3g>XGpP%&mG~Y$ zr6dnmm?|j!I=msAYF2uUI6=wyBQ|pKc5nFG^twv#Y5Vjwuw=sr6lM9U?x9f|2oB9^ zUr?5%hlca&)l~wW!6I0&z`OCgsofu9PyA4lnHcy`f7?6Mzf6qJG;b}kDEikFEhDD= zhSk{JH3cUPPa>N9=rXm~5%k~nDVJoVJlUwKuP&;7@J|04lCcY%>oi$eI_=JOoC&@o z2JFp`LJQZ(DKdcFmARdZ0^U+%!?bnG#A$cFy(Y|MOlL_(#Zpbq6@J5-W}D)C+n6ZF zqu}Q;?0c)Gt$U42XH%w3ar}eaQW{q+hekpP^gvn8SwyckHk<+WLSw@h-XbZ7ZcR5` zb=!lR9Pg|#8ZPPscVS-;f?Zf8=Y3tvnIvNivJiEVw@|NITshdc3_JJPn(hEj!|+V& zq;dv+asKz+fi)yMfM@|1_W(v|)AIYN`~a!uo28mOD}Qv=&*U(oC{l19IRGo>ic%U` zPdtaYqIFN%qR-uJmzyY-G?+saC9c89y3Z1rZqcJ4*&q??w_wjZE5GOHV~lCbmt zU*sY?B=R#M733nHXYy6_*ETF0IX3+&8~x3*Y6F#x2*1lirK8t8mp1;tq$3%>39~p? zp#N_jmXMbA53R*N28JlTF)&2w+X7chNHR%6BK#iDHyf#stJ@Q6wl)yU>W12T!Yif` zQd0dYy4xJ>(?+Bu2JsyCd+FZ&K^J_UE)w#>AK~kCf{-bAZ;yiSlLx*{xb)x-qx$PX zJzSsyyLd@}N>arVzc4yB-AP+$MC=B!-XzIVr6Xi1`>-ta3}lRO8#eU4?Vz$0BWi+` z|3#LX{r`}q27R9o$}lTMU5-tcHs0)&Ns<)d$8}xWNNGB!tA&(!ac?djmU+I0p80B- zXR$X-H`9jcrmOcg?3>>#<+#@&_nfkG9F=^CaLNN5U_n59=Qm5Ahh+8O8bkVPSTUzN zH`TVM)Ad64N~P!M8fMB&oRf*r>!IVWvHrqa&>{vFdCT20$$$M@_;K%FDuXUkZtWE; zY`SE9=)_%0f!?7OmBA9Ora=aI*uqvn9QLdanawDL^KrDRuA@$2nZCx-@RI#BxZxpi zLoIfgx7Q_@lcqA_XQ3B{XSXsCUISq|e;O>A8^yLlz3{vFJDl7m5}>t8&}HZUfVJ4Zs&w{$j;u8qaUzp=Gsp>5#|x-%y^mZUP4 z$1!H~L?D-Fp70NQDAg0;kJ4VPcZj|&Njj(Fkmw(x`xyTa-K+gq(|rJ$i~`F_ysL&K z)L*cU7Q&)+bnOs#IJ$=BB|hr^He-W6%0ZeptYw;~t))`Bta%nEZ*GOA?6>lI-`XU{ zps!uB`TfM~`=i7O zu3lyN(kdGtS!IDc=^CT5VOljX>dnzTn`$?%QF!|AqB~8qE&c+0!ETSsy&|-wlkDxc z%b*(&FUoVj7tR3F`;zd@MgQs|oFFLj5VDe=>$=FYo{K|cJ{MU4hH57`DO~R*rg*Q+ z0slqd4kVsEy7o2j;i10EhWkFTUke|{P`_IIeg9XRL%y&2j&t-}K>5x6UlQ`(1wyVn zPsq|nLY~1rwdaI+`q4Fkm2^!d^n~ZKN&Cb&MG*Q0CQ-22i_0FM-4 z@e$C?OZ`TPRu!Pt%Y8@J%HVtA?_Ig+)!uOJwC3)Mo7N@GrZpX1yRnp(&;i>_ha73- z%*EbVI}i|nixUf!3;!x$V*xMz41PTs(rLIYCwfWF+vgmcVtS5q%g;f-K9M2Y!7q2= zo(0BASpOZ)9d+OD{(acZRl7Hr-sp&NE(a<}tg{Fn;tQeg&^g!J5q#b%)}eq{+Y{Ke#2Pby-``H=$3SehV)*$*nfNW;WgDw|jK3g)4c{S30O`Rg3@A zr`tv2%jwy;92!sf2SOHX^dR39^|&~{&BGw>5!jsT-35#xC$mfbgkqO+mwJ~5I?r6-;8cNEOu^iLB>>@c&q7xb)n)Pbd2YK( zVvcp|pg%QKe~%dQQPBRzv@&8_P{A&1rCDPqk2vwD`XBL5imVFK|17Mp344-TrK}Ha z#K|~iPB}aUm$~BIi0yzcX)<~#gPz#LXW30`H!KzJcIYJSYuqV#dch9yIyBPZ5%`f0 zV_z}i$-ZyBqVKfRNyF#q`I(m+P|cZXg(FcwMXL+as0YL%Lli z_QY^qpYhsAD_`oZy zQeT$GJk)wegdITbM*J%7RM3g5ow0{B&cs7npbyN!nM>o=6w>)qv?|+FE?U}Y8~5bdOi;pdd(z-M=>c8673cnu=0Tc=L6EC0{Jw63njkU zNAY3mJ#xo8i`>L8Pcelny8tU&pp(0S5HTMo97RMM9mUgUJ3V=h zo2A)+B^^2)pcQAS5K|R{**hMLK^rd*M!Rouh0k<^-{2{~iaKwwldSIHI=|)vzV3k` zd;`QMhCJT+++;j8oEvQ%qClum!B88i=gT2b)6O6rjdus$Li3+4+WYIF*=||1V{k!^M=UkfaOQLFBAnt{u2>|HX^PI z#k4+(XV1m6W!Wn6fkBK1Kg~-rr+S&}@xXe}v-cza1+gpz3M=vvnpbB@2CyPv!mY`+>d|=X}m?I55H7UGXS9 zGoartjc-{)Iaous^J(BibysZIGo(|#L)awck&1K2v}GS;;LR2AofuH2Ckn~#Y}f9Y zhU!H3n&J4le+SoHH8bFC^m=F*iSVk2WY)XME@bn9-AndFK5(Yv+_wPddn}Ns{}W`)_0Tf>Rqw)yw!~I4 zgDs)wJ|qE0)&Y*smb{9d>=u1b1+p=-{~E|)U%(8F2mhMKF~BT^w-CPXN|XHQsD26FcktayfhD1))WFtHn!ka``>I1x zU|>fpJ)F9-2*quy{Dp=97`?XVp~@^W^;bukx(8iWEw#uNxnqb)Rik)-|p*T z3ikmAzQHoeb+XdHCQEsw;AhkEc^CZUl9P%g-BfNf&TUusgJl~FmphVLD1QdluLDQ$ zJfJ*7I;$^mZ!mzvs(E054jS8(qOHHiVQ5Zr8n9y~w4$GuR41)3JStAk4UOSR$SPG_ z5)el8$U0S3N<9^g(pl#iG=TL5RU3%)c76!LA^3xNe4L53-$=qJ#Uo?q9Q zchKA#+vfL8lln~avdQuJ9i4JZ0z8Z=xo(3S+Ria87VJQ=Pf_h{0qP>ccb%1-%tP;y zg`H$@t1w4C1mVGU<}cnMJ*^+QM9yT^L}Zc+2WbWiN0U@fx9JUV+HPl zC9@k?i3y;W&xA4X+qJ+p%}AayjRkH=!cOi?m1f|0=l_^Swd>v4i#M3E7XRKjMsTwU4GfdKWzMH`i($fPI?5Jaq#F+~{^2XeORYDHD&ujVz&{@>ei7jRjS( z!JE7*9rfdZOq8`B*z)b%N+8f44m=D^MxECp>0$2jlCdr>WA{90jx_m~eb#$Z#Exp^ox%1*l;j?{eh5oENb(Ujq;MyCZhyv7PcPx8q2)3FnJR z$n2~VYXTGzQ`LE$;}G4yfdn0Yp>EM8?BAn#>^WEM-*J)s8;JhW{>_MA1l8%2U;(~6 zyn9bBEBg{r2hg2jh3$OuL;oe(hcXQ;+eSt23khZce#(YzzoDWl{hAF zxpy9?$|}B{!RP~d0XUK9{{u?ak^bFa$jH5!osVZPSV!+_oqsx9FAI+%*u z{==s?P41Otb@Vb>U-Zg>!#z~jI_zw+tfd!e1b2Ke7AqQiL_hVO{yU$C?B4b69C)k& z{TIlfquntsx-To7x!9GHk?Z?LfpXyA5AWs*K8z7hM4vy`J=Qtf4!v3?-L>hu4e#1H z*r5me(C=u}*VvYi;ena%oDiY6H-W|{%lf<58hQURkN~og|L*I6O1wER3o+)) z1{=9Ad&A?jP#UK-d@88zM~qNs-_Qu15@?H`?Wd86iNV~~%f5g4>1r2!lS7L11U|R* z2b}+NQO4PCVIT4)M4orAKW;94-WP$PnvlcI8y)%fPK?i5__L&+gx*~UpFQry>tj42 z6Yxs+zdGF0^>*j*Y$YI8U_9*p<)y9Qr|n#IX-qy5Um6_J4HB^kx%|>`8X4m>UmRLr z8+*6+s>Db8Xe?Kt1Kak{w`7}AwE<2-7A@^I8kkf0UBtbmko zu=<;7BkHp@Xyc*~1uS>0YG9CIq=d`8&${gE`-sJqQHz+k+687@mW)I9Ub?sTzC-ub zE+CeJTUReXxV#d`IZEe!cJ<3AE96eO`-iRTR=C%~PU)=WjN5PFtlJnf^zBbDPXv5} zz>^^SL$F7w#2_-A*V>VbGxH>JBVAfuP@RH(UT$54+>5utbM;#O&kamQL|sMDnB(aeY4z zd(4rB=e^gNe`?f0&wU&S#k9v1IRZ9I-&XWH3i<<;xTR0#{?PCT?=-38*WPPD-?FK6 zkFupV&CnOWg402KKQfuK3hQVd*lA)yfB3YbFd+&EIQs$LKmBe*umpVn@GBv?GX+YD zrgwIRw+YyCbiBIJ`X|x)QIXc)j@F++>yt*b9wUZa2h_Kih>87mpz6fgVZ_=5J3&tJ zJJF6BoTCSk7mfO3QTgp%T!%BlxaL%@D+QfV-BHdb&{2PmSaw_=zD>x#;t+TEI?Z@Z zeL`-hYw7g`a~9fn1M$AMVhdN`81rN!q7ZI@9EuDQK&;v9`5mNI#(5)huhWx7t}w@L zdZoJpaeU4f3MsZ-Pe^%4(Ui(6UO;9Vu{V@(2>Tk){z_)+SzX3P$YM(94=8#ofn`ir z2W)4n>4F>+tnnAaPlgd9n*e z)kR@FxSmnv5!QGU(3ZEP|8IDe;;zu$Y!a#VnaWr+CTOuN|?Tdg6^;aXue{kpL8xm zgR)ncCggj1K`AnrvoHBk$lTJ3jQ8=F$s$&XSaXtdl25=KP|W3Z{V{j~MGcFcC4*Ot z3HfVOSPLJ5+nRufM&HftJBBfd4jnXv$AtFVfp+i3>&?xu4WwYHH1GdoF;loXwY2OTXijY0lZ(mtlfq$TL+qQ;`TA|q$Mxl01Kv^T zW=!?3D97Ra@L}|4@pT|SH_Hz+Ks)qYD97GFK)a3)^na}&Ez~b&3NLq6Ia*--jXIN0 z;|jpV>F0TTm7~0DY=^7tXFS{OAlb-njnQ%~ISQZBZ{SmElzd8mPh*{?T%oZ}g|FMb z2ZphJ3Gk^yO8Ap1#kWHbhoiwGwVuLyaswBRdgv0Dp<3>$tghgGgY}lmkg32&jWNYw z?lhP?4R3bn91mB^t7{x3)d|&%Y3eaz3SvJ@cthq$aLD1;^$^f5zX7^v!m*M5W7`fh zQqOZkxg&b+ghvChPUe~6o?nBW8yz&iE4YQ!^Xy2^(Qn7E{l0{LXZ&CKJtNZZ>m&Uh zs`E6swS43{JvN)3^c*vh&EC$nqwSBP?caG-dWI15)HgJd)_z#=!8|ff!)H16I)3o& z2%0b=_YI6ozamUMRxz4lpoMdTm0~a60gP`%Nb&Iw%Wz*mtdJdopZOu+OgS0P(_ALd z(^-B$G=Mk}Tyy0DJa@9w(ik^%zK%+qku&<_m>ZR#kj}^nJVm`nwCfbj4%O25%ay`$Q~9|UQoAG<$=;vhC;M%fAc`HYT>g!;8A3ijF5e5!-w_VKc6 zE$E`rkswh;Das>H4t6d%;)!h4t&aR-a!11KMewmpJ|92(QJ@hgIi5khe7w+*MI)Bo z`tJyInFWS1$rvAnz)U;nSE0FA;A#1=Jw7-jzkpB{}HYks`R5N5#QYqeA}y$xH+xkT9kYhWAb@2^y2>@Wb4O-?87w)mq^>5J;9pAPiAkNJP6C- zVAexREbN4$Ffx*by*>Tt3|+C2f7upwq5vLUpDp-s@q}^M^^p7NknPGzViJ#0oa3i# z{U=<;9SfJTXS^jCk1qsm9b*!`WZZX<;dU&nv(?RD%<_`*Vm;gAeahxWuHGMkcS&-u z<x7g9{#iH;K z`Fp@!cj1>5zp^uBvm?tF>L0-gPA#78wj@|F4=exDW&*sFCjzUtw~`-ZE-or!jbJIi z7ZNbqAv;7! zCG69Mo`vT^j3ddq<|g=_m0MQvr!dd_O>+|@?M0@6EFM>YyWqmT?+)}D`I-cm25a!q_P;V|C<%ylGlEVgY zp1$zd1{bgCxO+K39+lek@)Nk><>b_I;kOU;2N>)e%1;Ize-f0{?dyj;V%m?t+sa;k zBQrxU`y}-iqozSmv~~};{5+^^SG{)L;AY?fM<9wfeE}sQ}ql9GkS@;sj8{CjEH)<#38q9dTC_OS~C7 zl@UCvFpXxdsXopR3nW_i0!I{upNN=&DX zjXw?lI&XtcCclqm9gk=GcccASg(qcS^uF-NgK7up$IKdAGG^-~!P zS~DdcGco!$Zu;%>qfHy2FS}s=#B(#M&t9Oa3XCnd+m@WH%M9|C(C;n2(U zv9Iqb-ooK-*c8Dcr({M8+oumt-LJEpkwb$lJM(*$Jk|hNJmxF(BEDDo;XFcxZ++}p zh(}dN`9%f8|8k~e#xZtO_x|}}{g_5r1c<{(I_<4|Thg)$OcDw^z>s|@ z0zh&7>Vv=sMq`(|N-x)jVHH_XzFHr!FI~US=-0FhwgSU~DE}(`8DnTIeYGz0j4Dz= zznT!9QJu%T6-Mxjv5~orx#yrihc%_8iBD9qxH1Iu!(K}-DX)N@VahTwP zAg(~?Y^enWl;b`RX%aI?hVRUNI@8lKsPo9KX?yiKi|G7DIPbzey3oU+d%_^k@@+hC zsMkr%Wba~}DW+u{FV*H?*L5R54J)bB@g(*;pO^zjr0qi5JK#rU_J@ah@XUpA{36RE zwc;7i`q&5=v_rfy#Tq%D+&p(fpJR`FgJ8$4OWDo@AMC`Xs^N?rNx6AC1 zAfn$~_Y{|2&7fnx^I@CJZg+~(qt&K~9$&Dtn_-DxX8+pB#l;SNk?1VYmDwb)bP@u46YuXG z2krmKAj5i*r|6$irXF;> zJoqEhe;9PP&GIH=@1p(R{0Xv=6B4yl!@&Y(uTze-NtH`dOZiEeT_=>Y08$c?olrTC z4*p>K0e+7{(f+g(QeF-Yff+LS0F#^#(1i2Rut@XQUfdu6Eps|945Wb{co+Fa`n(Sm zx(;5`f_N4mZIWRxqc!FGY0Mg4o|2)@&e#_rqx}l@2z0*_o}kA63EpYB86PgtXC8!? zI-LI47Y?$C0hZHj8SYTYXnzt1OG@z7!A+l&3;#nds_e&Kvvr@)>u-e*gSO+Nc|Se| zbaRA-$(DucuqIYRFnblO|T8FK)Y~L zb?RsnJa=HvIa`oI_=DcFxIy@BmBSWQ!-9Jw7SHb%+Iek&O*~_xw*A%oR~wzDK=Nxd zvw6^8l-Vy2`nmj>%3?<26ia9LOZ4AV^3->iO0`dCgk~R!_)*mq00vg4IK#9Pa^*7% za}O+|y_Qt_m*}T6dPu`%f*hJhX4S(14@=}JGW(mDg&er(E^s9>`|$x<8);9Nc0$I> zVW09foEAcFC01*YK%XYWw9cT+%@t%7YMi;t;EzCN-!~AClMC7%Xmj&(zqhG#zqJw1 z$b=j+a@xe;n2O0Gmu@mFjKc9X&?kRl#?3?TlyiU46-eurX8Rf zUZ0(g&hCtuhIz`9-HwL_L|nUUTMezZZ_J`hZqTu6fWhNpmoLX&g+HH1@O*|jVt1|Y zJHR{2fIl+aMVIn->qon8)_e^fE-lMHc5|iyCm|mU_(LXXz^HvRFg?o$sWSUp1Jkk% zI30+0k3^@>yQvr!Zv7iYf4DcB z16#3=gr|+Z${68`Z(!5B%RI%xFJj}jWUjzCu7LJp7pV1k?A~Se$=KJsDMxAlIa|2k zKU9YLF9R1}Hirmw_YOV;_;|=11WWy!GY7H%ALaVBvj1t^pOe}Dgqt#N0$O|e7y584 z>|w@k_lFD^egF7f#?<(I9H9j9$?%szcgwr6zc9j6!XxlT-vIh5LV{pZJ3z3QfPEQv zjAVkU-PK00eMpO`1JZ$po+As&gi%)SM&Z%xHTv#=t54Os`Zr5bXu40u_gwKd8d z;F603qbKhE!(xH@TWCVrXnY~5klA1CAEw0L;7sNpc$3&aM+UhO`ZAjOBj?!t=tJ5G z|JY!ykH0j%5gh6fUDO%aNJvne9koa@o4iyt=E(WLth+M^qpx5GnRe12tGFC1Kx2-d zEB#BP|9~B-9r*GC^s91FZac!o2+L0dEb#@-vpC48rpsoe!d3vdSG4gcxZHo4b3tK< z&+fywF`OvB6L&QB6@`RN*0#!?&h$J?XbfbmH}@9zI*l0s4})h$;M@z+A=O<$CfC`xQvXg8#1G0 z(HW<RgkhSCh;?%p_Rb!*{!X zKjECCG2&+bm(Fzk=-qQP68kP!%HNPOMo8J=oUa{QM{-4W?zboibUMZ&rZ>gC9NKUrVoJp3n#MFuT%>q{;pBbPlR-~$_2Eqm;puNR{60nrI%1Jc z@Xc6{Q}lXOlOOJ`$zhqyzdpJtpq_6E#HqCm`|qXmqfSFEa(m zzB4Kqba)7E=kskVwD;$e9?5fQS3vUIKi~Qo@PRanKLAe6Haw6y1=_vYjE9DDt@c#T z;>;HqA3=Kjis{n5EFsZ+5-UYMs6>8lWvyJWcL|F_?W3%3fQwKh%j~bh9-RFypEO0h z-`V4?v}V|RZP3rP;2!AU-`Sh2oZZRBv7em7|GkM+iMH*opB$%q{0_@N-=qzLjz^p? z2+~1VPk`0dv3+egS8CEXXO|mNYDq5nLuphgbmq@VAq!!3^u@()qkf;O)Pl7MA*j-0bSi3{Wj*{ypwk&`kwq+HDDh7IHf2+?d*|Blmbz z_g?LfInoB=1d{o^$=@3!v9M&+$0dtCw;J?f3uUmODCObRCY6~#qWe4G>SegQF0((1 zQ&o7}waTFTB7=VmiW#iQ{Pg5O#|?re(4fWVm>(oNGW%nKw}}nbVgn=(2|ng7OR<5Q z4!!y_Rts4mAa1V{`=B4O!rTfk0saZ!nTS#?>%CK;*i!I%PxNr$RFt?a*rd68G5=67iiW2!*nj*I-_@uO$kgm*|WlSGtz$mhQ8c)6MjV*BGA5j zU~>WYTDsKy0fQnLI=#6v`%^t`tYPg&OR8%GvA+f0#Nb3TIV(kwtVz}H!k6zBtT6FC zgN~B^N<*a0=P>jF?1TN%m~3dr?6>InQWL{HCb~CAQqG^cvh>r6*=~)ieLwbm+a-)Q zY-rNxcXgqC(D(>l(_g#ywf9P??}1J2?95|QfJ`ro1TOVRq7#WMTKo||D0LA1Y>tsiv! zwx=4m5}V+4i~i!qCH}Swf4hahAsFw4`a4pbj+8#5eqC3MCV=;8icH_D4>V)17X&&h z%!^cbP+9@4pgR51u2npIgG`=&(X$QnyEIvVFjoG2)SA(A6WZh}Ks2yNw4_bAcxyNH z?c+X~y&JygW%hw?k+Yz8^MrSA^@Y01fqy&4xSmtMoGsm+W2x*4bmbUy1o!xNtpOa@ z;ko)69)tmS?mCGxU_4La`5ce9hiE$}1VqMJDO?k(JSC1Di76#3p5( ze++klmhcS|vh|f2G5qbBsnHGk)CX|C-#nb=i`nY~46d^HL-$0UkZi&UAl5VuzeAsn zc^)uuR2Oru0k^+bWJL0_vYGF4ti${DEU0$cGDAL#im27+>HQ5&EF)7@!6r#zL*@Im za@>Z#Ll5s+(~rXQ?y$_E`y`8d-ImJN37VB3nUCu1=Ncwv>$hf%FnS`iMf!Afuo$;8+4dcv)EmrMe_uC`k_w6QQ9+1>*a(~ z^V@ql>_>>w+|gT?J$%#Vl>RY+via8ULg)|alz$`Bgl!_5F}ok4vtDNYM@N(ae&ew2 z)I+CPQolp+%tm+pR%H4?r}-8=*;Z)KM)QRkn<5f;(!wSCqy^RnSgy^7b>{PiMywP| zttjK-lA%-)Yv=|C;SKqDTm?Ntg*gK4RHks#a7)g7zeSNE=M`zR`}>!v5Njb>FuL2^ zfVsXdgH3#06~Q;_Cs}?3{*Auq#;D{Dg7eNntZ-4H4@uJKh&FTDovxdAW6dkFIgB{= zh}x5`G-lq=LAo&o9jSb6>K%qH>>fc^w_`S)Y-2PJcF3Bn<1v?Sn8IPCaUX0p zZ%n20Vx38WKF__Ft^dp9Mb&*zaM`ptfrunZx9-}w{OH5O^i%T*`=gOKsTe#YA2lr9r!|W5) zr&;IO9ja}hIdiScazBP0HQ-E28shKpWj6U>E#s zbdMkc_XvC}!*>Wm%yg^ZCv$h#70P{KrFHnr-Y$X=t@}eQH~q!pZdW8h ztM$9}M`~9ajv4A8v4$+MVMVSK_5&06d3w^c>UZb|WOeY?Vox7ftruE#;jHDMA-+*! zRsueY24n)RyaD^eQelptw+z?YYza6<=kc%&I}p&MczI5$qQ2O0?~+yAX{hc);?1_g zqaZxsg3oy%^Kj;&OqvN{7Z*bA0G%!S?1573=-lP4Fw4-I!~KNmlXzJ8(4O;~6Yin8_1!txTA3a!;3}F_i9=n+|r>chPFbOdnr9cX|3y?(qYY zZ7Eq~ac)Jfs0sN-m#94(%S&N%b@agPHt{>ZF1g3}wz+=&G_v8g2w-uOM|sa$2-4U3&e$^bpI^qkDZpc$ zX%RdUM&{hf<4%S~J~C40(3S__CP4>i!<4VqH$lgi|$Y2pTv+p;TLh<$j+9(s+ zNV;LiTrfXG_Bher7a_}-@FQT1r@#T(8Q>a#XD6O}@jQM4dUJSc@j#lH6~1VDEBQv{ z4sFR~TB-fdut^nWR%UaJ)ZfV5AYo;Q2VLV5WET}#zG(S?V-Wt;={#SG{fb-KGXT#q zKiblNV5|>k1A2r%eb1N^sXeBTR_Lv` z`A@e{7i2eM#qWa-C|Nt8zqp$QO(G7rdvd^A$MAc=4=e|F__~VLQldU-!umMlVkXX_ zTVW%BoAI)43S`&x_HMR3Vh?*p^#i1b^{~4~viC{n@mHN%A+RJOG;%&^pBqF3LW<7Nyv^7>xZna$0@`oT4IWUiP`w!>o#$89vb-odC; z;$%xw|CTKR-*wnzxQhedoQ;-DE>(&%nJ3J&g33&x*vZi<@^Wv8u&0ySpN9r;pdfkk zHILk1gWu?V1h7^9g!zMz;VHm;S&t_kPXO**F+85DxhZ1Sm5O=Ww zIw*H!u(%pkkfo4K!O`Lus-y~<{p~#laM#WAL!lE>n+l#S>AQ3JELzAxblnd476ZQA zbgsU6{#9^Y`}LA0Yv#WBN{qrd!(m7!RW5k;;vUXOjXBbM{LVxYe9|5x4P4rHOYJAn zk3f{Az?VB7qEWfjBje9ukH1fUpUvsW$BpPSm}f7*rue;f=+I)Wt@$To>3HtNZ~KY4 zi*JGK@He0OVFD$Kqnl^@fWHl7?Fts9WEUo3SMdCN zt!WyxJM-bKBy z6GZmupPzqTz;AzZvQpx`^`=i>P-et-8Z!q-Ud>j&A`cvw;; zi>niG7Z2ynkdsO6@jY~g#v`xt#OTG_p^FUN13)hvd7xi(F~p0fQ1_6&7v%`-A$k;; z9hjvM)~}bael@w)uitkMIIi^N8@@!_h$eO5IgRJ)%aBFuaUU0<{lrvZ*Bj42DC~O9 zcekL%z>AZYBxFB;z2FpRX~qlK@gjCTT9W~5kd*f4O_F2#VV6g;H+C_Hd%F|)3H&h6 zQk<*2K{3(-(h(^R_}f=u^9hgq z1gsU9-H^JsTMjshV;?Xy_Onr^kJ%55M4S&Q-P#P4C6^01)w z^VY(X*^jnX144@Au{;lp#!~xD-HQZy(#_UT!|T~n+_$d>-HzmaaARv3W;&!Me7yic%@b`6LJB*IaBZQ<(|ynD2z!A z#)R(M)2LkY;uBZ)EYRZ)zxhW?L);3?N9e2I=1u`{w|0iXAhB0FtEZRd=DX-w{yiLK zGRacsT*O+6-qN}h#``qhf*U%GnYGx(%4V|h`}Aw{V=Toi*{}+0(IYBT?oxeqa@%HQ z1-x5ePro{%2|JBdpli~4ZiZ~;L0t$mj_v?O!2J(%F=JCB&xv0y2PNr(M=eBcOvQ3E4>{O1BrmwaIoZMZu(zr(K zGQWoel14hwH8(bpT*>TorP42neWP=NYku@Q_Bp@rf*tcd8NU_18jJpjt%@=P@cYp! zpZYKtmk^2>Cf!r7f4gg}(2IV@R_CX-(E`WT?|5ub5x2_LqCe5awAIt3^|+ynQD$e4 zb=_jS1@oW^^WhEXJwOJ=NY9|or3djU=-!_|@2c=fS|MWtZMpgqV=ECRpV-k_tlu9! z3O=AUn8SJ9;BhePv@R`?1S9P0^3v91&_Lyh?X3!47Rw!$;{F3Xk;N;_N;TIM;Tsur zYF^I8%wB-QytI+pS>|6GKy%+Xq?Gj!wpgi>H9-d-hDF6VtZFE(vQv6 zVLTb5R>a2Yfp?*baG^ z#BRe0wlD6_V#PM;Ad57seu$(qE!;7ImYtS=5!%CC+(p|PHf$#_4(E>1+Ooa%Zmhh! zqs3MnL@UOa6oRbD&H2H60 zx?{!6ah=Pdm*%6PS-lT%>cn|BGpBb-?4J#2Tm0(7T72tEwTdGRux&d=n-5J*d0hs) z7i8=G_TgSmqr`q1Tuuf*%d}kIB9twz|Am0d9l$C0S%_DI$BL|VszZ2_c3Z}IZl7+Q z$)}0ImmE>%BFi&bYOGpLhhuQeF+kJ4489o>avQU0pI@Ad_yDv?T{4ro<|kaaEy!(y zU;8M7Ea3$7PgKB%`v*i%qB7t^TmN$XF0n)ze$KA=ra|+G|kFSBu%(?r;OfPg$??)ddP5mU2<(Z%8 zfNztju&xQe^<%J}yp_2g*tlUncZS(@16lgFvHM)Duh%Q~j(Q?!cX0je>M0n}8#+Q` z6J`hOA^Qh4s;&GpI_cS2)k)YDYdZdbv#z*~*>py2R(H(dB^E7yOQ0w8qOPai8kGhQ zSp$w6F|V2F&Q9#2syT3*0VYv5?uzP8tjCYRyCiv1x&~Y1bFvreVgE%VkM)PA%clmQ ziHvqn@ALzwCV{@Qliiv*dz>nlQnNen&`(C{_I{?FZ7kMDJ+{@jf&Y{4KzmTrEzlYb zZc^+Y^>h=w;9PP11K7^Yb32J+oHIDNa~Mi*!MguwoKHDL8(`+YTbXvuF;>q#!PKMo zvDkk){v^mj&s)b}7m;NS2j`=Qd;vD9ggcC+n@0B-+g)_H1bh#({>$fagnRK=kbVdc z(P`3ElVINd@Cx`pJge}OApL*$;V!RRhG*J1)S?x1-gsdf#*sZS8g`4ob8EkIETz*q zQ@zk08q2StiQsf>gO@sqy`*oiWw@l7LnS2%CztE2V~&k(n8bhQ_)aL}9-)jc&7Yx9 z7lvj8q^uopx8U{}?+@=4e-YZS!Wu551R$loAMJ@xh91x8!%l|{8V!?8MorC2{ta1d z8Z3_LoPIIXuJ8JWS^_JDue-3^r~e7?P~k1Wama#Qa!ZrW8Y-0UgYpjv<&(GaBd!?` zHW1Y{oVU#C9`d>smxs%K3J?;@Dn$N2nM62@L)lp<`}K>|&oqcpsGpxqCSuCLb?UqPD zz2DJ{IqwJluNxysGWk9IjUJ^P#OZRlfU`OQ0tTz%NTil@Oli~C;w91vIIdrmmAxoCo9OD6%zRLx z_c5b_&*Qe5BMqEU0Dk=h|DoXJ@#{Os-BjQC^x?A2OE1ft#vCJxdAfJj(26$Ln{;^# zZtsVgK}k;k8=^&eeULYuAMaX&%KbmmgOWB!2Y(m4K;%L%St_@Sji zmnXSm3^BjUV~%xpjd!Iu`o{jpwJRhsjC6&I<3Vmuw9R*;xP6rhp^|| z&)6s_&I$1QJ*2I|yDI!n`#tWxB77Zb(~uT`=OH{FxN6wc`*oLSv$o$+*86am8*luD zk=}$ed75>JG=I&dUEbp!Af&JBGHT|w5JpAvqkv7D2Y^eavt0_jD7~R;aMvcP~Hb`aP<* z{qkPdZ@=Epy7st!bG?sVu5zQ-;aTiph0ae@??tj!3A1%cB{#sXjln@UW@E5+e zVC6KjcTAIi9jzd@;f{m+{4)J-vp>lJKZSJ&Hym{<&TMsk`_EpQ@#ng?byW&0maa?D z@)<0&Fs(D$smaX@sK2=jmaO)dXVL0GxK8Vb({ZNv>&wGyihmt$i#LsW+D*F-VV3#t zgTMCPWMFuG!f z>bcpY>Pe3q6y>biIvQScX?4|D{o#ub=XVH6Yvq3}u#nKCswO=6rzH`8&p~_V1=^*U zzOeW_<0qtjjt+B3!pO=lg3KtZ#P*}c`YQyTA{c7 zj+apv`SiYZXhooM7WTO*!bjbaLlog(-Jp?u;?9VC?tI&Qt4)RZ@ge36!(+s}k>i>E zBINi8Yw_4Ir}iRlLP&d~{q(yYKEv>g!TVUmUp>HBIle#gJmwnmdC#1U!v5}`myDXX zTe2XI66x@TJ`OM$6zHO+%x584_`5Y3(z2gS0sG){16seP_nwX`>I2VySd<#5MK$OlTo$sK4wm|apwa>D; zS5}$H=$h+3-8HUq;{i|jobJ8f6<7C6?V{dJgvBC_>App&(6_wUb+7AfNRPU!%Jn<2 zr_NS^em)}n{hdJJm-RdZn|Sx??y;3FD$U*kxzO8P8-asi{F`0MiE2IoGjuEQq2_Nd zQQM*UZeH&yud|z4@=Z@9za>M-`|siGCak|CfB7?PMfo?~6QSl;MM>=M)AtvAF$1Tl zT690O!>bm~4x?&Eflnk~TUQ)y0{!g;hZE4`|D<9M)f0uiNjx7>E5SV-!2hYy@a)I5 zR~>1>*sVrs#EIwYY5sGtgr=yc_SNe;FF=dgzGLua&==wyeQo`a1{{2qgcd|@UZgp3f+ zG|WZ#CSnWguqNX7G=$-l7tcSYL5~(s4!)6Uv16-G;YT+TY(vpjU-R9rG4ltV2;PYT;^;yBUzX@Q-}D~@OTzOdac zlnI-G&hIV>GsLv?@^V+&7tTwUh%TS=EBoRWSK22|!WRp?6)xB1cF`!c4zzc%3G}OF z;FwM18YS4nAdWpgGkt`0o5pYgFo?SV9;;8$vR`l1%w9wzxeol)?=c(1arDJFHenRQ zaPRbQDrd{C)TW3>g*{RQ&Vl}Amd=c{CAnJikkjdSyjwaU1okG$E+x^W(WX>bpQXD8 zY$8!5pL(J}J|>@ioV`TY2RbhU(*z3jy*b)dQl7K?l20S?#G$qR`>^}j6W;if;~Jnx zxOHbA?SAOjM?IkeZF(QDzv5thJ8hC=rRJ(*HF7eO9ok<+H3ngG&fb;wIAaaZfJQfi zC&Ji%CSj}>zX?a0pGCL}`V@$ZvR%<$>Mcud&3>@;fy^s8>}Ap^@5@~bk6&vHTXV^7 zW}6+CS9NE@8?1~Eo~AO~0c(&JNHG#k ziP_)gkUYV^ThzMqfwvRR{_(&>NRLsHz8A9kMqL_i#Ev}gVFu3rn*q@egG{|#-{)xT zk3jufbD4IFAGA~p2 zIjZ{Gk^YDNHvKby6ZfRFADx4FMSD`(e@f0_{lmH^M_MyN<%zJYuo364oZWAb&R>Iv z&R<6f5_|g%fczOL-CpHw$5bZ z$yx~)(#ef!wsIddcWTD$vT`T~oLL7`TA?Bz)+wFYY}L+mrK>ACSaN3vwc$6&$E9a> zs4bfiXa5`eS+jMTPo0G+pX&$~fyo&iYW0c^KTHvYdQXQ8a0_qS-l0&h>j+UaTT?=ttw{SOT)n+R-L~#@2;#~7 zHnURFY?h|4w8$d2HKX3=Q12mGy2Uy!ePzceDl2_2!R6y{v{|h#=t!0|TSFv9YfAWo zLK_w71!B4c=`y3$M~QOL_7voE|0Yi@+)Ql;H%22t-zD7A`JvA_o!?;0tu*E;jDZ^; zq%>}Ad#zIRPr{lxDoe^ztmtnT`WuG0>V=P6t;iQ?1Uxw<;2*M0OZm9@dr`->Y51K+ zV^S0TU}x}{ZJ1BZgd<;3eJD2s=Q#Xfj`Z}xh_B|Zx;Ur_XQ5|35bc0|l zjd4!p2yeOU=FVw=0bANk>77rb{lAn)vP=m)$kkE4dgL>zTdnVgG+Xlk8%a>J)j2&h z)G1313kuVOqWlnWDxDN}*A=v+xl_QYkas$F;CoJ8XLY}$`UxLB(aK!}F#b<0i@T?ckIT zfwmYi)*8!E;I?9ERU7d89lZaL+Q%%-m`f`=a)8$}Sry^O8A%9t8t>Z~;WOR=Ck5OO zbmRWgf)3>jz>4tS$7sbZj1CFL=Rk0sB_;fM%MQyk)&s$99JN816O?~C@}uoEFHn95 z8C+3`(CwT|qk`-fV)vi)lXgq;W0o!uxtUGe|gj@!FA-GW+ zXx>nN=pD^Pnv;|Vun(Z`fpd}E`Z_CM6p3<#IVoMghw_HdJOkYrDyt@Z+t6I3GAVxZ z*lj}jzlLjT1YFCsNG%!*=BSlud^YMQdd@9x?$l0u&>A~uhgA~SY}G7((5hbZpp_L6 z41+qP>^8LJc5Wd3g%0WBois-#A4qPsu2bWE?(G)o()TUyIOmHw_h&p7q+7nQNOJY+ zpry?k1v6^gdA#2p{gro#+^>9xcfOVbnl>VoJ01`I~oGw`-cM ziSM>r&toiz?qhr+nJ~6!-#g8nUl2_|I?~XkW~qBlEOI&@k+$7tk+j{;Jl7L~x5OIM zp&9eI^=SIuUz`uKP_D1#L2DX95jUm-PiAnSVZwM*JBU{P586fJ{X2vhYoe*vNAL}$ zVU3BTaoUJ)-0z5nx$$cWzS)*uXRSuKW9c4iKEkbdF9E%g1K+y$JFiI4Ua4UflYT+B z4&k@nvYM@yx2eh(*iQuUuwVpl-Ptj0BDcqCojbAT zf>v7He%)y7lI1gUBB0CT4xQiG4g3Wgn}8b(LXPjw zz~dv%FS&SM_{+jg_IQ7@4>Sj47W&IsWcUlMdJ9vRFVKGs-WZP#&-m;caJGqaKK`*7 zvgZRWpu?Q~GwfhSK?^{e=dZoN61^x!kRp)oCA=|2o>p>uCi5Jm2)ms=F;}n?+U_hi zG#Aj$n7;ARMqA>eA#*%uDS-Zj#p$SUGOeY+Qlc%CLKYctPQ|fcr{l2GU#rg3>6Xre zot1RTcNg-h^HluJClk>&1)d;0uvLZ|<>&nTK3|yJN^6H^wSG8}|uDK>sbk&GY9 z%ToLfrN=@_X+JsW`-JofUpnc)7mJ-+bzA2JOzew<)_;uBoLchRm+i6nc`5Lhkj9fO zeQlAXK?BQ|4GZ2Zme$EEl13%0A-`5E*;85I)8zXSEQvhHsU`bjd3f4=_KgKBJ{%q+ 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 literal 0 HcmV?d00001 diff --git a/libs/mips/libtun2socks.so b/libs/mips/libtun2socks.so index ac42c4da6d6c849a5f4cb0c7eac6225b61db0fa1..81c1722e78e985a2855ca48b75b46a082f4c8c71 100755 GIT binary patch delta 38893 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 XL0WmIJwNG$4__BVJ&}j)JwN{sk^6az delta 38383 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 diff --git a/libs/mips/pdnsd b/libs/mips/pdnsd new file mode 100755 index 0000000000000000000000000000000000000000..eaa189832764e86ce264eb8805484ab7c493863e GIT binary patch literal 334632 zcmeFaeRx#WwLiYjnVAqmfJsOoS}Jqo%p^j<@S;vzTBi~;LaM2zHr|^y2}vN)kW7=H zvCXYR2r+7s3E{=q8+8l>f`m*|kl0epMNmXk^kStg)m#-{(MF086`9{>?Xzccg5KY~ z_xJq1e|(?k&hzZ7v(MRk?X}n2Ui;;o+`TCCT18PP{IgIran8{~G#@Z&ijBtDDQiAC zD27t#V!DW;aG#%rlLr+z*>KN_WI?J%KAa{Y&xxPmHb3_^;v$@qaE}u|k4EA$=HHPY zT8R_m=coKUWvnfd4#yH@T|$B`ey-yA-~?MFIZ%NUj{*1H&$^2_JWm<9lKGIQnZxi4zk$xxhAqmF)uDMj9kmmOFt z^B)2>$?JcTut37!170Vu8H|&4AI0@lr2F`${5>n-#PAKkkLC40Buqg4TjcedfQd+( zkvvG|-)>|+KvHFU*|@#~X)6-{N|1giu8cp=1AHR$j{~lf*E=QrgM?x5E-t2sv*NPk4)UpvyjAw7UJ9_b^b zw~_t>={OSqE=S4}S44{>%mKU;=^B}TRl?5z??GZ4_?f&{3izbFPG*Q_gEG&+hxE^U zf!|w5tHqV^=M+Fc(g0F5693*o%0=468T@WG04zNZXLcAw7p={{0G>r;%pKn_YlwkS;~)M(Ra6 zgLDN_Ez*}rS0Vis>DNdX{vMP!_FVYje~|w!=>DJll4Rit5>7?^+x`m#iKaGmQ`w75 z_f5COf z@C~F(kWM1qij?PRKli zyXAE_eE3S{@0V}`;4!2+r1eO@MY;ire_tTIg!BT^a-=7a__x*obQj>yk>(@)4e2}R z%R<0INE2~A7KwiuNY{!h^d0x2ksgux3&D?YBVOK|EnyMhr}8>U;^b_UyvJY;k`-wT zXa1AlPjUad^4UxYQzeWAw3%@8?I`5`E}t{F4C%)*Uk^A1&!=&c_ZZBT*OPJo|HN++ z@Y?==M$9oF|120_nt*)%o2u}c@!;kf3&xM@Eh7Hl{4HQ`_2nuBP@eO50-hXW6|qYk zjit|ktNXMn#vXpodeM_)p<}?y`G?2hhCSSaNfd+pk@+eOqaHuM9YV|)rxMGV^Q%zw zbfQhjHV)CoY?N=hOd$v8;^*g4KJCY_Y&Z(ezZFB2eYryOW&Tmr_d+p?#v0EppnuQ5 z5fz~dmtTVC!zTP5XQ5W$ z<@_?V=YC72gmC|X-#tsAsgk}4Y!K&EDw5@!P~H)1p=_Byf_k2~aQ`OJ&+t4p(%(e7 z4EXGjS3AnbVTLdVe5ao(q(5!6&o=5toR4C7K7l5q-L#KXN|F6hVWjPLOQijO0>7#~ z78;WDJN`#<;Mem$@MB_$$ToFpL>$1Ue?#Z z(lRiK#|WnHX0)GXqVHvt?+5>VVSIR=@_m(bKra77-1kKEYa*QieQ9XVEz5rn{DYDH zO{Qlru*U|J%Z#>4d5xt9@Ej9m`5QwYfzJ7+`W%a-McNxrjp+9=80C80XL|66h9`jE zGJhNBoC^P#Bl9moZUK`%oq|3@NAM@o_t9UEN#7qpp5iU!mHbtpUnfx>Ss`Dj7Ink^ zYDIn$y$E~>Y0!Vk-_HRTMDS0hzkY2V*LxpRl0!x*r+{7=x{ z9yrNriT|&lr+$Hj24wz~3-qBD;I($I*H4bHB+Rz6<*F?D{TVCPI5OW?BmMzZsRQ=aBw#;^{0To ze)z{+neQJZuS6O`JMV%&V1wY_F68ScTf{ma*KY^^j-oRIQr^+P7yfZvz7qMV>+ldi z&PM@JtSNs7=sMRn@_Z8dchZz!2tFJ)_t z{Pk$B)|CGW_{&WB<0zkN%BSIZrYWBT`WKk;`_ac#Q@)k^Z_2+5dSgxbe+IsDYe)M3 z@2G#$lwXVb$4&WT;KyN8eme4dO!;4co*q+v8}N0Q@(&^3WXdlF{#sLhALuJHG0H|1{uy?adgKO)~_%Kt0c?=a;Xfv?Gw zKZ5eLru-(zyUdi|!u>bpZ$bS`Q+^Ec3rzW6g1%H!emeLy)s%l3_+w4^OChgw&8GgN z{7F;(6!hb`DIY-5!>0Vz;O8DweiQfKlurbG9j1H`^_xuj+1!6qejm!0nev;E&o$*8 z=wGHO{{r$0O!)-RpK8i~jQUee`9Gn(SX2HSo}X(P>HnMH_eoR!VeY>vpN#enoAN(H z`8}rmF5v4i9|2_1r!;~Ke zy-lWk9m?05@>R%}nex}7Ke?tn<>h7FwCMU9uFuZ<@l7}V_}08U+_@lIR=Tt>ue7|h z8jr5UGgHZh**D&lmwElo*`i+hs9a%9L0&<1aSiHKmXyz}s;;DERo=?d^6F(&Sy@<6 zSW;SDTv=9Hh3AzkR+=(px3Bb87c8Z+io$}j>e3a(d6k6f%lHyy%L`T%S5a|QVS%@p zu_Bcfms3e`P0`8~UMejwuFfm3uJCew(QHw9RbE*|1+Y?4aakT`OA4w=@O*h5P*oKy zFD5VU7Uc7v=Ho zqB{$?&v)kWoycRO`pR;Fb6I6^afFV%r7H_>FRrH1H>--viVLfYM-T}7ODii1iV6$B zvoKlWc2()}@`5rdFDS35Dl0Dbj(%#;V~|r-v8k%F%H?^?C59`imeY!Y zGL)tj#VZQEcL@Lv7cMJ9b1a1AWfe=&ZdJ9H9~V}FtD@Sn3NIwG?9NI^6m%>{#DZES(8g^)M9 z6GNsDW3@ML>0N@mCW$ffrFZ33-{pm-u(|xY0v*oFtGX6kU^6Tz%R})>?k~tH{k1Gs z#U3Tk5G4u2WkHoLH$+vqqDU~Vw4$)O%y?W2n?^d69)h)SC;1$R1q3t z6R0dMyn`(wFRu_Fue_$Z1dR)YfrBV5qLoG7syySept>4DF0N)LVlrS*19RYpU>pU7 zg~i@#sxFMwLKS!>p`=CJrHZmUP+D@0Q3(!Lc&qcgRmCfdDp;*q5ttPfcb0=<)EA;K zyk2o(#R`^Km7%$1BRxc|%F1f5V7YOdIn2oN3dK#nsuovyc@albR$NdH0eV-$b#j4X zQJ|{0yomXNJFN2{4=nmd9e88G8rHIib7Ecc78jN-D=m!N6CT)GQ3j_nf)Gkt#GDG7 zh~bf$;}_gvEv>390P#X3VKRz;wNiMg0zsmD$a>CJFO-Y@K^hdRyrL2=ueiJr3KZc) zWkGq-oGanB%AqsRrgAuDp%0)DgjKPWBZOc`!m||>F!|ApT z*X4_%rP3OZ5hd?fCdcJv-j&sbv}_rC7CfNA<~){cSWMLwE4^N58jqiH+=A_ZY~fJD zHEu73{K6Sy;H$2@OEd*!-aElr7VmOc4ZunO_6IP&mEI}{VR>bNw}h&g?G-CPez~Ns z)Nop~j42YludWbsSXPO0!lek6FkG+53#Bpgs1$A~k1x2dz{1+%ErpX2l<@<&W1Ijo z@Ku&CH!g%%mri|IDF$03B7!)IS9q)MVwvH(ps>0W?sesgf~t|gL3jhECc+YN2UQFg z!6YEA;TWT+wCZ-l12DEKjHR~=v_(bSK$xR=G^zpER9>OsTnbByO5q1qdgpS_DyxNB zhAo1}NqLuh&ApL%c09(|1dfz07XgD9yv-C9akN!|ri3rz+IilB>JnO3Q3*T{iIiiW zXis2Yh9Iqc83{elgSN79Fmf-7g5RtF00;tCFn2I;Qt2|3gGSxKptz>Eu#A?K8zV9k zSy@q0Z4fFwBnkFQnv5Y!__>10O2lTB#bt<>c+82604s%AR~CCKz#SvZV|r0k+>ttO zzQwggpTO4@7{EmLOUv&lC@aN4j^GrI7UO1NNkRGY;s_g86ja_G$p{M(^$<)~RTmY` zoH@Iy0z<*l6%rOoSX9OrdCL%M!jU4tM5K^cY=FF_@Z~~)c!Fy@fcwc4w{az6a07;y z94HHG+dLb|kuYDv5(&K$)=21+uu;NR3EL$MNZ2i5pM?Dq4oG-V!XpwMlW?Yggp}WNw`zOehK$T zI3VGE2@gtmSi&O`9+mKzgvTWul<-{%KalXGghLXZmT*|Ya}pBvsMzmXC5)CZRzkak zyqCr0k|dlep+iDl!W0QpB}|iWzJzWG7f9%lFkQk72{R?kk}zAs90_wJ%$Kl8!V(F~ zB=kyHEn$s>wG#Ryte3D+!X^n@C0s9IyM!GQ1|-}pVYh@m681^BQ^I};_eeM(;eH7Z zN_bepBN85!@R)?hCFC;|#wuQ9DE;4y|K-5{a^QbC@P8c#Y&3NN{h}jT8+_1GbN-LX zCCU>)tu;XDzBT>@z6bptU!6aR_5|~lzF@ubOwgz74c02VgEh)i!D?k!(5vhWmMKpL zi%o!`G0udCjl zRBAP^D*r;KSE;mNMhpdb%N6~27;QX)_LFq?L$4=m{ixfQQ_1%)1CI2EPA8uY<;NT4 zHi|xLl8z5L4!Hgv`mvxN$I$HPzrTt6P1(w(pf>!D5=-wUGrd_#Fvxx6dZHgG0nrce zg0htD{%qwj=Al0YebO>+Q<%5Wlma>_F1urkp4IVOvbq0SickHn?7u>1U9n`-XW0Lt zs!1m*HOG}|26*M5uH@q(PlBDI^mdx0tNk~lPxtsW9FSpLR%+N7?nlu>C-kurUnZV0 z%~4d}5T-fZ*C6`sedvJB&zSD76+><;BgPj^4J~1OzK3ki&*k%2+)u!%87`CV^G9UZ z`p^mINm-_y5_PrjXP~d$uMJ%(=(E#vk+R(n*^;M_!RJB6;BzQ6R=3d$_Vb}}dKA5A zPxm$Xv0Z1+>1c4K`|jgiWqV1-wYYBfdpouOwnXsldFX)iZ7H|I5??#LwVjG|<|Fr+`N%rOJgM#I)YE%cG#=qSE`rln`}6_mIc1q(T{dg^`Q{iTRWnX z!~7#9N*~du2Lv7251)wetu%sH)z!c?m706Lnn3UQVuT;K7krD+)ttqZTK=z;8fsoO zfdYx?z75c+7C(;n*#jNVIR#HV^94_;A9f0!Bv6!dNb(Lxk%f&`kK5u(_l>sY`iBp= zG9olg)YYLIE46`FEqBqh)m9pulI~lLw$}Jr2T)%RbSxXC1I*9B!^N(vA~?eG|4jWg z|Efr8e}LQcK6s7eZgw0LLQ|$9u`#AMT&vpY&}*4;Sm!2oCrU z$IX>m|6065^>$qpd7w+{{R)kN4PJ-q20ym0?VCHEu(VphOF3cY3;9CSPu16Wb$3@qWz3V zY{HJ&cfBm@HqzZK7s|E|{8L?>$-{#GR_byJy1WmoOm_ku zfZWkn(9Y%mJG8$eX?H|uhfTKLTq*Rv@u#AlI?_#ge~-}nJ&#~)XWl^X?NVMo(s2~o zm%#d#j`+>6*=vPQLaZUiopfKTsLyqeJYsVxl$jD^kHuO2XZ${8uOBgN*P6*%}E#jXE%w*~FJ9y}j<+r>CTp^UT`+Txl{_F1~JIf%1D@p#iT$a>}*jwZ+J zTXiiX1PRS()^c){Xz|tvOYH6z=7mZhC2J1E(ka&}fC$s5rD^vfsvg*Oj$?$fKv|9hWifxdr3pIXr;)=i_G z`*kg4nZoil>sM(+wuccTL$+ykp!K<+RAvkn@veGEKWDtM*Rbvo0jc^1P4-lJ6D z(j26uV2ljY`=bc02cQ>0%zZjht{1Y-f<7J%Y6GC(F%0_e$EnfpB=pHD8ezYhv z(^^%#h?|X=i{;F^(0Aw+$ewkw3v|1jKZwZJnCD$cx7L~s-qc`RTzDU3=O06h?;A(g z-8Ydk?wdr{;NHUDsbqsaKLa0>@jE+R^Sfxe?sryN{5uP+?#A2t{bT69ZY$k~Bl`Dr zN7Ft16REK~mKysLU`LavuAAj-Cr7-U>iS3Gk|sg#{zJ`pHHGOd2E7f=A4TZh@eO@s zJxrh%^qZj%c$*jUNrR3PY=Yw)o{t+mIC`i|^1vo|urPwN=NmX#c0|h{x0e8KfKI=n zYXhHv?-Ovuc3~UKQ6bAF<_+sR`!>883>`0S!MLTU)CpZ&9Pu#+&yV;Q)^W{U2YEh^ zcnI?JEK*e(EA?=@p@%6m6}+{h&&;=5;>ibHWO+6qH4FZ{3wfp}{lVJx2c$pT;>?Wn z=i6n9^5{#U(8aJ_3jde#o)K?2a#Z#)4@p{C=U7IcLPkcs*oOA&MElaWxTYSu)|rKN z-^3XI?x8##Z*WTg!oG-O_Eu4T_|RfOC-jefx9gS&t&jaDyk8F8%YdG}0GczPYae4B zrW8Cm2;Dl^Z^c^;QQ*6k4hL-TLEH};y%ZpNS@@hNdJTTzHOQly)3ChfjR*WT%xS8JhDz6C`dfOmqnEGO~)LFKJ=k(vUewZJvnf2F;6x0JyN;2QB=CBXS@zKe0(jj^I0u?y=p`rx15I3K*k zS^{DREhSsk98$;A9O&C?@KbTB=Kd+>*KCW=2W{k<4SF!%FmG9hxqpTZdtMCtq&1*t zi?b@yw{O>90|)ns*Gk6fcT4wWX)$&XS(As7avSu-#1^` z20Qamn$j6$ePzFEr|uy8UDjjvy?6a5JV0GP>iJOz{j3g91C@qgftDLBs7W-%c;f?e^Ogq*_xA@0F zcJ&y43_EDkGMbMb6n@Mhr0SC4cZadtIg6P4ad*1A8pR4ZNU z)SIS|`lEPK(~<5&g2z{AcPGz@6qh6r9$2-SRS7$VJb|%sO z__5T7=i~GgdJ&%oQgt`&n~aznZCAC7r90Z9>8>_fI+>h-2NkMIAoaEca)R#)#)VL5 z_8j{41XA}+AZOCB5(@n`P5tr`yd(D8PB;nsSh~BD<3q+fj>fmeP*fW&9#2j$!WdIM zg?8bkGyQsfdwN z5vwFoAJ)Qsq_qb~3k;CfI7klIxRwJyWxpMAU&wICQEO~snxX{AGkjei>yIuHYmb^cU%eP|<#xP?o7RJ7JL-jHnZD$Eq8#fz^Jk`Ag@7k+ z{I}34u@;24OZjaM&QVnZ6!q=sFRLo%#7(d$^WW%!aLw0`1&JQ{H zAwNIl=ZF0KkQwyFkbQ}iy}ocn_PK~hE|fXT8Tf_V!+OE;XW3^^mQQPh>{}uGcE~<3 zh_`Gh-iNlaHl^~q57zY1HU4!qaUXcU!cK$n^-?BU_kj8xd>Q7nGN^Jt><<36h|eAh z)$3oQJm%Of@R4@tm&#?q4_rfM`hg#LukT^#+5|nCwz*&@mh{;t zW8iytFo7NmT4{SrJ>=PlH{+UU2kc=RxHS%rLmA9^Ok8j z5u$k3pP25~)ptU>Cv&_1UwPmCV}tiT*j+nl%9XsXg^ks~2CHF%Uf5t6_+0|MDS{p5 zL-%sP`xsifUZIRM@FR|Oa~t@=bc8}~*E||~d6$@nsd^9Mc28CkY5BJy-frFyO}(?C z5Yr5Yf=-ooIemSJ;N=~7Tb%4x8fr1DwiSu^_b^E=D3fw9@Ute^V)UPf~PZqG!?8&byECr}4` zsU18|fL&Y3-x8pwVYltDEnchJ4BhAoM$-lt`is7H!LL3I-3h`M>p}Ij zwDZd)J{L6#AGrW}>p_Pt6a$-BGV2Fe3;3F1_2(q7 zLx|6YLzcKu$mX0!n^P}=e`=?#{uu0`D)fBXMTm`i5J!75Y*_2M9{etYoi)SG0#025r6HiZ=x|`E9tLmAI|I+YX)P zSU&}R3|AA$Veo)-;U@56dRD%H2_gujJN>6b%iVv;r! zglUh-*-u&${8tW<$Bpl|VBV&cELY4lPNo%cEFYrM4egK(?3ZJeVE2s=I^EPGXtay5 zYP6i0wiM{W0*rAe2fw()37?(7_7CF|z6ZgU7#rr%@GLluN$ihUU%0(?*nt=83dZ=j zca#nxZjA5|e3yH*4wZQTyMo>Bh28Fk-981o-37bdiJ0R_#2il`=6D=F(y(K%wB!Eo z8+M$7eSl2FF>J@1vDV+DJQ-}n`hPvv|9x2h?@_vfJC&`$fU-B(fqjB@>=UfVen2bs z3i#|urV;>MSjhlP=j+A+5&QNdmS_K?wR=csAEl@|DaM?10p_b7q*jX&k69^weUGx$ z@1r&I?+ICSJ#7z;!i#61^OE23iSLX%K6X)%&W%F(Q8^1XW$d12XhE)!|FZC z(|%{)1~v4|C3rsErVqcVhTgL2u{bAym~)+;bONGx^@jdFMyG3%NY7YK_~KtnXed^9 z=2#WIBo*sgOEz2SC!4XKidT<4_#A;}Gsca$SU?{0taOW0>m#h^ChD2W?&L)@5O1Y7 zF?X2Xq76WwyvNYSD_H9qL>#Qjwad2^Es#wMFz1P)cGt{1#J)yg z1HLJ>S;WLVM!O|Xm_G}^V=fEY;lDQ-Ypj7~@Le3=%D5Bzi8Ey#qBl2U4OmsLxdi233?>xhg@mx4WiTY)jbAvGa4y_M`mN-M9@;RRTabyYI2w#3|mIgW4U=tP! z&BBfyY>D z-H3i9=(&eoSeF@tb)DB;IgpPVd&~LC7M!Wt8Z3cb^ucbR`#~sF{D7dr*z?2}mR(Fk z0{GyD{_vTZEM?m!L|7a5qgSma=tS2>$O@Iw5?ImN5Vwow3#my;k6x z6uQP(lg*f^%*=nAZp3=*^n=$4{X(2JB^3Hz@t}x4pytOPK_7B` zZHTL`+h_ru2L1r#8h|}-PG)+AUSfa!hpK_+$IwIOiyJb`fxn2MB^%+RHhO)l(U-D0 z{n+QsRC<#$lwfkY(w`hN91EFqjQp6?8J-940IfW43Sulp{EfC2pbg*)9=Yi*WAE8L zU=Kf%5N>v#|3fVB+7=WALO>P*XkuDPL4Hu%p))DRy6FBVcG<^lJ(LZLHh^XP@y z-^H8;41}!bLRO3CUPPY69*m`)oH3-8+z-Ffi@56*#9f1kyN)65+UNA8sn`>6$+*kb zoJ`X$A1CcPm8L^h`F7ty%#R#*0rQ%s@O;%yTbrgMt~1)Z679V(cN*pqoKK*+EmN_l z%GY+frR5^{WxlrZzQ3||_C#__<`_92^5J#HBJivP>wj!J`(Rfr2j(H`pm}|f^IXr0 z^IGh0xm+|IaD68AH5A$aUTmK`kIH6U47>RnF@T2(PZ6oFcJQ5gI~*e zn)U92IJ6#ds1<8dPMitj@nw;SLl=NwTsM{6E#KofbQp1H(lpCV?j994T|~{3&m-oF zp-a)$wP|UX#~9^PTHrK=OrmK_GtSZo-)N@~n{>&mSc=E}5ngFDfG@~RhJM zigp;^#nd96#n9zwXLt_c7kr|M>AD){*9>2bFH?g*`LdlNe4^4PWMriiIKLN=_qR0h zoJs|+$9dj^T%dD(hz0<;ZN?cxm!XZhbJ`To-|XEn-z zpcDMU+QzGMRrvK<c`4d`wi#C-HBd|_=G#{1cGqUf#oXgcAFLhL*a>)~3X z_@1~OXM$C}W=L4$x~+7ohu7EH=A!9s#BCpL#@^#*_;=v+$ThY>tf$6`u^jtj@mh`t zG01rA&AlXK$8|Nwofr>fY=re!Zm(aiU4dtO7RAr&oILh$yb$KOA^Xu|lfmy@uEg_? zM)7zZ1ARFcvbTimeA{^T0?LSbUmGz*I@Y>*Y{of@NjyG-X;_0jg1sEV++!ogv%T=q zyOXgF4&S~rc^cMqRMK`b>8>_-y!-9OWtheefF|^l6=}gP1uX7ja%Xo?(wZJ`-c~1kukwxp*wB zrsNGg78&u4F%Fu?z~9K&hR>-ojtpgcGS7oN;0cfQJTB)e+k=A`<5^DlO83UEL+9sW z4QCSD=ef`uEq@LT#%q0VM0gX8*gWjF#a?v3hd#%gllvM&nXujFIn!~*k+H>MO~xT( z6+6AsjCF3|M`P*O296^*hOp9s=4g7hd3stQ>wU_&G%HO{*@D{LDdSS2@ts4g)hpW& zBaVST<#m8ADTgN@2VR@TUY#R=bpVH|Ax=rXLC)bY9;e9u$IwUc2TSI-C|}T(f-i1O zhu>ow?bO`tz#0Z$$5IREdSwpi!dhAb=xT4CKFnW^d}ro3dT6`w7f zia5|N=Kfni%T~~~19Q#+%T&ZQ9N&a#i_ircXAWT}3r#c6SZ}o<{#OQ<=wbcGIj;-+ z)S%iC8koZ6$8dQc`~;Gf=C)bs<}3N0mF9Kwy>JW&y$~^>2Xn{pJ@y@pBb?8;AfJgm z1_t{c*c0Pocq{Z4^H={ZxQ~61Ud;PiG!NQ$qX2!_+Hl^17tnxh%#M#sz=BkdrSu0ed_vHLQj z;XALV`+y7oNu(u)W+9GxdQQ`M$0V&4JCDH2v~c_&*5O-?b79=S)u_W|{=2@2X@oyC ze4&iTKaJ?LF&=#s`p?HBtbxh#=#cK~j=>tp&uA%Vuu>&ru`#pq&JPNDxNpaRSM)7# zJ>4q$*4D!O#k|yywE#cX0{mDD@MA5&kF@|l)(!kvH}GTK0A~`7wT5o&-$j!jzU*zx zRXi9cK6Q${lbU@Pmk;1x0QWZO;-2?eC61n38&A)#rE8;zGRIH?9a=ky_OEs3j8&Yx zPJEjcdz*t6r@a~T#HkBTUuLXf49I=KG_l_HB-US^;dxnbKGxt;;rn>)!~s3$y}~4{ zL-HCVk6T(_06vuEwgKy}tf$pt&NsuJsOq4X$2t6`5X66<;Vj*&DB1>T6}MhYPl)&d z{KPu?9M^n~Z!)6s9>F|?*UGGPjZ;heY}7tjD0CC{TCg7CW<2kYencA)|U2Szil^c&hA6M>^)23&0Nt)_ropuN?3z8~n-w4?WU(?qj_FelOsuw=(2JoHxq?HU= zmXqBO?$ambgz z`>Ss=-_SPiZT&^??ak!aRd^R-72daT45*lgici!V;pSXN!$j?F@DA^>>Ya#jQhLL ziBL$LU&Cw0SWm2`ZT_jEJdYFI&`BN}2Gm+S*COvD`BdlvXcPaZM$F&m!}qHF=PPTd z6L_`)Pd8{hqZ+t)ZJ7OfckmPR+e-U&$QA2=*lUNbK(1H^#9lje1+w=;#(u~jx@6dD zzSNa~%g`0?mw!x7#~!55hIhwoPX>+sWFMttZ8hCj@2|1#40hPI2DLzdI{vaycMPr3 z)Bf_jUTfPG1W$rZwr7Hkw!Oi68}`j?PXxLAupE}3^3bmCgN7W13Mu0Go{{yy7w(E5SD-?tVq zLyYrE@h_Qf+u^qETsMw<@jGoiCwDgRJZh({6FhGkwWihn=QU2&Jub)3i5|xKCHG@l z8KweP|(g&&z3Xsa)>Pu$(5rm#*oRrBmcNwoG;7{H zIJ-T7YxY}F`aCr%z8`0{t^*BNuUNx6mqNP{r}Dnzh@QD^Tg2Yq0^8Q)Q;MN$3v4_6 zSF66s9@}1j0?JPZ4qoSB91Con$!^=;WX8qsI$Vek`;(R&*arKEY+EPWi$B{I^lyYe z$$_pjPR64pork{}MEy;p=rMfDpc0F@DA&Cg{^fjV(tJc~voBM930yY@GR0m5&UAj% ziudwdv2@ZkL%g4{C3qPc2E+cT)sE&BP*J`SRf*za?bI1im|>z4g|4Eqz@&+Q}qOgWG9vR%P!_yaRtT3Wt5 zOYKp(pEsahHgs))Z42sd2H#&w)x7n}NhOe|+4qC)Ans-3EZ~Rtj-mJO9Y^onJCTO( zokSt9=)(tNY4|}qg&wrh`wvFbI}cjug>5+h_4F8eew&q^e;V`LZHV!oo=C^GEwJ%i z`q&2VWbt>%VsG+gv}F@waK%_39MLx|EuiGsc7PwfLFkf{39m!4o@@nO z%)d?G!EQrOGTy)%*0xc+6FQQXPneqt9bx@Asob0ZzwF2VPQVzf>hP`LFWnepk`Qk&9}RuwJ+|&(51wVhCuumtgHO)e zHMc|U_pO6}TiMX01mfQXErOqjy}7RDKvd(~DEyt{uLtB@+C%FkU#;*{9`uvf7+FR$ zlZMoVO1@poI7^83*WxUvOB?FPcu}vPMce{=56&FEMEyQwz%&cLkupd;zkYrn7-N~|P=F~~;05T-&fsbI z5B6aenmGF+tY?juZ5J_EqGUMJk{78 zh-DT62lLEITT}lg=ScWJbhx(`yzWgsCg;~2(DFUzCzwI6NxBSqZ%)oZ8@x|_VSl(h z>k-enxF6?3S#JEh4ttD!NM&ElK2zuQpOmBUsXNh^okk4i@Zs!}hue{3(Ocr2DE{*w zzJ8y9xyj;yLLaZof&4M|4ybf;orZT8nBUx{N|^y}&yD9Sn{4$k~V~bN_O{#r$F0j3>+Nrzk(+)6iJg zR2p_Mk5P`-Zk4N!fD|Bcpbckc?(Kf+t zvJTlII+W?=^F&?18)I)G!yigLs$o3}N`4F~%n!69bcp*T`(n_5{+RorIZlUTQw#f) zY}*t5QMv*>v15+qMSQ*4_Bi|!=FKIy>TH9&_s4V^>oV{)L!QW53HyT_ta&l6P-y)8 zJL#oKJg>MJ^k=|_AWm)JGm*TP)eRln3|kND=TtE_z&r!=u%7b1QhkZBCq(!`FGSx$ zp``g^C`ZgYekkyE2A9BgS&x?>&t-1~?F6%e@ z0Iaq*%*T4?x7TeO9Z&vsk?RMMy6aK*friOAyU4Mpxjx=q(Q$rT@QCLra5DCkWB2Mz zOXHun>3h(RT)!h611@GH|xTG8v5b`ZUSv((RF z?RH4XvTX^zc8>XRq&E?5U|gR+2`~e(c$}nD;0%u$f*<}!pR)gYLY_+{yx(E)dj)yD;D1iS>XdupVHXA?CFaL3dw(lJFl6)*+Pl%*eCmQO^#a z?s968XDy?i9XWl#xm-2q=64;;bi{ss!uc#6fh?;r zjt~_!Iam5}v*taUJ6ejmil ztD(<}^#u`Ltr_*~^ygjr6_IBRqn^>31NuqChm4c^TC=JV{EX6nOo6~o(1E?}M{8HF zMSD&DXwXuk)MITJYeN=e?IxR&ML+o->n@iW`l{YlZHvpt%(^^Vu0IXts9VBWTt^ z^8><`SRc9(rv*;0k?|*~7t&ILH7}J;_|maXnG0XYXA*F}rR9{u?=9h*5U{n66^iHg z2y0iZ^Z%HZ)XkvGx@N@(7k2xWT+EFZ(o?H`g#8{~KXlgbN*#XP>84kL zgl_{}fxT)tN&KeyXC4fxb8yZ{d`HOrP9XI)1ne`jEq@)kHDZr6>(WoA&lZswup;Qwu$UN;SEmbvJAH0{S(1E0M^ z(!_MuVGho9vLz0_hqJ#;yifTXr7Vu0mEjp?3{BidG`-%!_t-{wEsf74c!%+QnY4fr zGhn^IOase56te3cyko}uSl~7Gd!}LEd`$9qJ|7_LInh6}W*6a`IXJ`mzFrb~r+zqe zH`b=R^m;t!cDW|wQ@n(k%Fd)1(s?Infw3met(o)_024|=@lzp;;H#H|h* z2*yb}H1mPWbHBO&;Wqi6(RbtB_km%XF%DvUoWGi`uj^MFiMg;r_JvIt zi#&8+T{hjK{|C-lV2!#*E5WxqAfFVv0qbQ07*1c>V!U7WfZ%TwaMgZkjJK^{z9;M& zd~EmvlN&xOmJj*@un#khhvCb@_t*z8Ev+U#VIQF3T_qs=%X;{hc44bgI`gdqG(z_f zR=T>(IAi5Az8A)6zK8j@XvcgHHuH^pe5RG@F_)Vt@3FqD2M;?iUUNGbCj?&)T#WM{0JoLSHfz3s zeD`<|d-6H@K6jGf??BQRn*PBi3(ou|2bf;WPX)brU&(0Cr*aIK3m$sD+|uOvvK#ZR zYrFC8Su_3{Gu}PF9`BsTG+XKV{#Y8fb{s86elf0>1USxOTtyof3BEKT28hRaju@>s zTlRtQ<95EyE)D)0vd@C-!}By=!{j<1%B#~uSX=pkRHDr-TF8hG9Kx56*ENh0cVe%Q z#|fq*+?Lso^E?Xce}dm(zst0Aq8_)w_GljeW6zw>zZ)6j8%I5}pRqY7N1ov}aE#36I zD;Kc{kD(Y+P_HtuMbtY5K5z8@9@qJ&_q)N9U9;o# zS*vqAu5pICm*d&+c*k=Z9`BOy%;4+2{zkMrbXGU)3i`H4J`0%q+Co}f$K{{L8Bwj< z0}(E5I1D~+MwxC?IV%Mw8+0FT_>1@!7QZty1-gp$9oWD@`gsCF_JxLiJJc_6)`aUg z@LdBN&I0!UANF4wj_?^h*gfaXdedjhbDilp>&Er-F&2bEe71W{iw*Gv+auw;zqu~n zpKTa}cb9g;2KwQj!#0bR|7OO)_gRPWt+Y|&`4>`WaIUifG{&>fyP9sQv*B!7)2jRY zVIK%RBOYT|Hf%TC_WZ9-I5}>{c^n=8d0FuNOz0k6rFT;QJ(O=}y7{{Sdt|?|zOuRw z%Xp+l`b^f91N3uI_sy?82^?D8Ec@-(*>Xp zw5mgANBrsiCCUMq-(0#D`qY>?`;TG~Y9H)98QC7boB=jQL2| zSB&t9{aM{8+e|sL2xq|!AHZ>%*=|$MEOK5Nd3OJ(XY>qv*az2TVG1k<@RV^P_*luXlWTLeSq2+r|m3dOFYX@A}BRocY}U$Quy5`s z$G|nK{Agza+6g?`CEEG)(Ok^Int+$f&!8gb6;ijaLYv{f6Ml0;MnA*0!!~lIl=-)h zy~g);V!t{tYW#Df4#!#Cmk+*-%$w*^iObwa$5&m>RC%ArV>5pjoLS?GjQK8`q%MQaYWYdOS~iW{Z~9% zD{yQ8kE~xhUH|=h#TaK?~ zXBLSV4DTH3i0_0haooeUpuvyuzCa4)i2FD{S9c_IDmjK0&Yq6FgPK(huqhr>Z76eU z^Q&L+Jn#U<)aD5O?lXq3V*GQy1;3Rn`gB?-@Q33CY)iWkX9)S6M9g51_=#rhm&M}! z#GV~tJKl*l$Iz#b@;J`(X&(Q*XZDLeUx_xOMW5eCpTp}72Hv4FT{_l#M7wPN^55o?X`v=#55SoQ4!zqL2Ko|AJn;+NF%lKz@i_XBr~{&V0} z;it`dc24TqLhxz3;L}#uap)225bM$pp(A>PN2`T?DEQVCKW{xBQtPMRM$Z=;egc+3tldtam|d#rf3*}5~h+4^KKV0|LkVSPNv-_;zj^82ZM$%xCE_FKDxWR>Tr zu*bve@^}uu8sECs@%>vtCwzN5;u(I2fi~#pwKwXdlMNaak!!OirWXDZ#mu#ubWIlCNNIV?z&YClq?q<>|i!@gCM- zhNoEA7qT8>z59XOb+0u0{`F>8|GEvXXj+t7ZQUNMw+4f?=u;#5_ZiObw4%Q%U9a!A z;yg;$SmO8pt+clJZ{&!tw)TLBvsx~}+1_mH6Ulb;A;tP6&Q0oao|~`!GuDy0FVQr+ zrN$cc&uINr$yYsynd|&D)}8(#nzCSecZ)jk;P90*hWp`v2Pb8%<8Me}jd$G^Jr+0_ zH~Yr~*oEK`zK1ap`pon8tARvc;1Ve4oR+QV(|)Wa`i3sSJCVOtaRRov(Ynj; ztHC#H=uflDAomjJfEEab|A5o>NzcUZO@EAw;aPv4OPPV7ab@cuXNF+-32&|yDx*bg1{Lx=s)VLx=( z4;}VHhyBoVVJ`z#KKFV6XT|olv7a7GueFV%=iBIF8>K)Nbd5^;*BQRZnN}&{Qm1>2 zGF#F@R;xZeqYjho8J8hWPSkQ#$TU{>!H!~Szw1(p(;YNPKOc(Mwc&h4vpW>Li>ow& zw?v<9B3j>i5OJ`AJ>5{~XIP7WKlS|*Y@7E#8OPyuPFI`6!SCoT$Ge2AXKZh^ z)?TcOH#_S>y>Zpn9pKq$J7*hb+h%)?$G0-rc85c^>d7?y@}W?^opJ1ko}^Mk)5*|) z-RHgt@3lQob;oRe-ivoB3H##F z^cKz^4&r+=ka5i^i#BjMY-!rMbJ*We=#Bw@X=j>@I-pC=*T_0X-yzHL_i(uk@9oI-U4f6wY{vYC@%2EInzv1vrv#wCyJ0KGE`xI7C^p`R#`iBAST9#mMxnbw&o^lbgH2GE5HacJ zPTnW-!LB3nge)Ut5@h>Ld1gSyHeIvBM66M>`1$vtA9#-@5Y6^)9jj|e(dzV}6r5il z#5Wb*z}e~d(VzEm)`od;*2QfZwwh1OSK+JW*&iQ#&4~Wwt3LQ3g>KTdtWMA}PM_iU zrJ(7%As^aYg1&yzra7KaaZWvM`p|3OQ;$>YKZ*7}L3{j-r5>k^K82qB9rikmGoYb1 zx^@Cl!bF?{RTXE-F`|p{J+OnDAhQqKRQdJtLaso1K3&mG8W$mn`YrN&f{^ub^^{6+3Ab6iS%|G&4&H=;0$NhE^_AF zsu0BLEGbj?y%d}aX^RI<380D2PoPPBHZ`4T`oKarjKx3Bo&=iaDbA#0#OuNoKLziq zFD0iNpQAv{9ISIqrLN%Sbz87UWSrx1;(d=d&Kvp!KGD#5AJ#>QejxSPknw($AF)@S zi?Ix&>7_P~p~uq8ZNhi`8t)b&jts0bzGLo8`&4;G;$}QYQ7;BQ%d9u-3s{!l?gwr% z>CMf;5A>YRk2mz@AkHFF+*sh#8XG}z3S>u+oi6Y*J}o8Qu=}*v==Twt4}j*?p!uLd zGtS5wG#hhbXWBt(lQi>qqYbI*^zJ%hnwj=6-*}81t>**KqwDeB-ad=axvVP`et!3P z5B%20ff#xN^bW?4V;uPpfZhkzLbvfwL%ox6Ybh@XA3i;8o9dUehW*al$ir}SBL>=? zoIvkJ)+*_|N62EowI4B0w?6^l?X8$)DSFg@*V#6e5v&v5Uf@58@v z48+e754nsuXjd}(nvpnYQ2pp@1NT|Xg*i_610css2EBt8UQ6Y1j^)Q=U4f)~8_%5) zXYF6b|F;Bt@>xeMJRadYJ(#%1ZRnnP{3$r!o5&>GEb*K-{PF!L!@lq!^q6Bkj=_(gG3Ei?m;eeHUfUPe~%Z2@1jq_*uv?Z8IYyThi-aS6* z^340czuycH0VRYm#@5vtnH&sJC*Zbpmu;sIFqWu@w5Gdx>QqtDQpIX(b|2S{929jj z6Cs4uWozV&O=b{L>9amM590Z(sC3t@sfyB8Em~V?Ynk8sbAP{+OgOZ*zvs^$>%Ok*zRou?;V|l`43CVeeF6En$BZ`1BmMYaY%M74{>p7v4o#`KukJl37i8g0 zy%~`T$3EiQQTQxF;D>V8>QK2em{RV^%pv; z>rEgv0{d*GxtCmzc(9fHk2pCCzedI+$B}n`Q>AMND%SU0W%`37jf+frev}+#@|UMY z>Vh=t6g=ffcg8i|vcpWptjg$nKhx+F6LK z94?d0G(4qogFmS@^Kfk&_&O@OShVH&ojM*dbyKFfKZBnupGV_ysSS34jfD{e0x4tC z9gCcP3y*M9f_hQ?P8ia5%mr29rY||F(eOz=28}mVN6jemkw+76xxhaEp}A`8#Gb31 z&D3+6Fn^*OXI?J(iONrnnxobTh7D#U?~KA;Im^EDx;c03#Q3@7CMCwk%_eG{*103F zxoa$N)3RMwR$M_odjs$fA>*xJoShxN&nN6U>b~8FYNg}Fh;P)q&gyhbrh)omwhy(7 zGCN*y&gW0WZgb)qeW#v4^{0V*0p^wFYsvS>^Hh6f#1&v)v1>b;oKM%hG3gk89h8^P zp2`|LQmgf7!zMH;dU4S@JZ9=b)7<|gzE*8%?LI9I6vh%T_2BIn+d1RpG&|@XJxgI`FkA4?g0;uLDVkz`rxV;eE z4%c>?E5Nf5^rjm4-@-3)JT!*}n>?EP$I~8fB}X~^(D^cSp1r*R3?wj^|4B-0@~z znwWJfcSP8WL(rL?HKxC>)Kqq7M0LbTCDVwXbu!!{5Tni*+I zH~byLi9l!Yg|Wh)@x&&eM`8SOiS?kjKjO4|6<&nnlIp{av@)7_yY6Ox|Er3BtM57=zV`RJ(*l#!E3bH zvC5@}!enZC35Uo5V6T4!Tzb=^>nX)_y~otWrn$9wW7k`DceNMZLN#&XnY8XL!Jpf; zpD_D#PD}6?*{9&m9uAxUPkL_h=gG|!E}mg=BZy4g5-rP{W7Uq%{wOmiq?D)luY6a| z`);4^M5nj=baxbP8pZ3#Z&L6*)l-kZqI0I*D{D)YfBZnY4f{mEj7zlyZ%YZj6Xs7w z?hEj{J!9n%=0DOL!?<2)_$D~%z4JrfTZO%}9Ns$~wmMhwE*4e>|JrEqQE+3;l9#id z0n-gW?(e&BAogd>Kn|~-Qk!MGr#yR&VQ`&SU|VjoOy(YV$HF>ZT{FojE#D2 zjN9_Qfw5i9*uEPayq>dT9{g?WZ|x&(*b?Uk1Dr2$b7XGts7ycjAReT8G4bGz>~8+I z2H(!y$aV4m(X7w=$nI)OG+&915HO3G$D6(5WIM+uOD&rr^Z1#?n+MW=q>Xs+jJ`W; z+s|d&z>(i@tupSN~DmphrUR$vjICiFc$qAqy zVs;CvySniaL66zP|_#FIb6=-*DqVj{i&SSy!-!JlAjo zdGmVSF)uW@P6*t89=boFt{Pp|HEwkxM9x_4JaR?Xa+X%y;?HPvN#{w_7aRc}7OyBZ z^SiF}_w+$JotJvajY0Fuf4{I?@ar|}u@P?or#&CB=u`Jwg14YUf6JpyYMT+032i2e zX!G09W~SkLPHw!OA8i&wlh=axW5N57Pm_@$GnLvX*lV#xju|7>+n5u!swqYv{FN;yD^L%vuDC08zxB^Av zx-t0#@rKmX1dku<-3k0WJbrr!9(&^o`~~AO{(#j=E5%OM%cZ3q`8DOc_g|R z+ZT1!qTho)^~^t!v#oYog3D8NTeiCJQ_HVR*>g9|M$T(PcZ>%s$$K;7pa<68!`l|{ z)}ys0;C%-;zW_R03eF#0-OC``Qym5AgMy zlVxrQzAm0Kq3=USJm*$$=(5AFl`9$JSn?JmXC#vz-&&On*FNpb84p@q-;e%hZ5rE) z@yc62V?voy^KImcdB_!4bmhs{&F9}~n2=jV4Zv5Zad9a!MH@23_cpWy??_EpcA$hk zE%RkyFS;AS8hS8YoC@b+Ze7P(_a4?mGt+hWQ5yb}hX17DN5rLUOT&ZG@Srq2C=Cw+ zPW>hQ$or+h@n0CL-YqlN`f~n!WX!kf+L+_0?K?}tAz%Jmw%4s|I?25vA0qaPd<=M} z#zTHBy3*yzHZu{Kadc!<)2+_nJ9SRo{FB_vvGM60%~v&qlI*31KjB&!U8*J6otl6R zlKE!hK5o`?W(oQ+bxF%?UDBV>Uw{5hyEln<{2%Aj@||VyorNCXX+ngueCOsOzH<>{ zx;*-O?9Lja$9JxW?*yT5kMAOz7U9gT$%~yhIFkft7W5rJ$IzZ)%&kLYQ?*sbdx!F! z+kC!r@P3;s;yWkUHK{k(r;r843D3fbT*+$l3cjKv@x%7yPUK9PW-d*eDBKV0RH%fsEmJCX_Xj>iv!1AIq3Q`ZNdi~D?sTzU55xxp35e13lQT=wHR z1N>%Q>Xie9{r=|U|8PWmw=mwiKG{0k*n`=Rhm7|L)?NK=Dt_Wz@;mT!+&7qGSl1Dac77cyt?n`Ge&o4?cm^Wb_HOAbOV`qIr^Y z&Y4|%t?jAQe4ac6t5X~+Scu;B4E)&Y5@GCRy6@5Z<mU-tg(qUeQ#=;BZZV&#&t7#{Uov#O*MX7nG9jMv4l~VVQc!sg1 z)J!Wi&FyuM-^_VQp<^{~W3s*2P1`S&?ox}s-qu4d`8(|&qUY=GXtNhx@yQf58^%{) z?-*^KN>y+MuG-j_4~^3^_!($pXX?xFTkLDD@_fQu66POR(|B;WmBkc4)EeB_`!(*x zgGXmQ{(d3+eP(p$ft>9Np4jz&4)j-u--z$1<$Cka#Il9PCAMG<$iEH_e5qvVfsmye zJ->zLWS?&%W^F2Mw+7$u`yFJ(eQvd19ImbN%E@31?;(lZ)ERbpZD6H7k9rfTgI4){SG{_VC6w{9%fjXbtWF7SCl^ zpT2;37M<|bu|4o;uC=d1Ptu&eWS(b#6wSWU$GVh)y=!s_v#;EH@3-iSA6Nfc`!nx(@5k8#U#XsEUS*HIgSL01{(#=7{?1{4?lBM5 zcz7`jJwURg`0_Avx_a=RT*Vq^l69P2T<*(|_=&Q_<)U-s%EJ3&)bq>n{H)}M`M90K zXwxj)8FgKHDk|{#jy6YQJIb`HjeXb-)IK%XXrnA$&jugfZ}9)KRypHJepIb+#X?nd z4zDT242m*O@#)>n82-nDmjSDm-X7p6807M=1_gug zY=ghmjEl2|E(0M(0h?5gam{QGm^1o5K|dz0&yn0F`fCl2?0cFu*Lq?d%f3s0YICz4 zcMKf6CB4t$#Pq%r`jvc;=3a=g-N$vw^H19G+-z}PdQod|L+{V*wKsb890n{q2f<*= zK{B*-5OU=#{%JhnT+ZF(kLO6wf0?!gqqAu@9?bVv0Ml2wCVnOvXRRH><$cm=R{w0! zekxmO_YGa_T|;fChqIr`)(Sp#nd4nkQeR?@Chz9c+ML2*;DFr;{UY3xFt6R9y<>&H z$4e%80A9DQCeD2;n`4iQpj+s=-jlqitWQo6K?uez4*})Gpjlu8w?LJsdK0IT+KGTM; z$J0rAEG)=Do+`V5>JY`IogXQ!5wY1+9T!&ngs0c8Z#^9x?ckuygu9{O}-m`-y6AR|DO~Fmw>V#6uXv62I`BscwuN>y2EnYjZC$HmZ9n2Vdy}=N>v`3Y z*F8O}u@%~2?eOdBtdZxc8iQBD=Ku+Rh5NcUJ6M@AyraHbLliskP3# z0bsqeSM$|)!l54GjP^u|*RU5Gu-Xz_)wbYTfM;L+0(;Mx$Gc23RSM@Gg`g3$HsDWV z^L5Oit^M61_{evyJ~iKiVWc&XtwA&!3&whzf)`QmCtfBPHw728HwM3*+HoysFhrkr zriX^J7U@VG=i9Lnj#D3hZXG@?&K8edYg~Z)Fa5ELkIemVkB=x8tDCr5=7gW+p==a8 zNIiCtTI?VZ>>we_H>P(QqUTHM1Lhd`#uzhps$?7SGx2}5zo~NuwWS`yPqB@?;+{0` zr+FWq;OQ`m(-M7)zwRv|XKY#nwMNAE?y)&s!Vke!I@MLyyX6l#h32Lu7cvEUGGLU3kYU_bdwS5Ix=)I48yeagpy`|(NSqtn{&pE_=j|cXQ)2@sBS{$X(VeL^pIeUJR&g#K`j-phCUw;d7 z%}H#L7k7NZe(rF_p6VxPzG38B&9@49N%=Oa5df`#hsNhaA?o}prf}w@fLWI*H9Z?f znynjx#H5WTN4Jbm1s~QTL+oEB#3#b1mQOvOJht{IXNWcM@o?Z?a9|raa1S`3`T}=j zyWheZcr+zkC?gK)1MrcW;+a47PGRpU#QClM&q0{!Jf(d8Zt3ya$>yX}qrk4-;_Vg> zW{HG7Z%A>#_WYRv8=jZjSg~?GSZ&YeM22}ZvcfIMFsgetwC1vYkEEt)FM3EUL_T=a zTkKoEX!xwP?=`HHee@V)=L7lu4d|E23y{wWdgnh{y;Dcx9IAJ!O}#VHRBnJCfVBbE z23Q+lZGg1_)&^KpsDw|c`4aW5`>~tUS10C=Hd^EG!lUsSdvq8uFH}vi>wHosV8*08 zzsPyLO{_(Qjh7l;V@#~K)XYJ)K5tza-#O=kc8729*5Mx3ZfhFYvUWq)Y(GA@8sLm= z3jJm=&$;Nlu`-Pz(E?1C&9dVW&S^ZaTieu0{`wAWw|HGWyQ;S)O$V*XRexel)c?(Cuta*A#3?&u8Ur00?S5n8ywHw4Uh zaIFj|Rhx-tS0rF7ux}>3?Et z)U%rZ7CZm$>O>qJZ+1v{yJ<=x_dz{?6?UGdGV$ z8tvYu{$WX{BI<(fONfy_xI zdZ-t^WiC4P?$l^=>?(YNleTi6z-;!P5OvSSn~60#o8&rT(TQc6#5o+CCHjI>6vr zAy59=wesTXPVic5rW`Tl8E7A0xAFu6l*9}7VCQ|b`n3VN)0sg-d7*S?yFTof#k70f z%2`##{PaHu+Boz)>n6XAMC?TNttR)!{Kl4w&8EbW4XQsMZ6CB((9EyQ$(X1V9v`QMnVHy2iJp=e6s+1`CA{24D!uGVXtvhM;Ba-5g%G+o)l~oXBfl* zV!hU^y-L5$-8J>pa<}7XTH~I^wf=l{dtv?se%fXE>9hGqs3!$FM2$7H#}CpX30JgWKzj~mGDx7-A7{HdbEXg*0`iwwn3+(%~kM|Yv2Qe=SmpnHhO?hEKM#% z9`x*{8+sM50igJMWB?}mRe;H%_U;bfzijY{m?Hmj%=dja;Lkc8bwxJ4@1|x@Lrn6# z#>Ux>_`dI9Z0Dv9?*qIkIm6Pb7bg;fp{gDBn<2F7jqPwY?<0*ZEzp*%vE-pWZX(=42JTw_xW!5!p^UfM-uWv#-#$-alOXg*N~E zbN#mO|6}pzrpyBtcOK7l+289kx7pv1X4LN+_L^)_x1!^SRy;dU=X3uL$2|Or6yg8> z!?9u>CH(&XgJaQWJRDOE^9VApc-d6=@f73LFFz7Lv$2}+Gx4xSvp#zfe5?tdhsP^c z!pAxy^~7jOraI}c@d8Ve3yS#IrGJu-MSR{a-%o+JIvY3~QQZP1C2FPgl47Da(^KXCAfu=*jHu_V?1v zO8a|5Mtk5#PZr@0GLvwpVB7F;=zjLZ`?3YQN5S5qyI})4&Y3 zrRL18sF|_6!89%>AGAUJ1@gx^VZaxS@4^91{n<4#gQH3 zndA9{_(b^B@_7Lrt6sl-Sy8f5J!5!JNq+r z&k`3D-v3p%-khBZx4n$+x37Jjug4W+Px;){7I`%#$gIq92klibm$8hmlzSsm0W%jp z|6F9xrrt7hMz8uTSt<7>QXo0_c1G*u1%jQvpk43%jVJ9H$O z=9c95p``#em4KPm*XHZ5hP>v2eoz>@& zXKd|#U%;lWv5-7+n6dq}GR;uh7VHZ14r43zX!m|-_r5f=ls=r@tzc`>nG1qZ1v-X@ z!}Gx5?`OhgpROJGfYiq0mfm|a!kzQ*(*=m@R_>MBdC>BJ_cD^JUK#M)rjq5@EjVWw zI6c>QH2!W+R)2p8oSxua%}+kmc<`>w-|@c`+E`@Ud@A#iz5Xonc6VAaf~~=Nf8&J}$y zyU^Jtoi}@(bAR?4=iclB=N`^a+{!tMcXQUymMnUIO7$xDBA-Pa&n6LuCMuxk9r#$3 zhn)lM!#zDE6ZWnn_F}!Qr!>WRBr89LXaXBIF$bzCbR#x|WV)>Dv1D1-=ByykX1|OxQj~it8^RRl(KK_kV-Iyb zV(U5{-1nQD0j_@4e{9-^_;|@f$JUQsvn*s@9kBCj-ipDHo&ROu&L8q^I}!6Duz&3k zJHM{U&i}-Koxcq`zd2UEKlzE9gKwnYf&a+oIy*RFz|W`m6xXny+79Zkf6Y%U4@;aB zfKJzUnW@7}N#h7}53$n+_savOkN$LBz6JF^I~W?$wrZIi9DY-%G{Yxj2%Or zCC|sPwJKy@syWzaQJ9N#XU}JGDm4mo_%zeZWf61P-|mSUZ)*p?9V@JFUG& z^|ypW^SU14Oc*N8!T)t%dHto_o4Wcf^zC8Tk_OKDKo%>B{JoiOpZoN6IK28I9bHvb z7H6X|JB~tKkuW%~et}Y#x#no_?-(-%{L_3bJ%V!u{;%i6ue1g&hgtLcpiMnf@a<^M zIzLF)6ss&9vpF~(+epu61heMg3&cvER^1$YE>l>WLSKsi5WasR`T#q_CvY%${MeDL1$}Xtb z;Q3t_d+lR0U*fkf*lKRTH9eJf)n_BJ+Fbadd;_)4t2KdD^CGRlz1i8t*`=>$KMNn= zS@x(o*m2GymuYxpWbKRiQsTh*tZHICfb$tA-{SOFX#I`Z1e^_U{t9p&1)LW&e91|S zo$5TxxK0MnGk|m70GtbB2{R6jXQY|S+TJ$lP2$Z?gC1P7Xp)VW1uj#aSHRn!q>TCe zitES;RBx*L67IMkpV1^_mTQ-j&m459DLWN-)H*M&jhe?g8qDJzCp)>dbvYpi@J3FxTel2pc^UB(Qxw@Ko9On83&YXJ{+PjZ?n!aXt0eSQ-7%vz~49@kPMt=4&D z#TIB_D(`M%?Uh%z1-n+MXr%jY&M?tA<>$J@vAN_B;s?8hxQdS=u^4vBmL_D>1uLn8 zMx5%+r^K9xIme0`9nLE?u+_+C(2JU!N3+1cO6@1M6T@C9o$H$9aN;6j&NJwQONk@f z5T%Y9yE&37*Bs_uxA5EUP1w|3#Yr5YU-kL(d}zGd-=A-<(wUpT;+?6^bIjv+?e7xf z=AF4YrQ}WU*O-r3|D9>AVbm;UO>gU{WlgoN_0Gd&uBwOuu0l_!`t?@S8w{7L4Kjo6So;vJQB1s%f_MbaoIcS!Oy@>SMO^V)hFbFFTRrm)o{ZcV65WCMQa@9*3^&QFd*^ z9WmtWGb{4>kE>629$ED(V!<_rQhY+i&;L9>X9%BxKGVVtbHsY6UahO+yZ3nVKYZqT z8?!W6PwLON;nh@qch#_gz2w_|8{#R!R&yA#pf^soGI6zD_{9qb= z3n!+sHz>DO`b)?>;>j%3NmQJoV5HjptopH>L@+7dE9I;6 z;CyeF**4yk5Y2cT{6qVtSM%-SB@G99$|Ms?<_d>Ad231cBax0j(k6QvJgZ$iYZv1d zehY7-X8&ysoVh*7mv*oHDX=}od426y`Olf=?Zx}*TLb&5+P#=K-Z0t z=HOe|gZI@}{P}(QJ)~nGMx?oW*uWn0&_V6|dED{xeWtEjI)FQ>yCzs(Yv)(nUKrD# zZ_BG|*0yRO|Jgj{x21SQgMH=Gx8>!zZC^EGU|ie%wxnb1`?05E#EW8VR%1Ww#(vg` zzqkYYM-qR)GP5na1p8V7pTKqaI@+wSV|r(g;rux?0>$05QqNcMGpg+)nY^NNRds#m zb5)Xyq)Yc;?>?Pannuo7jnTGp4~<`U()v%g$ILapEoG$XMi)O}^1V)u*tt8P1?9_b zX&{(57=RY)$w?%ygFS3aWYod~>`gPUPwcEwEE{##i}FcA*GXdqZ1c$7BSR}^TstaKT3Vz zQ9F!{<4EK3;(h}7hx_xB25f{)W}WPDMRtUK>qC*vV{Y&*pFyG&>m|~G?!^?f_1oj^Q`(Fe5BiV6oN`8A-Kfb9uumR+IuL|`0b9^T|*uHqb z=dU}|j?-0uJ-#VoY6tKsX2ET@;*^K_cJH8l{jo#lI|%2)2vt5nEN_=tv7SHSV>QB zSKjPRR;P~H*wx=8*~iPhc*%TH_JbW8i4Ul~!)*+HCpA4W%($ksx^7E3vBT8AMIZlj zF_V8OoP^K6V@|EXXR?KHOaIh*2v-`3FVxyO<}qTHIin$XMkXM%<*)FJ?#~XE7RR@a z_u^YmCcZU%|;mf$e<7V)!PofD?4L-$)YNpK;KGxIq%kREdv zFnY7A!gNfk3YEA$J+`Lab_ z?C-PMXWyXMpC5udo*hJIFuLTfk6JbhUHlm8PwubUweof1tlsRJM@)Vza!E6?N{sK} zo}AM}T<%=6Jv$%xlGoxk!G}uCzPenA2{t0X^q4jD^L6qqPX{lyz;8^sV=j$;U3G7W zfBRO68Bbe0^F*rB4UG-YKAru2R(k~dek1EcE(+^>H|y@@35_=2K|lWLq<(69H_BO*g zT@_6NTZ&snKfx|0Ta2Cy@9QVden#}?$eZ#dHIl2*&Pz4kmdjYT$f&Ewj6Ufdx6lWYTL<6Ela4AK_EIcS@5Zn!6o zpXp1!pXsfd+2ECGM3DQQQlHd)=n@}NzyFQ=NVUG|*{qG{Z;~%XB* zJ4?7X7kn?lX85c8g7MQj%FV~ld*zC`lCC!&85quVXE@~TBVp<}dvj<={aA5HJvkRx z!Haub=qp_boq_An&rWzoC;h*K?Wql(d*b9doa@^PZIiDu`FQg%ea6bMW2Eagy$R3# z4LtYSR9)?x_(6Iqc+phyOkMO^%ahn&u|Zt~&((i3UN}a5y6AD>wD_%PF9uFDo4$0b z`7wQ*2OckAeebTSoBhx5fqN{EP>rPDABc@_hHr$o=ir~zrGy8;ZyDpP=vFt*xheQP z%zMaWX>|NlyK0AyYM{j@ga_WDGJbO(_XN)xHrN(jhXE4n^g^efc}N^ zqp81t47kzAd=+;#3|uedqZ(KFsH%5yXx$F&zk26DzK)pgyP(5A9Y5a=F4yyn>OE;b z#q`x_>1$DDw3)L`^hFFEH1-XAxcYt%wDBN)ttYPgJJ@#~!=}77)9zyPF&j6;%x1<{ zOaAD{cJ%+um#n-H>^qA8j=2~+H?aKM|#|oe7&9mun+e=Qk@?+?% zElC{vIPKG;&577t-kN+Ie6_CabhnwY!;gr|+}J7p9EqJ_hJ$mid3!Qv-*y>uS7)T9 z&N-SrLG8A3-mCP@fEmqRGv3oDH?4Fg%wOY%Lr1%H3y-$^VN@bz)V}fve`4*XS6531 z2dNoJvi!4(E-phwMs)qm(8zk0+avDKv-C<|u5gbq!6# z6EuTou9?UDzr8ZDu${T*#*^d3+}l=Sf9{Ix-|v17-CFOl-&$JzNA^*{oD3Pp179*5 zv*=~E9+T!KT%8C`d36$|_r43ClKe^x#38c1o>vW=k&a>`E1=^-?sNxnxXb+g=yZQS zGVDjj4P)<;PB0sJQn#Oz zpPse*6L$3m;Y3~Ti>#AZTWutGB3pOH;^_CIh5Ld@;hFvTHS~wU>YLl0(*Bcz+;&d6YGSN98hQd@A@< z@}ZVOCd4Pg2R%A-09e)YUwAjt{G2^;Lc^C8gA9#)4%wlJy}&j1RV8|Y@Q06B&#~A6 zzL=VVJgl)BYMzgVmwMk*$$dq!0Kc@c0Lpb98Vewtq9y};S-2@#X?aq3XAH8^l<)Ys z`D-hO?9U%8D|z}g)_Y`*x4_3e!2NAxrDc%`v+tpH#}mj(d%?wDfQvuh5GNk0CHO7k zuVx{8FX%mi8vD}4v1gDU5ii%co6rXotKFYpP!(RbzVxcrmILMj@ZybZYj9EKdHONLj=%i};lifO&-mXOT$&kA zoAIEVsW)p<*VCrm_v3TvZCN`t6)lebGuPEe3v$a<^bzi9G0I95ddGoR`0pMVn@cfg*JIjt}2kKxyr$IfD3xv(!De4}@>e_ec2e8TbQXO*!y zI6Sh|&ilz!haLN4S!!~pp8msNy@;tc7Ebns>b^`$6o6Y`TOn}ytV9yInfXiRg8^?JEhG2%i}(AZ<-T=pZoUYWWT z8j}qO8Iro>2b|CNwjc6+l1tzZ-o5?FkL4@nZ?wrLJsLZZe&Y99n}@hpIT^WXgX(Su zi0OLHuFYkAf(L8Vr#eP|urR-b{%=X|#CUAe7xhv*sCZE0dxePkN&G0Lidv9>< z!b~ski4Ol@-#Mx8d$ftnn5wXSRQDC+0mY9AP94AkoXCXHZ&#bMBE}?GuO-BgwObxR zEfHevpR4*8-j_^!@cY!9=KUR+@O-_m7_^=~`A`3t?;S6^4IoRdCKr2{o$IsMa+amv zx9d{U_XCR$x3&lE*xt`728a4^%ykUk+kyMt?bJIhC*GgAoy5CKpw$aA;Cb(N{CR#r zTapE}9|3cVcz2%uM%%bd?q#5gSQYf zui6%SQ&GF-oN>unhILKjoe+4awH05b_L|kpO3l~ct2s-*qs?5OudYnRgZEQ&vLAXs zAGp5398{y~!c07PVegmyIXni=8e$QJvzkL|a82*W`DyUcH#U5oXQdCZ)y7X_SrSPg6A>z`y2NAFutoV@le4zj15)%Ts2ySTjDh>=u_d!nMUh{ z9+Ui~UGrbJcR~yBuS~nW-p1ZD!s?b+b6@(Sd>w&1JzvKZ;;D3g*iPr6Y|eQw+e_@! zI!AfLoVP$c)pla7wh>dcg&3<%&em*?ji;JT{YNjJYKimTc3%x6YgCx&ksTo{M)-Mh zwN!oDyS_yARJ^n4;=aspT-^^7V%#X1yjyFYuhBRqb5L6n-(<*+$&~f1CsR7|f;ro^b2@Ze3$NbE zJ09#q?i8-6k4EtK`R*GdinmbwP9f&vwQeuwqT&bdRO`9Ix+U;Y>UTG`p+Vnb2zl^> zE<^lR$?4?=+h~QJu{2nAf zl*Z?n$B9Q9r#a zx_qRr<*UvI)KF1wNGv#wS}(B*wJ|&R3^fva#;YyGx_kcAR7$>A)k0_vrZY{!?sjU> z)-(n07|2C0UaKy0y~KCp!C*UQ+rr<(gPuq!wp{hZ6`nt}mB6pYy zc$Q?fpQMj-3a` zD~W>f$2k~#pm78uC%KJw91ER?R~#i6L=As$bja5pj;^7eP<#E?Tw;M1UShuL=EiHz zb+L!RyWuV}3GpS5MDD}BO@5@Sdj&ob{ecIMa5V1z7GAD#9$eEy*Mx(@#{z!4KHU&c zkRd8Ei%+g*n)zs4tBs5LUHZy==-5r><(lc{H{--tsb!R=%RcD_}j(10qPhfEdI>^4_ci^eZ0H_pI*P!5r{LQj!}%f z$Pd7=uchi@FL36c@$qseczIJYDxEHh?IF|;9^XM7qkdm*TL~_gQ^zP4tT1=8KaImC z@;%!I^0|+fyJ_R7^hwYWu=nd2g`Avl%zQ3efI%+*(XpKU!kJ1hV^3LG?#;a`qnKyS zQE*p|tK#03XE|8+NHrT?OE2Mm0mk~hHNP^r3HWUH-#4baSKnKSQvoj7d;RakpHf#T zG35L?y^qIf$Qi}DCO^6205q2QT}!LA_UcnP?MZMz{BR0*JC#q2Pa~fuKFxe)^HGf6 zRnF@xt|7+kyUxxP9nR~-=j~W~E;hBVJ3H5g+prutFVWpDHn*I5jvE`BbRN&zJoXlN==@uuc`uK>$<1-^ zx%9+b*36*}HD6pYH8_;|r-f4;N2AO}be zpNkxDroVTG7Z&7juTIz>^UsX0XHKi}ozy$Kvx)u0#`Rn1DDa~@+a*-Tv4CSv8EOdpT$H|*Clsx)^|kE64Cx4-`vWR_a`ndCgr znvR>a%ZUdyu7YpA)_K0B30xa}#2SvN+ITjp9>3@@+`>;_$kQwI=0#zv7U1`whY;<6w`2GcB9YBR5PtGcVVhG zwk4@ja97s{@2&L5cCh^-;g9WV#&&H{+<>vy3-4?F)ON8PsNdpGjp$h74_edhw-2*2 zWHE30Yvn%0{fXbJ_RSphf!*D2*A&Zs=MTuWOOb0gFphR)7Vqp$@vYao*W3O3njbt? z^%dUNc(tbir8^gZPqpTm74zAvlg^Xb?>H~5qQ1>o?c?E=t&Z~J$bsPefgbk5?^G4& zQutR3UH&*9v+Xq^cXExm0psz-XpH(cXJaG3a+3P1cbt|rf+YNS z3USImW`4vFW=qYYQ?aw-CtFet&8J6$)8YlHWvzY%`(@Cg;7dPFqu;majiA>u=?i){ zQ5m4l&UE(x?*+(FD~8odiu#dtL9wZl6)L&wuwHc}6l=@faoytXDT<7+xbCL}!v{4BmQqvE{u# zIHUTfeml|~3-OqC{_u_m|9GAqUvb+N18v_(+mC_^s-f-W6nJfW=e>0Ppr-1v!_1Fd zf6Ie}YvlAWzqf0O=TCiI|9+RP6Q1jS6d0~ZKg+YbyD#DUGMhiWyL&ir8I+kc=IzK$ zclmve<@wg&1({#6Msa-aifL&@Rxh5*qJg;-^tB{&@oHdsbMbV@{XaOv^7sOcdc5x$ zcweUB>&V$!Loa4;IkB5B!TVl?_g#}Z5uc@ag~1*_dSH)BC;ta>bRjMbmyDH_4z8Q6 zHf6^jHa4VnaA&A3i*fJ`x`+@aRtX;PN6q7F*lVnV2Px*tt>>Y)jQ+gY<>IZBgnsbfc-e%jzbD4Fv z&6dn>?eCk=NtUK%>unAGsJ9pgsfFa@;H_!d-E!TRRGrSADEZ0K2E0k@^R&;4#jDzY zude0uS5)_Zk{jO!KPshvt(oen%%`2*mUnt_*9AThxP4FLkJz8|u5fP?c)GiLW<>M- zp98geZ%m$VZA7Y*{ctb#Yh%~00m?wBVyyx~as%J1( zwbKEQq*iVuN3FCD=b7wP@OH^}#jrYl09Hv`XI1>FxZh(3`u)@VaLetNR*A=|-{SVi z475*8e&$E}@PI{W*=z-;;%AF_#~$u`yyKSi4?UQ|FIL%_9_(+`mob-ssmaP`6b~K; zE-bV4L|cO;eX@O(raaphaka!$l}!G;8@Kk@*dPCQ%{up?3IYBvhAN!1IzEpCLdVDqF-xfF7 zAAj!O3z^;(s?|Om+kj)na&FsgPPkNn!{WozA@jdkw*8|&SkY?KdpIsSD1PvJ9_PmE6^pC&%deDcH~ah6_cwwpmO z$*e6kTT|Gy;W^v8h(cSQ0B+Z~*=(D;J?rI!BO~nl4)w>s$e7>cEW$Xx;umXlF3&LV zN_E@XfQxcWR1a4)A2fSAIcxQlHRyy3-A&o8j7f7`=<3|l_EY}B=^49(u`hJj^4^7! zL@jwM(P3`DeLcAWS??NG=L)^USzjX@mp0TUXW(SZ%*W{wobjZ#{vBOk*U|M;FEI{X zQygBv9H6e&i+)|Lx2UV-$=_jQl|o%D^7B)bh8m{ulaRZmChD#QUJrRP2euHwHsr3e z@}yv@H5EMT+;!|XOR1CIL%xChE348mcPsnMk>aA4C9%f9zrFaSKQI^B;?M$z@JO}w z*PqYe)m3PA?@!nG`Bvd&{m9pf*FMtu3^yegTiz`{(%Ze)TRW!Ws)oj?dgD5LT(s^T zdTxXVyMyDRrQ7Ox&X-DID++qFbZ`226XZPS`^uqV{E=<=KPx65MZBec*HQ-u8P(ns z%^q(`A{D%Q9c!ig(0m%2Peb!*Xg&?ir{M`{=speIr=fdvFt09R&Q-qcs&t2ouaW&? znY+Qt^3>!is>gMg_{k7EgSXzdM$gU1ZS8*Hm~f%gG}?M<{|4Uaokp$)$gj0I``{V2 z8;dilr&j0Q4bDuO^f5LVJzEc6N!MQJW`M^nNpc6k4=)G*N=JKWJJ*Ni;OjlLqjwJE zBa?`)I%Nqo%J>H8{zx=G3cXHrztG(dt({nt*iYPV*+V6NgUu`Ao*!8ZkB$c~h4*$Igp9C8-d58QO ztlKd8g51k4VU4B(k7oBr@Pu`YD-}s>KZaUh$HD{N!~VH_rTG2$e4O~OMd`V&YPnrN z9Gz;poq!&H9KOTQxQXOA63^=Mfp4s_HEK;$2WJ&_xaQmryvtlWa}D3Ay&&tduaN6L7}qY|ROfC3uU1Z4Ox&jKd9v>+_}1MuG4~#L(ifqboG;fF#|hk+ ze8$Q#w?O+(_FjeWPFxg!>S1`&PS)>W-FkUa{ZT(XD4FZvF&5_w6nK(1wv}mOAmK|N z!Ixfw_T#?1JFiIIy)`)tIkHgSb0)C%#&&3ZPtH3#jNaejkIgVPQ#7`?#0p?BUJqiNv2l=NoLD?r;n% zM*f&~;yzga&FtM9;rXw(8}oXW_!xYJKkX~U2PB>){LmT9iJWTqRYDV2BtOdM#@lyz zRy6z{b_`Etl;2IAw@ioq{b)w~EQ9W1-?@-<;9MQYf`ttPpg~t-pcJ>gP zot~MAe$O7Bsdd+{iU6x?=syAfZgaP;T0)-{Sf-G zxa+d=!|Pq0$8fC=C#_R!@E4hd@U3Q^PsB%IGw*fUx!#{oC6`0X)Ykwnl4;qCTZ6aq zJ?+;^ec#Hor!V$oTGf7%4+#jE}3;o8tzW2!?&jWc8*TMx3!)`C2qyr@WtxgYzs z;(m4Zh-gB5U;esFplyv&GE2am4K8Nwo;6|9`}iXo`F-zzFP5{Mz|B`D;lH%?PF5F6BgfqNR)4vUX#GXLA+ z;+sdvQELajssq0Q-+oVDEST$S3SNnwt$(bSqt-?oP#0}cA2zYSq%rt%YC5gEoH@Y$-ar06q%??%^#=A&Jl(tI4V!Ous#Bopv;PSJokknYb8jws4U z>#y+g(Q3&@GsH36!uv;2H|I?9(Z1#9qY>vA>LDL(!9YIR$v*66S=jB)&a|+5op_36 z=?(VU@V>+4sL6Kr@8ki?N2mBYJs*JfpTEwd{pZAB zIICE85qo|Kv`$TRXuUJ7+`}-jKbGEc-h_NwFPs4k4)nEXCyV%HCD3(p2Y5tO*Y6};Jt^|BNg9`vaZ<4d&M91 zZefj!*UrO1&0;o(E=g6WPEk;A5ZpEVoSK0TyZm761Vv#Xp2 z_NBw+N*-xk#dxRj6~?3(o5HvngG-C>j=c2XjYq({n#15-(_!%L)`ReF@Vv70dwaVngUy~f)^w9ZuvPazKaY}WalE<-+U$tRW6-RM77bzdhksw355(|W5WX91oC zSZW@UvBVo?cbOfG_r`(=&JUTPd|3bdkeNxl#$V#B#AR=@#z(bJFB{7me}#CYGo8;N zZyauo5001mv}4r1QW)n@ezU%4-Kj+o+;D_-KODbVc9?bl(Lw9pJHT)L{V?mU+LMBp z*1Mx^PxlrrAsmCB%E>}!xKEJ)Xm$iuL ztgwzdFpX7FXKNTXg|W*gbKk=c-?s?Q`51X!V^S?CoxNGd-b1`ul=#f?G|JzZ#OhBt z<+JR$``Pzgb6QoR8@;;cJn$;T{*|-(W0`rm{VnRkd++=f+zMLUIv(88T4>)uzaw_= zPuKe^$a6Jj)+sMw6Vmvp_nmx}aVFx_8=v27-mr9&L9ZL^=N6@ENz~t3PHf()zi*wSY{}%AI|GOT(ZXrf?s&g;+N<5!)KQTJ@S^m^a%xn`evs0XH z#Jb#rk9upip4i!1Vr0p)B>$1c@nzjw;q3MTugVSVf0B1wSPS)e7xsBWJn~3$IWq06 zhW~&^sIG@=nj5w|iLuIEDn*9WI%^NrJ9^)kySvOM#FEyZXwG6k)N_mt+>5)6Ph(Cq zW@_c!i_e_8BhEe48QY3q{cikTUX18$VnoF^3b-UWx`0njUPiE0t4reVp(L)S$ zGnSala}OJnsdt)?V;X~xr$7B#ri#{bxxbd@_%WILh{>EyOy+H@Y!81|;(_g9gn}cUkXQP(> zn=;MBkY31I9gcqV?48&n)h_vP1M#~*BYs!3;_;%P>mPEw^`GOfzw*enzKT=6=5{ZK zJRBwO(}@Mt{^4_}#KG$jIfX>9yLo9*WfM`>^DjPVQ5kef8JiUp=*aRKq6!rLj{-Equ=j?_&)+ zkP)4ptoR(~*?cZcnSn%((;7@g-2x{OOhn7bU;KV59NLfUycC(S2O3gt$mY(I%oiHg zW6y1~=X5+rUh|ylk^4S!Fi}^(pFbw3w)8H!XX8T90x@jWBbWWqT!bE=HbjRmba*j- zCjB<(F2pr<)HwaNkMR5ib>jNbB@BDc(^cX5y~v&!{BJq@Z)Md{bLDc?9_Xd^fZpC` z#*|O&+2_Cu$|vj_;~s?_RroO6?mu~Q?|xcCe)70*=nf-4ulg#+XYyhEeX9|_<(mcabl)KjMAa-{z1v9t$>u-`Hh=&r``ZGyP5f2|Qr*V#+aQAp%AetO$u7@8! zG8vn6nQI=M{9XUO|9v1-E?NNQUFN!DjB2frLt*#cV%nPkJ!l+5_p0Rsblw=8;PbcZ z(aAUmHu%LO$Vg`u$;Lf?jgVuIk#f*>8vLn1C;JGUY>F=mlY`UZM3Aeb;@ecKe{57d`I19w-#WseYX8t1QY<%_Hr$**>^;L5g@CmW^ zNEfW5Uf^dq^G`9{m1gr=(fn~{6SeTXvjB_NL42{W7P1S=PWtA7cu;)jJ;tYee{cQA zL~h7GXK{Z6`E!DGock;=f6p)f<^k55d}HFR@muYN{+?fnPjpp?o z=AX}xjTGz4XlT~UdcSZlJEEF@r~pe%w5k@lLdPG z%A|8S*Vm&*#q_@m4qOC1R#1PE8tEZ_uKN~1k2^}HAmeC0Gky3QAO6L1M*b?&qtaT*7d~6)EXI= z&#$W%jvKR+vnHunbNo@}O7dgHb3FMs{;6g5$!2N&d&m)L&z?0GC4MmWHf8b+NT(FYu1= zAz*9Ak56$v6}+nwIYqVO?YTw0Wt_`vuu%-wj-L}z4v+dR(4$8qi44(Wd>T>@AhTeb zbq8yD?DONHj3;N}qYbNmd`}E|EUq0NcX;DhaY>i_V* zww3H(va9!CSMM3(Ytwq!arD5SiKY4|3jb8$R-7=a>t?kpTASVt#r**93FV4>-I}w!vGtCflHN`UmEF^s6|y z?bvaq!ZTzOk(}8|9?IU^*GFoh;}~|Gsn~d?VB2Z5dj6JdOK?syyo?-*;MLZj#{R(> zQLzBerxjbPw!)#1Tl#N%{5qz_Jkdz@dIRh#wyHmoX4jKQMD=**DGd@Q;sGh08Vc5&@U zI2B_|GiLa~R`}7~_+>mjsY&)A=DqV$UpHjVjlM0T$)F2jyP&S4rynxU7(8t%ye!Jx z>zRA4wPRt=D6)-Gci#N1_}9Li`2n(_YBeu1xnnEMgFX%BN>nTMR$qSFj~*%=FJ$hk ziSn#5Gg9&=g`>V+F-7;hvz)`VF?R&{h0-VXrG9K<%)|$jH%UyL)h7n)UVHugg4k(G zXXN6WdiWzX*T0DGui4r&LN4=6GiTs~PHE67v6V9CG;>TdM{Ib$P6@33GWsaw`HhD@ z{`UVOeH_j{a5(z-D)g~(K&M>o-eg)WVxtR|=k4noaXxcv4Ky1%FDV+3Mp~jC?h3PuYJ% zcX}9N!@g9Ry(c`m-oK}Q$S?HAAXyFDgZy>$_fh`K0pZZq^rv@XW!OBUGl?(ZP78sT)W_EwvY#0f?}_4%XD_nv7p{p`E9VW$82IU- z(fgoL(d0I0Qs?*H4UNiwp`0*k=yWq)_>!%cv!&mB9lc{Vc&^yguVYVq_l`Lc@jK-s zhv6l5PleBg6EX8o%wDkobH%&J^U_`^IWs&Z!9IFlR?k+@w~ZGdmSi9oguQ({F&?@e zB!)%%&e=BF6*(~w8S6Ad*(PGNtIsBi2$%mv!J7uq}gInJJ+I384uT($Y9o-f3r z=$(R`pz+A(y1=#Hu? z;l?N5^l)Pee7uLXZ$oQ?)`1P5gsc%Ka*#_!n3oI z#$3iTm-EcGdLz{9tL4M_fYcxE$zE!D)34X&C1;RZcHR4JW;)P#dZBYe~*nd8|){+Snp3y!Y=By z^IPyg_nFhFR~z0$#SMQvk~@q0pL)>m*g?Nr_&wKLpE?>Fi`VXp=}{);k8f9vbS7_n zOZ@SbRhQa4+1Uq;&x1oN?G?u2P!maQ#*40XGrwK=mk)ZkpL4K~WT6dkDGe^A!KE~~ zlm_3@;FIt#4c?`}M;q($IQ01M_!$I~e*z|wZSVt7{~=ed^`XYZxGC@hYT?>(OaK0g z&r7sMW8fX44|0HX9!Hs;Ezmc0IxN3x#4kSIzuw=o)6V4vOP42Qw64QwqwwBr+L`FL zKiV9Vs;92q-YyJtIq4&RT+YDvOOm`{@EKi}Pr{e7kb1-Xm+P-J|eT#P&?#1qGwD-;&xJM3$ zKliqtb@tvg|DMOULT+PEmCb_-Q%~#f{4q@N$METS(DH$~J;A#l-7%wDF#QU48_loI zEUgauaJ|5+Tl^)nY*DFM2H(HKj&IkRw}$ZLY+x?+YXen+ z)foRd?H`4CUbE&cJI_-8-Z#zq#a}jy7L71#Xrp`Jxg~1@`1&76D<4j4c%fOlc$&GH z=Pu*9^uTldYu~bcedIrPk-2N}baN}u%^ItG!a~1O*X^{={lb5)*(6g7s7E!z^zvN$ zz;mnDt+UVd`_ILR>B#3#fM0$$^%?VEaGsUrbDzNu92sujzcFlfjr}2Udf}+>{8(c9 z9*vAKkCu0HuFL%VFPDCjzZRS9qu5xL*OnYu2f_W5bxW%rIpE=yp$3&=XGK@)L-(g5 zSHLIiexrQ7!d$x7H`*}@F8BHG>;;}0LxC?ud>$DfmS40uc-`Z_rR33yz6#fC*;i(x z&$n^bx8Qy>Hr0h@dzRGtB3?QUds~55&GUKHPti-RhL=8g5Wg`tMzzCis!^R6!&ze9 z8G19Z9Wkl^9|;k`>f!?dCb+}p2B?B z`Sb0BH{Z*AccCW@?m?1C^}Ch!3NY0^qigY^Yu(uAcjbS55UfJ>-PP0=o6p*-4um(C zhchc!U)i%HGd%uvPi9d2iuF;vq^@r{!u4+dy5eS#o7vazLGFAgtC)vE9Oh{FtJMjq zn}&S<8TL!$$-o%Rm3V@!1_jLa^a2yK`V`MUp%@?>?N+Gzv# zr);=5a_+!=&z3Q}=>F^tdm_~JwS5$96QhgnCpHYL`m%q&iMFM$k;_BgQOx#VW`=7{ zthsT$JhPka7&6W?Z0c)ohb^Q-LhOE!8r(AanIxfNjC zZSQGp>oyMa_uEUV_xkszo9{1D&1J2%aHnUra^byoEzD=z#)~7b71}d3i$2CC;=z6y z&nsuyTZ6*$k8iB1dftD2hKVeC4;zp2#kGg@te(m9$$>Fx?z=ZGt=d^=pS2M@n~PvR zdeeFf^Z(!(59Z#Q%`JlI>6;#@x@VvbZ{1po?ze8*Q}v^P``((xi|#Mmw6uEdz$ z?3rD;Yu#VqH`OzZ@VhWDwqts}s`_~UxtO&*>`k8O`<4+)+GSfB!I%~@rrD;)NU!yOaD2Tww`7!-$t(1c(3tcRq3q3|4E(*u?+BR;#ck?e&t@` zSGEzqau4wC3}2p)ng2lcQ@?K` zyQwebRb4Y`W@ME8|7c{q{eMYSll?!u<|_WfGvN=*?3xBP539P=AG>S|YC|=H6uTg~ zp!?iG`xE_Ody;=kac=h_3k=;tQUtwYZwP8;QTWx;k-gXEp0>>->z zge^z9`o2Zis1JYb!~0@}b+m09Wy;IHZAv0xQ&K)3nP`Ful+QE6A~j}M`L(n$(F_l| z`(C=*LH?%3IsWKG2|9Q{cG8X!et@sSfBnp>%@E_ z&#yYcsE)vdeb3;MJ;9hcCzuJuRhn;(GXHI_-|EQL>F(QgwfNJn%_r9UjNjx%Wuyn~ z+q^fT=cx6Z(Hebpj<-hEhr#-2o#dyWwmj=G)Ltk%p=^e-6%y-^JPFtsvukk^>qU)h z)lWC)nZ@OEsX5$-Jj6K+(AAQ3*<(xXnbEDN7xiXrI?wqWuBkf(y=44poL?9x7_D~V{4j_AB{O7bJ$werW0i+U zP_r%>j!q@lHOF`PIs*~Wj4|sN@6(H4&3BHi!%qB6zJ0vrvx|EgGd}#q6KTsa57+z? zbbZ}NtUd`p_0eYUxQWZoH!k{#?Z7;QJ^1?x2Yu$V_Wg?@zs>)g z*c9xwTVmz`+IP(L=!=&orrJ21iy{-d&o>|9d%ZpXA@gYFT#8#yA^&}BV*Y62ea>=> zd9FR2`$RSJEI+5dChNa(pdaEgY5yYl1NH2Y#mnw`p$0qVr-rTey8?WV0zS$E6MRPT zUA{Mc$Nv?%$^U*d-<3P4>!TQphu0f>j^g`&+Upy8j^_KT{`Zl57hE;wMtJR9^v~1p zs;*JL-?!Iq>=j(U%lGgWY}b6(fAKxRO7ya`*`t>pbea}uMD;+YLKEm&*;eRgE;KY7 zy3rXVP4KuzbPZ@8TH2DGM?SA)EZHuN<3{3UXLi1M6q?$R6~DlaNuBnX*gW6g=*4To`vdz z&JU1Hat~b%wW9bB@lPZ=ORm`mSmc_`26nW+Eo(xl*0tM)m+1s{%skMiElN%?*k zxgPLU&5!MS_|)D?^$ydNlX>0eKJAZ?KAEzPTl8;R$x8_ZgPz{g??uku8eK;J>kPGo1J%D9d+(WFAob)` z^tL9h?g`bHbx4dt)*2drjS8|(rCOemn1$xsGzvapYMpCPHi_ z6u@7)CsP1UrNA?A_2m?J1?|5`f9WMD@G2#;1l)sP89g8lUuy4@dy9RY=x>zutzaJ$ zwJ+$|xhuiLRYqQ6KQ(6!o@^HyU=O3{kyxr@tzLAjLh4F#cUAJ;O1s@}ofs`t=6)ZbkSy$^;jUpAkf95Y(8@rC{Py`1}K zwNCTf-|O+D#+CU0(Du5G8&h*-q|s-L{1ka<;%aGfb2I2hEyUGC4>*trl20hKM9<2u zLNDdu`?d6|r{;q@aV~ppU?#0S~JuHdHfsNIRLtLA{@-|fscu{4G3 z*%x-y-b4d>I#)|j!xRYjRb7xxi7tjGwO@CQ)t9+thrMoyP^ZFP`%U>o!+HLMfSOt% z<91O`>Q9fFKS63T&HXhuOj(S)c?+1iJg9{A$vx<@2dP))P8{Uh{0SdtpTvZa_089M zf!2@cCobQ8l%1--%VxJmf1k}%I_kNIyazuDaF31>`se%jg>!rXm;5BEvV?h(CC?$ph#x7Ds!<~l}Qw5%hW?Gs64gB9*v|FLt)JD+49&Rc7r zi1<|<)+#tRbcn$@Q-@}1&vcBrDnXnzqsoYJ2wx(9uTkhbh=2VM^zHgZ;Ca+}#k}HE z3W8%oFXAf`nI!K9=DBugoLZ3!^m{H{xjwZO7n?QAM*a!xMPD3_oExg;-1Er4SCM}& zBKH;(TL$mbtWDy|!Hg38(foB%M*JE2oWSv^C9;h!-vue-4UR5fV9>rd& z)Qj+K!JD+k_a4OY9=E?m7F5bR@NN6upR4QacZO%(KSg+!+!>|kB|k)P;~m~n^tGf~ zfc^%r!WSk-dT?)AW_%g_ey@Z+dp1&kAbWx5z6j4<0?&N`p1U{|gWs|*%?|{ABY~gT z7iOKY+&V?hg%UAh#zM=NBt}E?GPhZ8`~AFb?E{hN68j9r(M+>t(I@FIUCTXY}_o*aH8bONW)5=4Xuxi-=osm;^>3q zYSd$&1XbTYzau}R_edF|H0&LHyT`ewjARG?X8$rElG)%aq5Fa~7lYSp-iwi(l)r_z`Du z&7(blZ#MhWXpnmp!rZ-9!(Ak`{?+)Z%iz@D+iB0GNpB}*(4Vy21_)>iG0X1}f zXZ-k8`0;z-rw_uz|F35!Fh`LHglf2bM5)t)s;KXk*!sOk2#h*}z1+3o+*zvBJ^an4 z21KSV^r&U!%K5BRMXE;9R$}K_k)fm1$>%z!@dx%?gXHXg8@og7;@{ZcUWYyPdu$6+U=NUhv_DRmJcTmPD z2z%4_Dd%j+rH;SZHFLac1S!Wd?=R{@C7!Y9(f=_p3)29nQg~pS00ABne8$4a` zLe5U$aH=z&l#TTeycPe5z;w*qUePb336~zkwxGXmSoCJ{+Wn`~#|$VR(%AZRAdE!&7ezi%xBM3jLo&XQIay zyrE5}dlo)nY<$U~lUzE1kI3AU`EAfS0Kb(nv@F1Hb$5 z$NLvG{=xrh<1{~aGyA!l+0Wg~e(q-Wb2qb}yP5sw9s{vWmiU)zTO;jX(HLUSv;C_Y z=lfSTmijY|Uj8cn9`h}0Z1vH1S;x!c^TXhS>`i&R;Zpyy#w(!FAo}TS|LW8w@GAyB_XTb8f(=gKrhv@akxhe-paVmW1SRwfVsk4z;J9WzNId z$13Gr$&C&}o4sdWx5EYj**3%(6cen1~V z`JKVH3~Ot#y0&VEZ-QrO|4MR1()!*Efemz)nvM=C>lS<)7B={HBYg#gj~HBgNaI>y zp3SYm-WhH2_$JPv#w)%2Mx2lDk)(rX%mUbq`epJIS3M^L;DG5kZYq zEosS9ku!47Q+_9F7%jXV{Ly$sF8h3F-Cu6bq6YZO^B$~O-d*Bfqj5s|gQ9;e7_V`y zQ@GXlda4t!l=+Rm9oOTDzD>Vjy;r|}_Zsx=QOQrTQ?UyQ!eg`dbx!-Y4lqwZvkjryDgU&MDL-}lA` zcZIqG-0v8^PTgs7e-m@wko*PoQ02UfkLzmg2;>d`aGkt>WC`al=gxgRdHC4k+-vbs zdb7%J&s_pP_r#Dtn;H{Sxv9{(@6tmLKfQJR+fu?~mD-uqG>~X<3LHaUH$Xd~ z@h$M!BkP=}P7JnB0dT`H}-Vxcs#lJWv|f zv67Rwaqq791y)fTWq4qk-zE&K!N1HGF0Anl`J3ULJ*y9Lrb3(2XGU}akLofgR4+Dn zSvYakv(Yid%cAwKJsfGBFpa&_zuudf*#q4o=wHLVx?&?{sCi9$PJ+Rt7H1jt!Gd!) zU~^Ml*a0ceiIj+x2>e@p1 zldrU6qnoA9g9!^wk;MCXIAKPpdG)F#OX@vW}z;a}Z2 zRrh-v`KZKQi?E}y!^oSt5E^Zr&wb_CW_z*CJ|L%R81bCKe`*0o{GR~d?12+SQ zBhlI5*s9)&yD21p=*iTcl7Z0!t6z!+S)c54HhT(lW^FX^F=yOj_ZD;R2)VQ#pk^YU z4zBtNI;gLdcMXky;skSNoYCV}%if^zXMFA%H>a-7@w?*WmAU?W6?uCLI)AY5yL7P5 z#^+sqN#dy@JNGWzh1_1H^=;un0qmrj<3>)-JFWtvSBVa#zDOhER-7akj~+Mc+RM8l z7sZb*GF@bO>9UE@)(MZMiiZ6*PmZtEay-EM*dPnoO49JYn6tdtj5Qf~EV4>?*D>GL z>T8ZG%gdD~>~9jg*T9_GM#0Zv$75ceGq1?cjo|A?Rv&IiVvBYXx%Dbz3Lg~u-9EP> zdOq`ep;z>0=Ga{Q&Esi1M-04*+ws%RK*p9iT79osc~Q;SqUZRMA5-%#V?TrZ!0nP0 z96RRQSiQ^RjwQ4j%#F1pC+9`>Y-62e)xegq-eat|9_ux=$!TS2Fadh~61CTAr$R1ZB!PiBG5z&u@?Tu?3V zPQ*8%8Kw3nf2GhvRg%13qYFfju@-1Za*HO+$@a8`7=4UpS)7S$t<`Vz{_7E~jU=R{9pBx1j&OUhVZS zubwvayWwNL=IR=J4YlyvB6ub~X5tqMxbtTw_^li{XW3)D|4n=mF>Mb$aV&<=sT=`scvw|eUXE|GG#lH~&8IpsfV~920Rn;+cRSj4F<`nDG`gtuniL8_RksDbT?<QH_Jd>jxZO6+$YUM}{a2Bd{!o%R>ck}p|u}9u!Ub!b!<;lKmT-RJZ>sS&>phj__VhriY1xdh)M`DX_oN*69feJP)Y{^w3*BHFORk&HxXda4 z56oMs*Vwe|xk%E^o3QiNc;9&9ckre*UkDbEm6;N!*1Ac3zTDb~ZW7Fs$@zLZ`Wx>K z0&jXR{lr0cFt~ufp&N0f*VSbj7k-959)@OD&?B%j{9_ROQRf%6XPr}J&ZwQ~I-tYeqFxU5{1?lNmf4@hmHPia5EBf6}yh32g z9mxHD27Nf{+DH&RQhL~gs+M}He7A9DOuV81I>c{*{SmkJ$IVGPJ8Szx`q3EsLwI)^ zet$pb7vR1lev5q;cI^-B^h9&^eexl8)}D_~q*!$%PpoLr7W^JP(6P4QYfOA|TO@H+ zmk601$$a~X{(~Cc&DlC~$C~=}LLhlHj6?<{^w~&UXN%9=iz4|4CU-38X>jci^lgD5 z{;EKOe?w{nRpQ(KnqwtUXO1)QcFZ&;>c6D(koimnPoah$h zBD`D)e-6bTQ(NJYJr-a~Gg zcOK30>LBCX|JR8Tfp>sd!XWUd%@(qG58%%qte?*1>4IZF1NUW5J>WlHU?|_Y@SFs-P%gP#` z;@=16Y>EatIy!I3nbd3SAmrGCJa;CYKlTCr`HivXs85l3Uh=bcTA8=Gkv`1HT6Boc z>I&q$++8TOf^qnqeD{;&K-JPkct7WKO4@je{0&)mtFOt@MsdW@#%qmD%!_W^=ux*P ztJKr@U3}qpvlE#|daaF%_DA0I#kP_)kVmO~WAq!ZY``~hDms*T$Y=5LeY^SOY|!-@ zTYcM8(wFEhk&BkMiO;Y&YhdQ(J&(GE`R=yxOyuCXLVq_7TY4k7{v`V5qUaBK=7ry% zp{}b?{0XUR_2*{$?ls(lDKYtT$O)A11!ir0dQ`HvJ*x)nj~uUFgr0!??dnqK%;ZL? zJbv9~Lw(9Up?cm##u0u!2Yg^G_|H$0Z)cBacxAKeBkRA&;FKK~UC6owmL7Fma%=W( z{k=!6k37e7`92@F41Txa@<7Jk0xnBlzKh@edA27r1e_Sp`E~9j`GTvmW%wg|o^XCY zPM${p6D-SKl01qq%YZB=LL|-+D`9jF)|Zf@6DXvv)=0TO&0f?G!D6Xh4E<`-Qsq1i-(RH z-Qq#kBf7=c)Ejyq6>5wAY|;A(;N!VD*_1t^;hN26tG`ApR?hKRzE|qUob#w;COb`k zPXL$NRddediX``EzhUuX9J-9i!$5Sc{+*BCl_z&+4_W*e7Zu!>?}iRVo^5AjVW>Xs{37QIlsJmmV?(g*Rx!r@oE@dq zCwX>t+!=1yw~KuW-H~GiJ|8A#;0?c--AP_z1?PVR+g1F(Tde<=l3(6C2i-t$?X%o^ zL^o(#&!OCU#IBR|EVsJBa`@5u)aYZGE@EREcpBUhc>d7BbA^WIb<96l>wp2id;FNu z>TmIw@yfDdR_8LG}70*y1I76Q9I5{jcIFVNsQq< zwSe=G-13?FJU&CliGF{v`b6VgC-t%ZTxMY;Hd5E_qxns7__L~8^l$!3j(fSPsC)Bs zu?@E2GZOuZJ5SKBNLZjA;w|za(*iE#QM;0RvoBcO9T0t(-w2FNj@jon=t;@v@7P8po&U2`2euHeD@b!9zUw2b$t!MIEx ztzAv*w;r7gy^`-%;P8Q{NXQ>T7Dh#zn>=m!y_Dgc|A)$_6-UUcb(^ zN2bIYhGNe%XNtK~tO46+U?uBGDX&xK!1F>Q#yH%|@r?N8Bqzr3zMZ)^@8RrkiSs&j z%3D!4p8bgrLfh4?Q?c{J58E|?Qo$mP>GAas9=-A5>v#9l9ZtP}BZ;@RQPnIjaK z=kch0$vgD3BT*T92R+XOcHdRcRg6=w_PK`o0QvuwYG%cqYWBG$qnofr$2gJ?pw#3v zgQ7=2i(iGljOgidm$J4`YGT^g>gv*No<-|~2cZ8g@a|36<=gPrY{g%*2s>{zdSC({ z&C87S5+D&r|dHEaSPW$93m@@rPuymEd!w=H2bbY_48w#}wUnAiA$Y@BOlOrZIjo z;|o6Zf^T21>1QkXcU90%IkeLe+9_qOVrb`RvYOtoVmnqT+5++iJnf{s{yO@>YMB!n z(F~q`SL3PV;u<_XntUr8B!(|IuK8yL(HtpOSBBBE+^wvSX=G42NsmfmL zL-du=Dpe6mNbQUGp@eUAfNzw*H+sT1I>9$K!8eL5-za78H-@M> zU3YY?e*?T?o#quo@s|u{&IV$V1O00)zgTbMia{rw$1g%Tez6vQu_hHBeTJj1C{qPz z7t{M`jfMqdVIQ3jzvvCW7*+4kGZEU<{89Wl%xC$=YV3f-`tt zpTS08Vb0)Pc!h~!)2jep(OvV3u3r;gvC;5~s(Q;S;%TvAPvjMnlPL5M3SvLiAl|%- zrfxe;k+1!f;TOTK$jtYMiNy7s!Y|&o{9>rOIWSJ$Qgfk=mwa2@6Sz~|)KF42k$Fbw znkA)XrVSoef`@V*TfoDv;30Rtb51vLP9>b3QhSm;@UP%K0}m^;oGenEDwMYaco^6J z4>e5%1~oH@~XZu2#6pYMxII|5H=z^-KM3ssHQ z4a2Ip=F{TiG`?_ec;PWG_MYiEY@U~+tG8HPUG(Km)!Prdx_X9liCJAC?QA;i>Sv-W zNZfuuy83#?E=5;QXqa}1;zMZZvHc%n9<@4x?J<-))?Of_#2~U;h75L+~=IQD^ zlhmDQ9b?>4cRgwRS}Pkv@OsT>i9y|d)LoNnv%SumUe`7#@1jeuNsT@lLucP~k`463 zqp^VCa!2eov4MK1Pc%QPR3Gb4IXi(>Z*3+a#wb2 zPA~lj&*ghk7L(1{EPlk+{$~PI;r$_e%dHcp;=fy2z4ZL<+P5un0_@S0>?24XRGhqY z{1)VtxiRQlIp0{``8HR_+nukW5h?!ABfor>}POpcLRIL>4|ZdrPyX+b&;h%<9j;~J*e^MPV|v{pWKh+d^Art zd0pG8TR(O2UHETH?tDJ})W!83_I&oE9|`^4!TF>s1mCdR^3EsY{N{x7F}|Nld_NBK z=Lj!=iI2lp-UjUp{Z(R*NUqdxlDAs=d!p4{PYdhGx4tk;IX=t$bl7}E?GM@7gKf1)ssG)dN@{+UJ-Qjw4dt{rg734eO zXib`a5>@z|YYH4MwP=N$iRkr$uYxmUS!;amjHtvsgs*^$CT3Ev3g7|6A5^8x$({A& zm>D1I#N0UwA8k9wM7whoKDyK9KS{n>$0YGRySDX>GG>k5!@88z@(4fDeggP`&{h$2 z)UYH<-M-;jCF-E&T`B#p~3)9hkvj|HOipn^Az zi%#ITa{l7y-IsmL@}@vk@;c@F9DOtY9vN%ND&{E*H>k-K;yK@it5}uj8RrdZRbao4V$)JYuUszuc>qE$=vlnt}bA9rD zOJ}R0v+b#mzfj$TcNpJD8=Zahh2eSRBeJGz!UGf~+5D+i1N5iyOG+JVAvl-T_+0B> zsd27YA2Un}(9 z#NXMV{hfj6Z~3jvN$v&s)oAf6Tm3lCp_gHFZ$uzS+V;{EKW$De?K@;mi)R(>-h#^57tBb*K3?uljq-V!-@aO z!F`>@iARu!Yr%;%;KXYdCsuN*$rB zpGsf$^DesJklH$xvHd36%N+EkL46Y!tB~b0K43fs{wDIu^>`Ke zm-m@IOM8$Hv$+el=7k4L?7u#ydsWDq@^hV5GUxagCc>Yd%&jfMvtx^`o`Fxur+LqR9ly1U=&OdVD)14mvT|N>qQxg(%)5sF{I*RmM9)S>=E?fUbGo7M zAmNXGXkoS0vsVG{WvK)Bx!dG@8y$Rb%1O zoNe5^Jq-xlhUz^g!N0Z~w@WzVY4ayS{{{G{$63BHAlh`y=-R6_-zbJ}R3&$2E457_ zagB`T8zN8bST;YaAu}-=tKjlZ@r(Y2<&x>P;CZ@rf&I+PM6T_!u?&%G5?ht? z!d_r}fnUGFryjpLcUC9oR}0Pl_E6gT(c8{w+97jBDfTVA%IMu2tAEulhazbA5R=*j zubhX;_Y>XEwFPfQ7mexjy$GF7VzWBNj-D_2ip)QK$&jej7qrDTOzi#^&QWs6M5bJ< z{shd6!hO`FJRN#GFfT>Ul%luh>(IC4#hXNreWUuy+`2_)P3P8qX>Q%FjS~isMeoYD zaoX$9?c+`3qWO7lV#f#^Jm}z6Y6&#gfgU0AkUbKE%GayiIONUAUN#0r?E4h*K1R

    9#X8 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 Y(olfn=qIeU2!D?e@6W;;a2W6Z0^&=vc>n+a literal 0 HcmV?d00001 diff --git a/libs/x86/libtun2socks.so b/libs/x86/libtun2socks.so index f80e6f7242214b669cdfdab0fd2264588cb84f62..0548a83a50bb31b18975a423de39884a614db50e 100755 GIT binary patch delta 32280 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 delta 31543 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 + + +global { + perm_cache=1024; + cache_dir="/data/data/org.torproject.android/app_bin"; + server_port = 8091; + server_ip = 0.0.0.0; + query_method=tcp_only; + min_ttl=15m; + max_ttl=1w; + timeout=10; + daemon=on; + pid_file="/data/data/org.torproject.android/app_bin/pdnsd.pid"; +} + +server { + label= "upstream"; + ip = %s; + port = %d; + uptest = none; +} + +rr { + name=localhost; + reverse=on; + a=127.0.0.1; + owner=localhost; + soa=localhost,root.localhost,42,86400,900,86400,86400; +} + + diff --git a/src/org/torproject/android/OrbotApp.java b/src/org/torproject/android/OrbotApp.java index 4ee1edbf..25818fa4 100644 --- a/src/org/torproject/android/OrbotApp.java +++ b/src/org/torproject/android/OrbotApp.java @@ -31,6 +31,8 @@ public class OrbotApp extends Application implements OrbotConstants public static File fileMeekclient; public static File fileXtables; public static File fileTorRc; + public static File filePdnsd; + @Override public void onCreate() { @@ -48,6 +50,9 @@ public class OrbotApp extends Application implements OrbotConstants fileMeekclient = new File(appBinHome, TorServiceConstants.MEEK_ASSET_KEY); fileXtables = new File(appBinHome, TorServiceConstants.IPTABLES_ASSET_KEY); fileTorRc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY); + filePdnsd = new File(appBinHome, TorServiceConstants.PDNSD_ASSET_KEY); + + } diff --git a/src/org/torproject/android/service/TorResourceInstaller.java b/src/org/torproject/android/service/TorResourceInstaller.java index 2f946a91..97e691cf 100644 --- a/src/org/torproject/android/service/TorResourceInstaller.java +++ b/src/org/torproject/android/service/TorResourceInstaller.java @@ -127,8 +127,8 @@ public class TorResourceInstaller implements TorServiceConstants { streamToFile(is,outFile, false, true); setExecutable(outFile); - is = context.getAssets().open(cpuPath + '/' + TUN2SOCKS_ASSET_KEY + MP3_EXT); - outFile = new File(installFolder, TUN2SOCKS_ASSET_KEY); + is = context.getAssets().open(cpuPath + '/' + PDNSD_ASSET_KEY + MP3_EXT); + outFile = new File(installFolder, PDNSD_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); setExecutable(outFile); diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 952c732d..5513e780 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -647,8 +647,9 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (Prefs.useDebugLogging()) { extraLines.append("Log debug syslog").append('\n'); - extraLines.append("Log info syslog").append('\n'); - + extraLines.append("Log info syslog").append('\n'); + extraLines.append("SafeLogging 0").append('\n'); + //extraLines.append("Log debug stdout").append('\n'); } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 6c8d546e..77b7a9bf 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -32,18 +32,15 @@ public interface TorServiceConstants { //geoip data file asset key public final static String GEOIP_ASSET_KEY = "geoip"; public final static String GEOIP6_ASSET_KEY = "geoip6"; - - //tun2socks VPN - public final static String TUN2SOCKS_ASSET_KEY = "tun2socks"; - //various console cmds public final static String SHELL_CMD_CHMOD = "chmod"; public final static String SHELL_CMD_KILL = "kill -9"; public final static String SHELL_CMD_RM = "rm"; public final static String SHELL_CMD_PS = "toolbox ps"; public final static String SHELL_CMD_PS_ALT = "ps"; - + + //public final static String SHELL_CMD_PIDOF = "pidof"; public final static String SHELL_CMD_LINK = "ln -s"; public final static String SHELL_CMD_CP = "cp"; @@ -135,14 +132,18 @@ public interface TorServiceConstants { public static final String CMD_VPN_CLEAR = "vpnclear"; public static final String CMD_UPDATE_TRANS_PROXY = "update"; - public static final String BINARY_TOR_VERSION = "0.2.7.5"; + public static final String BINARY_TOR_VERSION = "0.2.7.5-020120160125"; public static final String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED"; //obfsproxy public static final String OBFSCLIENT_ASSET_KEY = "obfs4proxy"; public static final String MEEK_ASSET_KEY = "meek-client"; + //name of the iptables binary public final static String IPTABLES_ASSET_KEY = "xtables"; + //DNS daemon for TCP DNS over TOr + public final static String PDNSD_ASSET_KEY = "pdnsd"; + } diff --git a/src/org/torproject/android/vpn/OrbotVpnService.java b/src/org/torproject/android/vpn/OrbotVpnService.java index 709a3da4..64854238 100644 --- a/src/org/torproject/android/vpn/OrbotVpnService.java +++ b/src/org/torproject/android/vpn/OrbotVpnService.java @@ -16,13 +16,20 @@ package org.torproject.android.vpn; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; import java.net.InetAddress; import java.util.ArrayList; import java.util.Locale; +import java.util.concurrent.TimeoutException; import org.sufficientlysecure.rootcommands.Shell; import org.sufficientlysecure.rootcommands.command.SimpleCommand; import org.torproject.android.OrbotApp; +import org.torproject.android.R; import org.torproject.android.service.TorServiceConstants; import org.torproject.android.service.TorServiceUtils; import org.torproject.android.settings.AppManager; @@ -30,6 +37,7 @@ import org.torproject.android.settings.TorifiedApp; import android.annotation.TargetApi; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; @@ -64,6 +72,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + private final static String DEFAULT_ACTUAL_DNS = "208.67.222.222"; + private boolean isRestart = false; @Override @@ -245,11 +255,15 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { Thread.sleep(3000); } + //start PDNSD daemon pointing to OpenDNS + startDNS(DEFAULT_ACTUAL_DNS,53); + + final String vpnName = "OrbotVPN"; final String localhost = "127.0.0.1"; - // final String virtualGateway = "10.0.0.1"; - final String virtualIP = "192.168.10.1"; + final String virtualGateway = "10.10.10.1"; + final String virtualIP = "10.10.10.2"; final String virtualNetMask = "255.255.255.0"; final String dummyDNS = "8.8.8.8"; //this is intercepted by the tun2socks library, but we must put in a valid DNS to start final String defaultRoute = "0.0.0.0"; @@ -257,21 +271,25 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { final String localSocks = localhost + ':' + String.valueOf(TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); - final String localDNS = localhost + ':' + String.valueOf(TorServiceConstants.TOR_DNS_PORT_DEFAULT); + final String localDNS = virtualGateway + ':' + "8091";//String.valueOf(TorServiceConstants.TOR_DNS_PORT_DEFAULT); final boolean localDnsTransparentProxy = true; Builder builder = new Builder(); builder.setMtu(VPN_MTU); - builder.addAddress(virtualIP,24); - builder.setSession(vpnName); + builder.addAddress(virtualGateway,32); + builder.setSession(vpnName); + + builder.addDnsServer(dummyDNS); + builder.addRoute(dummyDNS,32); + //route all traffic through VPN (we might offer country specific exclude lists in the future) builder.addRoute(defaultRoute,0); - builder.addDnsServer(dummyDNS); - builder.addRoute(dummyDNS,32); - + //handle ipv6 + //builder.addAddress("fdfe:dcba:9876::1", 126); + //builder.addRoute("::", 0); if (mIsLollipop) doLollipopAppRouting(builder); @@ -313,19 +331,19 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { ArrayList apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); - boolean appAllowed = false; + boolean perAppEnabled = false; for (TorifiedApp app : apps) { if (app.isTorified()) { builder.addAllowedApplication(app.getUsername()); - appAllowed = true; + perAppEnabled = true; } } - if (!appAllowed) + if (!perAppEnabled) builder.addDisallowedApplication(getPackageName()); } @@ -346,4 +364,50 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { super.onRevoke(); } + private void startDNS (String dns, int port) throws IOException, TimeoutException + { + makePdnsdConf(this, dns, port,OrbotApp.filePdnsd.getParentFile() ); + + ArrayList customEnv = new ArrayList(); + String baseDirectory = OrbotApp.filePdnsd.getParent(); + Shell shell = Shell.startShell(customEnv, baseDirectory); + + String cmdString = OrbotApp.filePdnsd.getCanonicalPath() + + " -c " + baseDirectory + "/pdnsd.conf"; + + SimpleCommand shellCommand = new SimpleCommand(cmdString); + shell.add(shellCommand).waitForFinish(); + + + } + + public static void makePdnsdConf(Context context, String dns, int port, File fileDir) throws FileNotFoundException { + String conf = String.format(context.getString(R.string.pdnsd_conf), dns, port); + + File f = new File(fileDir,"pdnsd.conf"); + + if (f.exists()) { + f.delete(); + } + + FileOutputStream fos = new FileOutputStream(f, false); + PrintStream ps = new PrintStream(fos); + ps.print(conf); + ps.close(); + + //f.withWriter { out -> out.print conf }; + + + File cache = new File(fileDir,"pdnsd.cache"); + + if (!cache.exists()) { + try { + cache.createNewFile(); + } catch (Exception e) { + + } + } +} + + }

    4X$+>vvW3%pZ^(kj0 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