diff --git a/CHANGES b/CHANGES index 2b432bcb3b..b96114bbf7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2660. [func] Add a new set of DNS libraries for non-BIND9 + applications. See README.libdns. [RT #19369] + 2659. [doc] Clarify dnssec-keygen doc: key name must match zone name for DNSSEC keys. [RT #19938] diff --git a/Makefile.in b/Makefile.in index 0021dadc2d..f2b730e30c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.56 2009/06/25 17:06:42 each Exp $ +# $Id: Makefile.in,v 1.57 2009/09/01 00:22:24 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -21,13 +21,13 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ -SUBDIRS = make lib bin doc +SUBDIRS = make lib bin doc @LIBEXPORT@ TARGETS = MANPAGES = isc-config.sh.1 - + HTMLPAGES = isc-config.sh.html - + MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ diff --git a/README b/README index 51dd578120..f2962f2946 100644 --- a/README +++ b/README @@ -66,11 +66,11 @@ BIND 9.7.0 - Smart signing: simplified tools for zone signing and key maintenance - The "statistics-channels" option is now available on Windows + - DNSSEC-aware libdns API Planned but not complete in this alpha: - Fully automatic signing of zones by "named" - - DNSSEC-aware libdns API - Improved PKCS#11 support, including Keyper support BIND 9.6.0 diff --git a/README.libdns b/README.libdns new file mode 100644 index 0000000000..2a16b7b1ba --- /dev/null +++ b/README.libdns @@ -0,0 +1,275 @@ + + BIND-9 DNS Library Support + +This version of BIND9 "exports" its internal libraries so that they +can be used by third-party applications more easily (we call them +"export" libraries in this document). In addition to all major +DNS-related APIs BIND9 is currently using, the export libraries +provide the following features: + +- The newly created "DNS client" module. This is a higher level API + that provides an interface to name resolution, single DNS + transaction with a particular server, and dynamic update. Regarding + name resolution, it supports advanced features such as DNSSEC + validation and caching. This module supports both synchronous and + asynchronous mode. +- The new "IRS" (Information Retrieval System) library. It provides + an interface to parse the traditional resolv.conf file and more + advanced, DNS-specific configuration file for the rest of this + package (see the description for the dns.conf file below). +- As part of the IRS library, newly implemented standard address-name + mapping functions, getaddrinfo() and getnameinfo(), are provided. + They use the DNSSEC-aware validating resolver backend, and could use + other advanced features of the BIND9 libraries such as caching. The + getaddrinfo() function resolves both A and AAAA RRs concurrently + (when the address family is unspecified). +- An experimental framework to support other event libraries than + BIND9's internal event task system. + +* Prerequisite + +GNU make is required to build the export libraries (other part of +BIND9 can still be built with other types of make). In the reminder +of this document, "make" means GNU make. Note that in some platforms +you may need to invoke a different command name than "make" +(e.g. "gmake") to indicate it's GNU make. + +* Compilation + +1. ./configure --enable-exportlib [other flags] +2. make + +This will create (in addition to usual BIND9 programs) and a separate +set of libraries under the lib/export directory. For example, +lib/export/dns/libdns.a is the archive file of the export version of +the BIND9 DNS library. + +Sample application programs using the libraries will also be built +under the lib/export/samples directory (see below). + +* Installation + +1. cd lib/export +2. make install (root privilege is normally required) + (make install at the top directory will do the same) + +This will install library object files under the directory specified +by the --with-export-libdir configure option (default: +EPREFIX/lib/bind9), and header files under the directory specified by +the --with-export-installdir configure option (default: +PREFIX/include/bind9). + +To see how to build your own application after the installation, see +lib/export/samples/Makefile-postinstall.in + +* Known Defects/Restrictions + +- Currently, win32 is not supported for the export library. (Normal + BIND9 application can be built as before). +- The "fixed" RRset order is not (currently) supported in the export + library. If you want to use "fixed" RRset order for, e.g. named + while still building the export library even without the fixed + order support, build them separately: + % ./configure --enable-fixed-rrset [other flags, but not --enable-exportlib] + % make (this doesn't have to be make) + % ./configure --enable-exportlib [other flags, but not --enable-fixed-rrset] + % cd lib/export + % make +- The client module and the IRS library currently do not support + DNSSEC validation using DLV (the underlying modules can handle it, + but there is no tunable interface to enable the feature). +- RFC5011 is not supported in the validating stub resolver of the + export library. In fact, it is not clear whether it should: trust + anchors would be a system-wide configuration which would be managed + by an administrator, while the stub resolver will be used by + ordinary applications run by a normal user. +- Not all common /etc/resolv.conf options are supported in the IRS library. + The only available options in this version are "debug" and "ndots". + +* The dns.conf File + +The IRS library supports an "advanced" configuration file related to +the DNS library for configuration parameters that would be beyond the +capability of the resolv.conf file. Specifically, it is intended to +provide DNSSEC related configuration parameters. + +By default the path to this configuration file is /etc/dns.conf. + +This module is very experimental and the configuration syntax or +library interfaces may change in future versions. Currently, only the +'trusted-keys' statement is supported, whose syntax is the same as the +same name of statement for named.conf. + +* Sample Applications + +Some sample application programs using this API are provided for +reference. The following is a brief description of these +applications. + +- sample: a simple stub resolver utility. + + It sends a query of a given name (of a given optional RR type) + to a specified recursive server, and prints the result as a list of + RRs. It can also act as a validating stub resolver if a trust + anchor is given via a set of command line options. + + Usage: sample [options] server_address hostname + + Options and Arguments: + -t RRtype + specify the RR type of the query. The default is the A RR. + [-a algorithm] [-e] -k keyname -K keystring + specify a command-line DNS key to validate the answer. For + example, to specify the following DNSKEY of example.com: + example.com. 3600 IN DNSKEY 257 3 5 xxx + specify the options as follows: + -e -k example.com -K "xxx" + -e means that this key is a zone's "key signing key" (as known + as "secure Entry point"). + when -a is omitted rsasha1 will be used by default. + -s domain:alt_server_address + specify a separate recursive server address for the specific + "domain". Example: -s example.com:2001:db8::1234 + server_address + an IP(v4/v6) address of the recursive server to which queries + are sent. + hostname + the domain name for the query + +- sample-async: a simple stub resolver, working asynchronously. + + Similar to "sample", but accepts a list of (query) domain names as a + separate file and resolves the names asynchronously. + + Usage: sample-async [-s server_address] [-t RR_type] input_file + Options and Arguments: + -s server_address + an IPv4 address of the recursive server to which queries are + sent. (IPv6 addresses are not supported in this implementation) + -t RR_type + specify the RR type of the queries. The default is the A RR. + input_file + a list of domain names to be resolved. each line consists of a + single domain name. Example: + www.example.com + mx.examle.net + ns.xxx.example + +- sample-request: a simple DNS transaction client. + + It sends a query to a specified server, and prints the response with + minimal processing. It doesn't act as a "stub resolver": it stops + the processing once it gets any response from the server, whether + it's a referral or an alias (CNAME or DNAME) that would require + further queries to get the ultimate answer. In other words, this + utility acts as a very simplified dig. + + Usage: sample-request [-t RRtype] server_address hostname + Options and Arguments: + -t RRtype + specify the RR type of the queries. The default is the A RR. + server_address + an IP(v4/v6) address of the recursive server to which the query is + sent. + hostname + the domain name for the query + +- sample-gai: getaddrinfo() and getnameinfo() test code. + + This is a test program to check getaddrinfo() and getnameinfo() + behavior. It takes a host name as an argument, calls getaddrinfo() + with the given host name, and calls getnameinfo() with the resulting + IP addresses returned by getaddrinfo(). If the dns.conf file exists + and defines a trust anchor, the underlying resolver will act as a + validating resolver, and getaddrinfo()/getnameinfo() will fail with + an EAI_INSECUREDATA error when DNSSEC validation fails. + + Usage: sample-gai hostname + +- sample-update: a simple dynamic update client program + + It accepts a single update command as a command-line argument, sends + an update request message to the authoritative server, and shows the + response from the server. In other words, this is a simplified + nsupdate. + + Usage: sample-update [options] (add|delete) "update data" + Options and Arguments: + -a auth_server + An IP address of the authoritative server that has authority + for the zone containing the update name. This should normally + be the primary authoritative server that accepts dynamic + updates. It can also be a secondary server that is configured + to forward update requests to the primary server. + -k keyfile + A TSIG key file to secure the update transaction. The keyfile + format is the same as that for the nsupdate utility. + -p prerequisite + A prerequisite for the update (only one prerequisite can be + specified). The prerequisite format is the same as that is + accepted by the nsupdate utility. + -r recursive_server + An IP address of a recursive server that this utility will + use. A recursive server may be necessary to identify the + authoritative server address to which the update request is + sent. + -z zonename + The domain name of the zone that contains + (add|delete) + Specify the type of update operation. Either "add" or "delete" + must be specified. + "update data" + Specify the data to be updated. A typical example of the data + would look like "name TTL RRtype RDATA". + + Note: in practice, either -a or -r must be specified. Others can + be optional; the underlying library routine tries to identify the + appropriate server and the zone name for the update. + + Examples: assuming the primary authoritative server of the + dynamic.example.com zone has an IPv6 address 2001:db8::1234, + + sample-update -a sample-update -k Kxxx.+nnn+mmmm.key add "foo.dynamic.example.com 30 IN A 192.168.2.1" + adds an A RR for foo.dynamic.example.com using the given key. + + sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com 30 IN A" + removes all A RRs for foo.dynamic.example.com using the given key. + + sample-update -a sample-update -k Kxxx.+nnn+mmmm.key delete "foo.dynamic.example.com" + removes all RRs for foo.dynamic.example.com using the given key. + +- nsprobe: domain/name server checker in terms of RFC4074. + + It checks a set of domains to see the name servers of the domains + behave correctly in terms of RFC4074. This is included in the set + of sample programs to show how the export library can be used in a + DNS-related application. + + Usage: nsprobe [-d] [-v [-v...]] [-c cache_address] [input_file] + Options + -d + run in the "debug" mode. with this option nsprobe will dump + every RRs it receives. + -v + increase verbosity of other normal log messages. This can be + specified multiple times + -c cache_address + specify an IP address of a recursive (caching) name server. + nsprobe uses this server to get the NS RRset of each domain and + the A and/or AAAA RRsets for the name servers. The default + value is 127.0.0.1. + input_file + a file name containing a list of domain (zone) names to be + probed. when omitted the standard input will be used. Each + line of the input file specifies a single domain name such as + "example.com". In general this domain name must be the apex + name of some DNS zone (unlike normal "host names" such as + "www.example.com"). nsprobe first identifies the NS RRsets for + the given domain name, and sends A and AAAA queries to these + servers for some "widely used" names under the zone; + specifically, adding "www" and "ftp" to the zone name. + +* Library References + +As of this writing, there is no formal "manual" of the libraries, +except this document, header files (some of them provide pretty +detailed explanations), and sample application programs. + +; $Id: README.libdns,v 1.2 2009/09/01 00:22:24 jinmei Exp $ diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in index 06f55418b4..488a143d83 100644 --- a/bin/check/Makefile.in +++ b/bin/check/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2007/06/19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.33 2009/09/01 00:22:24 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISCCFG_INCLUDES} \ ${ISC_INCLUDES} -CDEFINES = -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" +CDEFINES = -DBIND9 -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c index 0bad407aa7..09fd2c9900 100644 --- a/bin/check/check-tool.c +++ b/bin/check/check-tool.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.c,v 1.38 2009/01/20 02:01:11 marka Exp $ */ +/* $Id: check-tool.c,v 1.39 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -597,8 +597,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, isc_buffer_add(&buffer, strlen(zonename)); dns_fixedname_init(&fixorigin); origin = dns_fixedname_name(&fixorigin); - CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); CHECK(dns_zone_setorigin(zone, origin)); CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); CHECK(dns_zone_setfile2(zone, filename, fileformat)); diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in index b67ccdd04e..be9fc385b8 100644 --- a/bin/confgen/Makefile.in +++ b/bin/confgen/Makefile.in @@ -12,7 +12,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.4 2009/07/14 22:54:56 each Exp $ +# $Id: Makefile.in,v 1.5 2009/09/01 00:22:24 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in index bc9d34f044..ad8f2e8d98 100644 --- a/bin/dig/Makefile.in +++ b/bin/dig/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.41 2007/06/19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.42 2009/09/01 00:22:24 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISC_INCLUDES} ${LWRES_INCLUDES} -CDEFINES = -DVERSION=\"${VERSION}\" +CDEFINES = -DBIND9 -DVERSION=\"${VERSION}\" CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 271f806e49..f1fa25ef7b 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.323 2009/07/19 04:18:03 each Exp $ */ +/* $Id: dighost.c,v 1.324 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file * \note @@ -921,9 +921,7 @@ setup_text_key(void) { secretsize = isc_buffer_usedlength(&secretbuf); - result = dns_name_fromtext(&keyname, namebuf, - dns_rootname, ISC_FALSE, - namebuf); + result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); if (result != ISC_R_SUCCESS) goto failure; @@ -1890,7 +1888,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->origin->origin, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->oname, &b, dns_rootname, - ISC_FALSE, &lookup->onamebuf); + 0, &lookup->onamebuf); if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); @@ -1907,7 +1905,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - lookup->oname, ISC_FALSE, + lookup->oname, 0, &lookup->namebuf); } if (result != ISC_R_SUCCESS) { @@ -1931,16 +1929,14 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, idn_textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #else len = strlen(lookup->textname); isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #endif } @@ -4085,7 +4081,7 @@ nameFromString(const char *str, dns_name_t *p_ret) { dns_fixedname_init(&fixedname); result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); check_result(result, "nameFromString"); if (dns_name_dynamic(p_ret)) diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in index af6f3a556f..ef4bedbcf5 100644 --- a/bin/dnssec/Makefile.in +++ b/bin/dnssec/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.38 2009/07/19 04:18:04 each Exp $ +# $Id: Makefile.in,v 1.39 2009/09/01 00:22:24 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = -DVERSION=\"${VERSION}\" +CDEFINES = -DBIND9 -DVERSION=\"${VERSION}\" CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c index 9e152439b3..9b1b55a8b7 100644 --- a/bin/dnssec/dnssec-dsfromkey.c +++ b/bin/dnssec/dnssec-dsfromkey.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-dsfromkey.c,v 1.12 2009/08/13 04:13:58 marka Exp $ */ +/* $Id: dnssec-dsfromkey.c,v 1.13 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -72,7 +72,7 @@ initname(char *setname) { isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); - result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); return (result); } diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c index 02bba62a11..f0df650ee3 100644 --- a/bin/dnssec/dnssec-keyfromlabel.c +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keyfromlabel.c,v 1.9 2009/07/19 04:18:04 each Exp $ */ +/* $Id: dnssec-keyfromlabel.c,v 1.10 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -273,7 +273,7 @@ main(int argc, char **argv) { isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index d2188478f2..60451ec23e 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.89 2009/07/19 23:47:55 tbox Exp $ */ +/* $Id: dnssec-keygen.c,v 1.90 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -567,7 +567,7 @@ main(int argc, char **argv) { isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 1a0c97cf20..d369298227 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.227 2009/08/14 01:07:00 each Exp $ */ +/* $Id: dnssec-signzone.c,v 1.228 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -2486,7 +2486,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("failed converting name '%s' to dns format: %s", origin, isc_result_totext(result)); @@ -3274,8 +3274,8 @@ main(int argc, char *argv[]) { dns_fixedname_init(&dlv_fixed); dlv = dns_fixedname_name(&dlv_fixed); - result = dns_name_fromtext(dlv, &b, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(dlv, &b, dns_rootname, 0, + NULL); check_result(result, "dns_name_fromtext(dlv)"); break; diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index 69438e2f04..cd2a0247ae 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.104 2009/03/05 23:47:35 tbox Exp $ +# $Id: Makefile.in,v 1.105 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -45,7 +45,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} -CDEFINES = @USE_DLZ@ +CDEFINES = -DBIND9 @USE_DLZ@ CWARNINGS = diff --git a/bin/named/config.c b/bin/named/config.c index 8d89c89cf4..ef64482670 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.99 2009/07/14 22:54:56 each Exp $ */ +/* $Id: config.c,v 1.100 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -651,7 +651,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, diff --git a/bin/named/lwdgabn.c b/bin/named/lwdgabn.c index dec1e1a571..761b741500 100644 --- a/bin/named/lwdgabn.c +++ b/bin/named/lwdgabn.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgabn.c,v 1.22 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: lwdgabn.c,v 1.23 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -619,7 +619,7 @@ ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->target_name); dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c index b54e83d0dd..c3bbe58b5d 100644 --- a/bin/named/lwdgrbn.c +++ b/bin/named/lwdgrbn.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgrbn.c,v 1.20 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: lwdgrbn.c,v 1.21 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -472,7 +472,7 @@ ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c index 4e245fdb3d..f32c8cb37e 100644 --- a/bin/named/lwresd.c +++ b/bin/named/lwresd.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.c,v 1.58 2008/07/23 23:27:54 marka Exp $ */ +/* $Id: lwresd.c,v 1.59 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file * \brief @@ -372,8 +372,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, - dns_rootname, ISC_FALSE, - NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, diff --git a/bin/named/server.c b/bin/named/server.c index 7302cdf064..b4a1a8cf06 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.542 2009/08/25 23:47:51 tbox Exp $ */ +/* $Id: server.c,v 1.543 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -422,8 +422,7 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, str = cfg_obj_asstring(nameobj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); /* * We don't need the node data, but need to set dummy data to * avoid a partial match with an empty node. For example, if @@ -526,9 +525,7 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, dns_fixedname_init(&fkeyname); isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); - CHECK(dns_name_fromtext(keyname, &namebuf, - dns_rootname, ISC_FALSE, - NULL)); + CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, mctx, &dstkey)); @@ -712,8 +709,7 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); CHECK(dns_resolver_setmustbesecure(resolver, name, value)); } @@ -873,7 +869,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { isc_buffer_add(&b, strlen(str)); dns_fixedname_init(&fixed); result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -1057,7 +1053,7 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); algorithms = cfg_tuple_get(disabled, "algorithms"); for (element = cfg_list_first(algorithms); @@ -1110,7 +1106,7 @@ on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dns_name_equal(name, zonename)) return (ISC_TRUE); @@ -2111,7 +2107,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL)); + 0, NULL)); #endif str = cfg_obj_asstring(cfg_tuple_get(obj, "trust-anchor")); @@ -2119,7 +2115,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_buffer_add(&b, strlen(str)); dlv = dns_fixedname_name(&view->dlv_fixed); CHECK(dns_name_fromtext(dlv, &b, dns_rootname, - ISC_TRUE, NULL)); + DNS_NAME_DOWNCASE, NULL)); view->dlv = dns_fixedname_name(&view->dlv_fixed); } } else @@ -2171,7 +2167,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + 0, NULL)); CHECK(dns_view_excludedelegationonly(view, name)); } @@ -2224,8 +2220,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, server, sizeof(server) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); server[isc_buffer_usedlength(&buffer)] = 0; @@ -2239,8 +2235,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, contact, sizeof(contact) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); contact[isc_buffer_usedlength(&buffer)] = 0; @@ -2266,8 +2262,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Look for zone on drop list. */ - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); if (disablelist != NULL && on_disable_list(disablelist, name)) continue; @@ -2457,8 +2453,8 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, isc_buffer_add(&buffer, strlen(str)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); portobj = cfg_tuple_get(alternate, "port"); if (cfg_obj_isuint32(portobj)) { @@ -2671,7 +2667,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), - &buffer, dns_rootname, ISC_FALSE, NULL)); + &buffer, dns_rootname, 0, NULL)); origin = dns_fixedname_name(&fixorigin); CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), @@ -3471,8 +3467,7 @@ configure_session_key(const cfg_obj_t **maps, ns_server_t *server, isc_buffer_init(&buffer, keynamestr, strlen(keynamestr)); isc_buffer_add(&buffer, strlen(keynamestr)); keyname = dns_fixedname_name(&fname); - result = dns_name_fromtext(keyname, &buffer, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -5053,7 +5048,7 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { isc_buffer_add(&buf, strlen(zonetxt)); dns_fixedname_init(&name); result = dns_name_fromtext(dns_fixedname_name(&name), - &buf, dns_rootname, ISC_FALSE, NULL); + &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto fail1; @@ -5894,7 +5889,7 @@ ns_server_flushname(ns_server_t *server, char *args) { isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c index 82cf573bf7..52f5f105c1 100644 --- a/bin/named/tkeyconf.c +++ b/bin/named/tkeyconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.c,v 1.29 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: tkeyconf.c,v 1.30 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -77,8 +77,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH, type, NULL, mctx, &tctx->dhkey)); @@ -92,8 +91,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); if (tctx->domain == NULL) { result = ISC_R_NOMEMORY; @@ -112,10 +110,8 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); - RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, - &tctx->gsscred)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } *tctxp = tctx; diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c index f44dcd7eb4..5e06b0f64a 100644 --- a/bin/named/tsigconf.c +++ b/bin/named/tsigconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.c,v 1.32 2009/06/11 23:47:55 tbox Exp $ */ +/* $Id: tsigconf.c,v 1.33 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -82,7 +82,7 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, - ISC_TRUE, &keynamebuf); + DNS_NAME_DOWNCASE, &keynamebuf); if (ret != ISC_R_SUCCESS) goto failure; diff --git a/bin/named/unix/Makefile.in b/bin/named/unix/Makefile.in index 5092834001..00bf2e0696 100644 --- a/bin/named/unix/Makefile.in +++ b/bin/named/unix/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.10 2007/06/19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.11 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = OBJS = os.@O@ diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 1ecc4b96b3..f56da44899 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.153 2009/07/14 23:47:53 tbox Exp $ */ +/* $Id: zoneconf.c,v 1.154 2009/09/01 00:22:25 jinmei Exp $ */ /*% */ @@ -260,7 +260,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); @@ -283,8 +283,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fname), - &b, dns_rootname, - ISC_FALSE, NULL); + &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in index b479eb7e93..00d0fbd23e 100644 --- a/bin/nsupdate/Makefile.in +++ b/bin/nsupdate/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2009/07/14 22:54:56 each Exp $ +# $Id: Makefile.in,v 1.33 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISC_INCLUDES} ${ISCCFG_INCLUDES} @DST_GSSAPI_INC@ -CDEFINES = @USE_GSSAPI@ +CDEFINES = -DBIND9 @USE_GSSAPI@ CWARNINGS = LWRESLIBS = ../../lib/lwres/liblwres.@A@ diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 27c61742e0..c62a8418bf 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.171 2009/07/19 04:18:04 each Exp $ */ +/* $Id: nsupdate.c,v 1.172 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -526,8 +526,7 @@ setup_keystr(void) { isc_buffer_add(&keynamesrc, n - name); debug("namefromtext"); - result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); secretlen = strlen(secretstr) * 3 / 4; @@ -1110,8 +1109,7 @@ parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { dns_message_takebuffer(msg, &namebuf); isc_buffer_init(&source, word, strlen(word)); isc_buffer_add(&source, strlen(word)); - result = dns_name_fromtext(*namep, &source, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); isc_buffer_invalidate(&source); return (STATUS_MORE); @@ -1433,7 +1431,7 @@ evaluate_key(char *cmdline) { isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); - result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not parse key name\n"); return (STATUS_SYNTAX); @@ -1490,8 +1488,7 @@ evaluate_zone(char *cmdline) { userzone = dns_fixedname_name(&fuserzone); isc_buffer_init(&b, word, strlen(word)); isc_buffer_add(&b, strlen(word)); - result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { userzone = NULL; /* Lest it point to an invalid name */ fprintf(stderr, "could not parse zone name\n"); @@ -2426,8 +2423,7 @@ start_gssrequest(dns_name_t *master) isc_result_totext(result)); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(servname) failed: %s", isc_result_totext(result)); @@ -2444,8 +2440,7 @@ start_gssrequest(dns_name_t *master) isc_buffer_init(&buf, keystr, strlen(keystr)); isc_buffer_add(&buf, strlen(keystr)); - result = dns_name_fromtext(keyname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(keyname) failed: %s", isc_result_totext(result)); @@ -2596,8 +2591,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { servname = dns_fixedname_name(&fname); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); tsigkey = NULL; diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in index d6892d1270..6ec10ba7d3 100644 --- a/bin/rndc/Makefile.in +++ b/bin/rndc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.46 2009/06/11 23:47:55 tbox Exp $ +# $Id: Makefile.in,v 1.47 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in index ac3a51adbe..20f1206046 100644 --- a/bin/tests/Makefile.in +++ b/bin/tests/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.134 2009/03/02 03:53:29 each Exp $ +# $Id: Makefile.in,v 1.135 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ ${LWRES_INCLUDES} ${OMAPI_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/adb_test.c b/bin/tests/adb_test.c index 2ef812d70d..a63a2537e2 100644 --- a/bin/tests/adb_test.c +++ b/bin/tests/adb_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb_test.c,v 1.68 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: adb_test.c,v 1.69 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file */ @@ -249,8 +249,7 @@ lookup(const char *target) { isc_buffer_add(&t, strlen(target)); isc_buffer_init(&namebuf, namedata, sizeof(namedata)); dns_name_init(&name, NULL); - result = dns_name_fromtext(&name, &t, dns_rootname, ISC_FALSE, - &namebuf); + result = dns_name_fromtext(&name, &t, dns_rootname, 0, &namebuf); check_result(result, "dns_name_fromtext %s", target); result = dns_name_dup(&name, mctx, &client->name); diff --git a/bin/tests/byname_test.c b/bin/tests/byname_test.c index fdf45a9891..1c3ea711a3 100644 --- a/bin/tests/byname_test.c +++ b/bin/tests/byname_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: byname_test.c,v 1.31 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: byname_test.c,v 1.32 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file * \author @@ -343,7 +343,7 @@ main(int argc, char *argv[]) { dns_fixedname_init(&name); dns_fixedname_init(&target); RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&name), &b, - dns_rootname, ISC_FALSE, NULL) == + dns_rootname, 0, NULL) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS); diff --git a/bin/tests/db/Makefile.in b/bin/tests/db/Makefile.in index 13ebad269e..fe9e28398e 100644 --- a/bin/tests/db/Makefile.in +++ b/bin/tests/db/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.29 2007/06/19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.30 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/db/t_db.c b/bin/tests/db/t_db.c index 6ec057a53a..3a7a2a725a 100644 --- a/bin/tests/db/t_db.c +++ b/bin/tests/db/t_db.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: t_db.c,v 1.38 2009/01/22 23:47:53 tbox Exp $ */ +/* $Id: t_db.c,v 1.39 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -61,7 +61,7 @@ t_create(const char *db_type, const char *origin, const char *class, isc_buffer_init(&origin_buffer, origin, len); isc_buffer_add(&origin_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), - &origin_buffer, NULL, ISC_FALSE, NULL); + &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -190,7 +190,7 @@ t_dns_db_load(char **av) { isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &findname_buffer, NULL, ISC_FALSE, NULL); + &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -305,7 +305,7 @@ t_dns_db_zc_x(char *filename, char *db_type, char *origin, char *class, isc_buffer_init(&origin_buffer, origin, len); isc_buffer_add(&origin_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), - &origin_buffer, NULL, ISC_FALSE, NULL); + &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -584,7 +584,7 @@ t_dns_db_origin(char **av) { } dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), - &origin_buffer, NULL, ISC_FALSE, NULL); + &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -832,7 +832,7 @@ t_dns_db_currentversion(char **av) { isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &findname_buffer, NULL, ISC_FALSE, NULL); + &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -1123,7 +1123,7 @@ t_dns_db_newversion(char **av) { isc_buffer_init(&newname_buffer, newname, len); isc_buffer_add(&newname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), - &newname_buffer, NULL, ISC_FALSE, NULL); + &newname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -1449,7 +1449,7 @@ t_dns_db_closeversion_1(char **av) { isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -1528,7 +1528,7 @@ t_dns_db_closeversion_1(char **av) { isc_buffer_init(&name_buffer, new_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -1861,7 +1861,7 @@ t_dns_db_closeversion_2(char **av) { isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -1942,7 +1942,7 @@ t_dns_db_closeversion_2(char **av) { isc_buffer_init(&name_buffer, new_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -2279,7 +2279,7 @@ t_dns_db_expirenode(char **av) { isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); @@ -2525,7 +2525,7 @@ t_dns_db_findnode_1(char **av) { isc_buffer_init(&name_buffer, find_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_FALSE, &nodep); @@ -2681,7 +2681,7 @@ t_dns_db_findnode_2(char **av) { isc_buffer_init(&name_buffer, newname, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name), - &name_buffer, NULL, ISC_FALSE, NULL); + &name_buffer, NULL, 0, NULL); dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_FALSE, &nodep); @@ -2886,7 +2886,7 @@ t_dns_db_find_x(char **av) { isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &findname_buffer, NULL, ISC_FALSE, NULL); + &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); diff --git a/bin/tests/db_test.c b/bin/tests/db_test.c index 9b0d90d2b2..1cd8f0dfc7 100644 --- a/bin/tests/db_test.c +++ b/bin/tests/db_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db_test.c,v 1.66 2008/09/25 04:02:38 tbox Exp $ */ +/* $Id: db_test.c,v 1.67 2009/09/01 00:22:25 jinmei Exp $ */ /*! \file * \author @@ -134,8 +134,7 @@ select_db(char *origintext) { isc_buffer_add(&source, len); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); - result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { print_result("bad name", result); return (NULL); @@ -188,8 +187,7 @@ list(dbinfo *dbi, char *seektext) { result = dns_name_fromtext(seekname, &source, dns_db_origin( dbi->db), - ISC_FALSE, - NULL); + 0, NULL); if (result == ISC_R_SUCCESS) result = dns_dbiterator_seek( dbi->dbiterator, @@ -271,8 +269,7 @@ load(const char *filename, const char *origintext, isc_boolean_t cache) { isc_buffer_add(&source, len); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); - result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -736,8 +733,7 @@ main(int argc, char *argv[]) { isc_buffer_init(&source, s, len); isc_buffer_add(&source, len); isc_buffer_init(&target, b, sizeof(b)); - result = dns_name_fromtext(&name, &source, origin, - ISC_FALSE, &target); + result = dns_name_fromtext(&name, &source, origin, 0, &target); if (result != ISC_R_SUCCESS) { print_result("bad name: ", result); continue; diff --git a/bin/tests/dst/Makefile.in b/bin/tests/dst/Makefile.in index fad70d5aef..72e6e42373 100644 --- a/bin/tests/dst/Makefile.in +++ b/bin/tests/dst/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.48 2009/03/02 23:47:43 tbox Exp $ +# $Id: Makefile.in,v 1.49 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} \ ${ISC_INCLUDES} @DST_GSSAPI_INC@ -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/dst/dst_test.c b/bin/tests/dst/dst_test.c index 597e6356c6..ac1327c99f 100644 --- a/bin/tests/dst/dst_test.c +++ b/bin/tests/dst/dst_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_test.c,v 1.45 2009/03/02 23:47:43 tbox Exp $ */ +/* $Id: dst_test.c,v 1.46 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -264,7 +264,7 @@ main(void) { name = dns_fixedname_name(&fname); isc_buffer_init(&b, "test.", 5); isc_buffer_add(&b, 5); - result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) return (1); io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx); @@ -276,7 +276,7 @@ main(void) { isc_buffer_init(&b, "dh.", 3); isc_buffer_add(&b, 3); - result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) return (1); dh(name, 18602, name, 48957, mctx); diff --git a/bin/tests/dst/gsstest.c b/bin/tests/dst/gsstest.c index 98e16d265b..355fde3a9e 100755 --- a/bin/tests/dst/gsstest.c +++ b/bin/tests/dst/gsstest.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gsstest.c,v 1.6 2007/06/19 23:47:00 tbox Exp $ */ +/* $Id: gsstest.c,v 1.7 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -212,7 +212,7 @@ sendquery(isc_task_t *task, isc_event_t *event) isc_buffer_init(&buf, host, strlen(host)); isc_buffer_add(&buf, strlen(host)); result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); @@ -369,7 +369,7 @@ initctx1(isc_task_t *task, isc_event_t *event) { isc_buffer_init(&buf, contextname, strlen(contextname)); isc_buffer_add(&buf, strlen(contextname)); result = dns_name_fromtext(dns_fixedname_name(&servername), &buf, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); /* Make name happen */ @@ -377,7 +377,7 @@ initctx1(isc_task_t *task, isc_event_t *event) { isc_buffer_init(&buf, gssid, strlen(gssid)); isc_buffer_add(&buf, strlen(gssid)); result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); query = NULL; diff --git a/bin/tests/dst/t_dst.c b/bin/tests/dst/t_dst.c index c801022869..bc430ec64a 100644 --- a/bin/tests/dst/t_dst.c +++ b/bin/tests/dst/t_dst.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: t_dst.c,v 1.57 2009/01/22 23:47:54 tbox Exp $ */ +/* $Id: t_dst.c,v 1.58 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -405,7 +405,7 @@ t1(void) { name = dns_fixedname_name(&fname); isc_buffer_init(&b, "test.", 5); isc_buffer_add(&b, 5); - isc_result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL); + isc_result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", isc_result_totext(isc_result)); @@ -427,7 +427,7 @@ t1(void) { isc_buffer_init(&b, "dh.", 3); isc_buffer_add(&b, 3); - isc_result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL); + isc_result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", isc_result_totext(isc_result)); @@ -686,7 +686,7 @@ t2_sigchk(char *datapath, char *sigpath, char *keyname, name = dns_fixedname_name(&fname); isc_buffer_init(&b, keyname, strlen(keyname)); isc_buffer_add(&b, strlen(keyname)); - isc_result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + isc_result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", isc_result_totext(isc_result)); diff --git a/bin/tests/master/Makefile.in b/bin/tests/master/Makefile.in index 03125da11c..61b6761db5 100644 --- a/bin/tests/master/Makefile.in +++ b/bin/tests/master/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.28 2007/06/19 23:47:00 tbox Exp $ +# $Id: Makefile.in,v 1.29 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = # Note that we do not want to use libtool for libt_api diff --git a/bin/tests/master/t_master.c b/bin/tests/master/t_master.c index 8df588b0c6..496b79aa37 100644 --- a/bin/tests/master/t_master.c +++ b/bin/tests/master/t_master.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: t_master.c,v 1.38 2009/01/22 23:47:54 tbox Exp $ */ +/* $Id: t_master.c,v 1.39 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -94,7 +94,7 @@ test_master(char *testfile, char *origin, char *class, isc_result_t exp_result) isc_buffer_init(&target, name_buf, BUFLEN); dns_name_init(&dns_origin, NULL); dns_result = dns_name_fromtext(&dns_origin, &source, dns_rootname, - ISC_FALSE, &target); + 0, &target); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); diff --git a/bin/tests/master_test.c b/bin/tests/master_test.c index f77c8f64fc..f0160f436c 100644 --- a/bin/tests/master_test.c +++ b/bin/tests/master_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master_test.c,v 1.30 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: master_test.c,v 1.31 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -75,7 +75,7 @@ main(int argc, char *argv[]) { isc_buffer_init(&target, name_buf, 255); dns_name_init(&origin, NULL); result = dns_name_fromtext(&origin, &source, dns_rootname, - ISC_FALSE, &target); + 0, &target); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_name_fromtext: %s\n", dns_result_totext(result)); diff --git a/bin/tests/mem/Makefile.in b/bin/tests/mem/Makefile.in index 135a8e3ec9..550ebe5611 100644 --- a/bin/tests/mem/Makefile.in +++ b/bin/tests/mem/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.34 2007/06/19 23:47:00 tbox Exp $ +# $Id: Makefile.in,v 1.35 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ diff --git a/bin/tests/name_test.c b/bin/tests/name_test.c index 799115fe06..c54260fa8f 100644 --- a/bin/tests/name_test.c +++ b/bin/tests/name_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name_test.c,v 1.41 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: name_test.c,v 1.42 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -73,7 +73,7 @@ main(int argc, char *argv[]) { isc_buffer_t source; isc_region_t r; dns_name_t *name, *origin, *comp, *down; - isc_boolean_t downcase = ISC_FALSE; + unsigned int downcase = 0; size_t len; isc_boolean_t quiet = ISC_FALSE; isc_boolean_t concatenate = ISC_FALSE; @@ -128,8 +128,7 @@ main(int argc, char *argv[]) { dns_fixedname_init(&oname); origin = &oname.name; result = dns_name_fromtext(origin, &source, - dns_rootname, ISC_FALSE, - NULL); + dns_rootname, 0, NULL); if (result != 0) { fprintf(stderr, "dns_name_fromtext() failed: %d\n", @@ -151,8 +150,8 @@ main(int argc, char *argv[]) { isc_buffer_add(&source, len); dns_fixedname_init(&compname); comp = &compname.name; - result = dns_name_fromtext(comp, &source, - origin, ISC_FALSE, NULL); + result = dns_name_fromtext(comp, &source, origin, + 0, NULL); if (result != 0) { fprintf(stderr, "dns_name_fromtext() failed: %d\n", diff --git a/bin/tests/names/Makefile.in b/bin/tests/names/Makefile.in index 31b12feef9..17711f1ae0 100644 --- a/bin/tests/names/Makefile.in +++ b/bin/tests/names/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.28 2007/06/19 23:47:00 tbox Exp $ +# $Id: Makefile.in,v 1.29 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = # Note that we do not want to use libtool for libt_api diff --git a/bin/tests/names/t_names.c b/bin/tests/names/t_names.c index ce776dec29..ce859dea53 100644 --- a/bin/tests/names/t_names.c +++ b/bin/tests/names/t_names.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: t_names.c,v 1.48 2009/01/22 23:47:54 tbox Exp $ */ +/* $Id: t_names.c,v 1.49 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -344,8 +344,7 @@ dname_from_tname(char *name, dns_name_t *dns_name) { isc_buffer_init(binbuf, junk, BUFLEN); dns_name_init(dns_name, NULL); dns_name_setbuffer(dns_name, binbuf); - result = dns_name_fromtext(dns_name, &txtbuf, - NULL, ISC_FALSE, NULL); + result = dns_name_fromtext(dns_name, &txtbuf, NULL, 0, NULL); } else { result = ISC_R_NOSPACE; if (junk != NULL) @@ -535,7 +534,7 @@ test_dns_name_isabsolute(char *test_name, isc_boolean_t expected) { isc_buffer_init(&binbuf, &junk[0], BUFLEN); dns_name_init(&name, NULL); dns_name_setbuffer(&name, &binbuf); - result = dns_name_fromtext(&name, &buf, NULL, ISC_FALSE, NULL); + result = dns_name_fromtext(&name, &buf, NULL, 0, NULL); if (result == ISC_R_SUCCESS) { isabs_p = dns_name_isabsolute(&name); if (isabs_p == expected) @@ -1659,7 +1658,7 @@ static const char *a40 = static int test_dns_name_fromtext(char *test_name1, char *test_name2, char *test_origin, - isc_boolean_t downcase) + unsigned int downcase) { int result; int order; @@ -1702,8 +1701,8 @@ test_dns_name_fromtext(char *test_name1, char *test_name2, char *test_origin, dns_name_setbuffer(&dns_name2, &binbuf2); dns_name_setbuffer(&dns_name3, &binbuf3); - dns_result = dns_name_fromtext(&dns_name3, &txtbuf3, NULL, - ISC_FALSE, &binbuf3); + dns_result = dns_name_fromtext(&dns_name3, &txtbuf3, NULL, 0, + &binbuf3); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext(dns_name3) failed, result == %s\n", dns_result_totext(dns_result)); @@ -1718,8 +1717,8 @@ test_dns_name_fromtext(char *test_name1, char *test_name2, char *test_origin, return (T_FAIL); } - dns_result = dns_name_fromtext(&dns_name2, &txtbuf2, NULL, - ISC_FALSE, &binbuf2); + dns_result = dns_name_fromtext(&dns_name2, &txtbuf2, NULL, 0, + &binbuf2); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext(dns_name2) failed, result == %s\n", dns_result_totext(dns_result)); @@ -1777,8 +1776,8 @@ t_dns_name_fromtext(void) { Tokens[2], atoi(Tokens[3]) == 0 ? - ISC_FALSE : - ISC_TRUE); + 0 : + DNS_NAME_DOWNCASE); } else { t_info("bad format at line %d\n", line); } @@ -1830,8 +1829,7 @@ test_dns_name_totext(char *test_name, isc_boolean_t omit_final) { /* * Out of the data file to dns_name1. */ - dns_result = dns_name_fromtext(&dns_name1, &buf1, NULL, ISC_FALSE, - &buf2); + dns_result = dns_name_fromtext(&dns_name1, &buf1, NULL, 0, &buf2); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed, result == %s\n", dns_result_totext(dns_result)); @@ -1855,8 +1853,7 @@ test_dns_name_totext(char *test_name, isc_boolean_t omit_final) { */ dns_name_init(&dns_name2, NULL); isc_buffer_init(&buf3, junk3, BUFLEN); - dns_result = dns_name_fromtext(&dns_name2, &buf1, NULL, ISC_FALSE, - &buf3); + dns_result = dns_name_fromtext(&dns_name2, &buf1, NULL, 0, &buf3); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed, result == %s\n", dns_result_totext(dns_result)); @@ -2195,8 +2192,7 @@ test_dns_name_towire(char *testname, unsigned int dc_method, char *exp_data, isc_buffer_init(&iscbuf1, testname, len); isc_buffer_add(&iscbuf1, len); isc_buffer_init(&iscbuf2, buf2, BUFLEN); - dns_result = dns_name_fromtext(&dns_name, &iscbuf1, NULL, ISC_FALSE, - &iscbuf2); + dns_result = dns_name_fromtext(&dns_name, &iscbuf1, NULL, 0, &iscbuf2); if (dns_result == ISC_R_SUCCESS) { isc_buffer_init(&iscbuf3, buf3, buflen); dns_result = dns_name_towire(&dns_name, &cctx, &iscbuf3); diff --git a/bin/tests/net/Makefile.in b/bin/tests/net/Makefile.in index 0c75c28bfa..1c223bf03b 100644 --- a/bin/tests/net/Makefile.in +++ b/bin/tests/net/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.16 2007/06/19 23:47:00 tbox Exp $ +# $Id: Makefile.in,v 1.17 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ diff --git a/bin/tests/nsecify.c b/bin/tests/nsecify.c index 2e055c66d5..d7f841c299 100644 --- a/bin/tests/nsecify.c +++ b/bin/tests/nsecify.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsecify.c,v 1.8 2008/09/25 04:02:38 tbox Exp $ */ +/* $Id: nsecify.c,v 1.9 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -139,7 +139,7 @@ nsecify(char *filename) { len = strlen(origintext); isc_buffer_init(&b, origintext, len); isc_buffer_add(&b, len); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext()"); db = NULL; diff --git a/bin/tests/rbt/Makefile.in b/bin/tests/rbt/Makefile.in index d551297b57..be3cd5a50d 100644 --- a/bin/tests/rbt/Makefile.in +++ b/bin/tests/rbt/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.28 2007/06/19 23:47:00 tbox Exp $ +# $Id: Makefile.in,v 1.29 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = # Note that we do not want to use libtool for libt_api diff --git a/bin/tests/rbt/t_rbt.c b/bin/tests/rbt/t_rbt.c index 848e262452..55ebfd2b77 100644 --- a/bin/tests/rbt/t_rbt.c +++ b/bin/tests/rbt/t_rbt.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: t_rbt.c,v 1.32 2009/01/22 23:47:54 tbox Exp $ */ +/* $Id: t_rbt.c,v 1.33 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -152,7 +152,7 @@ create_name(char *s, isc_mem_t *mctx, dns_name_t **dns_name) { isc_buffer_init(&target, name + 1, DNSNAMELEN); result = dns_name_fromtext(name, &source, dns_rootname, - ISC_FALSE, &target); + 0, &target); if (result != ISC_R_SUCCESS) { ++nfails; @@ -832,7 +832,7 @@ t_dns_rbtnodechain_init(char *dbfile, char *findname, dns_fixedname_init(&dns_nextname); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &isc_buffer, NULL, ISC_FALSE, NULL); + &isc_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", @@ -1494,7 +1494,7 @@ t_dns_rbtnodechain_next(char *dbfile, char *findname, dns_fixedname_init(&dns_origin); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &isc_buffer, NULL, ISC_FALSE, NULL); + &isc_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", @@ -1701,7 +1701,7 @@ t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname, dns_fixedname_init(&dns_origin); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), - &isc_buffer, NULL, ISC_FALSE, NULL); + &isc_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", diff --git a/bin/tests/rbt_test.c b/bin/tests/rbt_test.c index ac8db14e45..93e4705447 100644 --- a/bin/tests/rbt_test.c +++ b/bin/tests/rbt_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt_test.c,v 1.48 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: rbt_test.c,v 1.49 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -71,8 +71,7 @@ create_name(char *s) { dns_name_init(name, NULL); isc_buffer_init(&target, name + 1, DNSNAMELEN); - result = dns_name_fromtext(name, &source, dns_rootname, - ISC_FALSE, &target); + result = dns_name_fromtext(name, &source, dns_rootname, 0, &target); if (result != ISC_R_SUCCESS) { printf("dns_name_fromtext(%s) failed: %s\n", diff --git a/bin/tests/sig0_test.c b/bin/tests/sig0_test.c index f36bbee02f..07654ed9cc 100644 --- a/bin/tests/sig0_test.c +++ b/bin/tests/sig0_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sig0_test.c,v 1.17 2008/07/22 23:47:04 tbox Exp $ */ +/* $Id: sig0_test.c,v 1.18 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -157,8 +157,7 @@ buildquery(void) { isc_buffer_add(&namesrc, strlen(nametext)); isc_buffer_init(&namedst, namedata, sizeof(namedata)); dns_name_init(qname, NULL); - result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE, - &namedst); + result = dns_name_fromtext(qname, &namesrc, dns_rootname, 0, &namedst); CHECK("dns_name_fromtext", result); ISC_LIST_APPEND(qname->list, question, link); dns_message_addname(query, qname, DNS_SECTION_QUESTION); @@ -264,7 +263,7 @@ main(int argc, char *argv[]) { name = dns_fixedname_name(&fname); isc_buffer_init(&b, "child.example.", strlen("child.example.")); isc_buffer_add(&b, strlen("child.example.")); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); key = NULL; diff --git a/bin/tests/sockaddr/Makefile.in b/bin/tests/sockaddr/Makefile.in index cdb3626e09..83b76f1175 100644 --- a/bin/tests/sockaddr/Makefile.in +++ b/bin/tests/sockaddr/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.23 2009/02/06 23:47:42 tbox Exp $ +# $Id: Makefile.in,v 1.24 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/system/lwresd/Makefile.in b/bin/tests/system/lwresd/Makefile.in index 807349dd32..85ec286574 100644 --- a/bin/tests/system/lwresd/Makefile.in +++ b/bin/tests/system/lwresd/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.19 2007/06/19 23:47:03 tbox Exp $ +# $Id: Makefile.in,v 1.20 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${LWRES_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = LWRESLIBS = ../../../../lib/lwres/liblwres.@A@ diff --git a/bin/tests/system/tkey/Makefile.in b/bin/tests/system/tkey/Makefile.in index 684fb1a610..1157c8d464 100644 --- a/bin/tests/system/tkey/Makefile.in +++ b/bin/tests/system/tkey/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.11 2007/06/19 23:47:06 tbox Exp $ +# $Id: Makefile.in,v 1.12 2009/09/01 00:22:25 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index cbb27d3119..23e6d42476 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keycreate.c,v 1.17 2009/07/19 23:47:55 tbox Exp $ */ +/* $Id: keycreate.c,v 1.18 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -153,14 +153,14 @@ sendquery(isc_task_t *task, isc_event_t *event) { isc_buffer_init(&namestr, "tkeytest.", 9); isc_buffer_add(&namestr, 9); result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr, - NULL, ISC_FALSE, NULL); + NULL, 0, NULL); CHECK("dns_name_fromtext", result); dns_fixedname_init(&ownername); isc_buffer_init(&namestr, ownername_str, strlen(ownername_str)); isc_buffer_add(&namestr, strlen(ownername_str)); result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr, - NULL, ISC_FALSE, NULL); + NULL, 0, NULL); CHECK("dns_name_fromtext", result); isc_buffer_init(&keybuf, keydata, 9); diff --git a/bin/tests/tasks/Makefile.in b/bin/tests/tasks/Makefile.in index 8f6e236d63..8806b6a808 100644 --- a/bin/tests/tasks/Makefile.in +++ b/bin/tests/tasks/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2009/02/06 23:47:42 tbox Exp $ +# $Id: Makefile.in,v 1.33 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/timers/Makefile.in b/bin/tests/timers/Makefile.in index 19c083d65e..7924067796 100644 --- a/bin/tests/timers/Makefile.in +++ b/bin/tests/timers/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.30 2009/02/06 23:47:42 tbox Exp $ +# $Id: Makefile.in,v 1.31 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@ diff --git a/bin/tests/zone_test.c b/bin/tests/zone_test.c index 7983bbaa8a..9274e41dc2 100644 --- a/bin/tests/zone_test.c +++ b/bin/tests/zone_test.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone_test.c,v 1.33 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: zone_test.c,v 1.34 2009/09/01 00:22:25 jinmei Exp $ */ #include @@ -104,7 +104,7 @@ setup(const char *zonename, const char *filename, const char *classname) { isc_buffer_add(&buffer, strlen(zonename)); dns_fixedname_init(&fixorigin); result = dns_name_fromtext(dns_fixedname_name(&fixorigin), - &buffer, dns_rootname, ISC_FALSE, NULL); + &buffer, dns_rootname, 0, NULL); ERRRET(result, "dns_name_fromtext"); origin = dns_fixedname_name(&fixorigin); @@ -206,7 +206,7 @@ query(void) { isc_buffer_init(&buffer, buf, strlen(buf)); isc_buffer_add(&buffer, strlen(buf)); result = dns_name_fromtext(dns_fixedname_name(&name), - &buffer, dns_rootname, ISC_FALSE, NULL); + &buffer, dns_rootname, 0, NULL); ERRCONT(result, "dns_name_fromtext"); result = dns_db_find(db, dns_fixedname_name(&name), diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in index e244fde428..90a7b9eac9 100644 --- a/bin/tools/Makefile.in +++ b/bin/tools/Makefile.in @@ -12,7 +12,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.7 2009/07/21 02:41:01 marka Exp $ +# $Id: Makefile.in,v 1.8 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ ${LWRES_INCLUDES} ${OMAPI_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ diff --git a/config.h.in b/config.h.in index 99595db675..e4cdc9b9df 100644 --- a/config.h.in +++ b/config.h.in @@ -16,7 +16,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h.in,v 1.117 2009/08/13 01:51:19 marka Exp $ */ +/* $Id: config.h.in,v 1.118 2009/09/01 00:22:24 jinmei Exp $ */ /*! \file */ @@ -292,6 +292,12 @@ int sigwait(const unsigned int *set, int *sig); /* Defined if extern char *optarg is not declared. */ #undef NEED_OPTARG +/* Define to the buffer length type used by getnameinfo(3). */ +#undef IRS_GETNAMEINFO_BUFLEN_T + +/* Define to the flags type used by getnameinfo(3). */ +#undef IRS_GETNAMEINFO_FLAGS_T + /* Define if connect does not honour the permission on the UNIX domain socket. */ #undef NEED_SECURE_DIRECTORY diff --git a/configure.in b/configure.in index 94f1c6a93a..7f5bd3c135 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.473 $) +AC_REVISION($Revision: 1.474 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.59) @@ -62,7 +62,6 @@ It is available from http://www.isc.org as a separate download.]) ;; esac - # # Make very sure that these are the first files processed by # config.status, since we use the processed output as the input for @@ -1323,6 +1322,54 @@ AC_SUBST(LIBTOOL_MODE_LINK) AC_SUBST(LIBTOOL_ALLOW_UNDEFINED) AC_SUBST(LIBTOOL_IN_MAIN) +# +# build exportable DNS library? +# +AC_ARG_ENABLE(exportlib, + [ --enable-exportlib build exportable library (GNU make required) + [[default=no]]]) +case "$enable_exportlib" in + yes) + gmake= + for x in gmake gnumake make; do + if $x --version 2>/dev/null | grep GNU > /dev/null; then + gmake=$x + break; + fi + done + if test -z "$gmake"; then + AC_MSG_ERROR([exportlib requires GNU make. Install it or disable the feature.]) + fi + LIBEXPORT=lib/export + AC_SUBST(LIBEXPORT) + BIND9_CO_RULE="%.$O: \${srcdir}/%.c" + ;; + no|*) + BIND9_CO_RULE=".c.$O:" + ;; +esac +AC_SUBST(BIND9_CO_RULE) + +AC_ARG_WITH(export-libdir, + [ --with-export-libdir[=PATH] + installation directory for the export library + [[EPREFIX/lib/bind9]]], + export_libdir="$withval",) +if test -z "$export_libdir"; then + export_libdir="\${exec_prefix}/lib/bind9/" +fi +AC_SUBST(export_libdir) + +AC_ARG_WITH(export-installdir, + [ --with-export-installdir[=PATH] + installation directory for the header files of the + export library [[PREFIX/include/bind9]]], + export_installdir="$withval",) +if test -z "$export_includedir"; then + export_includedir="\${prefix}/include/bind9/" +fi +AC_SUBST(export_includedir) + # # Here begins a very long section to determine the system's networking # capabilities. The order of the tests is significant. @@ -1707,10 +1754,13 @@ AC_TRY_COMPILE([ [struct addrinfo a; return (0);], [AC_MSG_RESULT(yes) ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO" + ISC_IRS_NEEDADDRINFO="#undef ISC_IRS_NEEDADDRINFO" AC_DEFINE(HAVE_ADDRINFO)], [AC_MSG_RESULT(no) - ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1"]) + ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1" + ISC_IRS_NEEDADDRINFO="#define ISC_IRS_NEEDADDRINFO 1"]) AC_SUBST(ISC_LWRES_NEEDADDRINFO) +AC_SUBST(ISC_IRS_NEEDADDRINFO) # # Check for rrsetinfo @@ -1797,6 +1847,35 @@ AC_TRY_COMPILE([ ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1"]) AC_SUBST(ISC_LWRES_NEEDHERRNO) +# +# Sadly, the definitions of system-supplied getnameinfo(3) vary. Try to catch +# known variations here: +# +AC_MSG_CHECKING(for getnameinfo prototype definitions) +AC_TRY_COMPILE([ +#include +#include +#include +int getnameinfo(const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, unsigned int);], +[ return (0);], + [AC_MSG_RESULT(socklen_t for buflen; u_int for flags) + AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t) + AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, unsigned int)], +[AC_TRY_COMPILE([ +#include +#include +#include +int getnameinfo(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int);], +[ return (0);], + [AC_MSG_RESULT(size_t for buflen; int for flags) + AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, size_t) + AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)], +[AC_MSG_RESULT(not match any subspecies; assume standard definition) +AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t) +AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)])]) + AC_CHECK_FUNC(getipnodebyname, [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"], [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"]) @@ -1811,6 +1890,7 @@ AC_CHECK_FUNC(gai_strerror, AC_DEFINE(HAVE_GAISTRERROR)) AC_SUBST(ISC_LWRES_GETIPNODEPROTO) AC_SUBST(ISC_LWRES_GETADDRINFOPROTO) AC_SUBST(ISC_LWRES_GETNAMEINFOPROTO) +AC_SUBST(ISC_IRS_GETNAMEINFOSOCKLEN) AC_ARG_ENABLE(getifaddrs, [ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no]].], @@ -2144,6 +2224,8 @@ AC_SUBST(ISC_PLATFORM_USEDECLSPEC) ISC_PLATFORM_USEDECLSPEC="#undef ISC_PLATFORM_USEDECLSPEC" AC_SUBST(LWRES_PLATFORM_USEDECLSPEC) LWRES_PLATFORM_USEDECLSPEC="#undef LWRES_PLATFORM_USEDECLSPEC" +AC_SUBST(IRS_PLATFORM_USEDECLSPEC) +IRS_PLATFORM_USEDECLSPEC="#undef IRS_PLATFORM_USEDECLSPEC" # # Random remaining OS-specific issues involving compiler warnings. @@ -2752,6 +2834,9 @@ LIBBIND9_API=$srcdir/lib/bind9/api AC_SUBST_FILE(LIBLWRES_API) LIBLWRES_API=$srcdir/lib/lwres/api +AC_SUBST_FILE(LIBIRS_API) +LIBIRS_API=$srcdir/lib/irs/api + # # Configure any DLZ drivers. # @@ -2941,10 +3026,38 @@ AC_CONFIG_FILES([ lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile + lib/irs/Makefile + lib/irs/include/Makefile + lib/irs/include/irs/Makefile + lib/irs/include/irs/netdb.h + lib/irs/include/irs/platform.h lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile + lib/export/Makefile + lib/export/isc/Makefile + lib/export/isc/include/Makefile + lib/export/isc/include/isc/Makefile + lib/export/isc/unix/Makefile + lib/export/isc/unix/include/Makefile + lib/export/isc/unix/include/isc/Makefile + lib/export/isc/nls/Makefile + lib/export/isc/$thread_dir/Makefile + lib/export/isc/$thread_dir/include/Makefile + lib/export/isc/$thread_dir/include/isc/Makefile + lib/export/dns/Makefile + lib/export/dns/include/Makefile + lib/export/dns/include/dns/Makefile + lib/export/dns/include/dst/Makefile + lib/export/irs/Makefile + lib/export/irs/include/Makefile + lib/export/irs/include/irs/Makefile + lib/export/isccfg/Makefile + lib/export/isccfg/include/Makefile + lib/export/isccfg/include/isccfg/Makefile + lib/export/samples/Makefile + lib/export/samples/Makefile-postinstall lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile diff --git a/contrib/dbus/dbus_mgr.c b/contrib/dbus/dbus_mgr.c index b744790cfa..427aff86b1 100644 --- a/contrib/dbus/dbus_mgr.c +++ b/contrib/dbus/dbus_mgr.c @@ -914,7 +914,7 @@ dbus_mgr_get_name_list dnsName = dns_fixedname_name(fixedname); result= dns_name_fromtext - ( dnsName, &buffer, ( *(endp-1) != '.') ? dns_rootname : NULL, ISC_FALSE, NULL + ( dnsName, &buffer, ( *(endp-1) != '.') ? dns_rootname : NULL, 0, NULL ); if( result != ISC_R_SUCCESS ) @@ -1566,7 +1566,7 @@ dbus_mgr_handle_get_forwarders dnsName = dns_fixedname_name(&fixedname); result = dns_name_fromtext - ( dnsName, &buffer, dns_rootname, ISC_FALSE, NULL + ( dnsName, &buffer, dns_rootname, 0, NULL ); if( result != ISC_R_SUCCESS ) @@ -1740,7 +1740,7 @@ dns_name_t *dbus_mgr_if_reverse_ip_name dns_name = dns_fixedname_name(fixedname); result= dns_name_fromtext - ( dns_name, &buffer, dns_rootname, ISC_FALSE, NULL + ( dns_name, &buffer, dns_rootname, 0, NULL ); ISC_LINK_INIT(dns_name, link); diff --git a/contrib/dlz/bin/dlzbdb/Makefile.in b/contrib/dlz/bin/dlzbdb/Makefile.in index a31c503b42..f0e20c294c 100644 --- a/contrib/dlz/bin/dlzbdb/Makefile.in +++ b/contrib/dlz/bin/dlzbdb/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.3 2007/09/07 06:53:03 marka Exp $ +# $Id: Makefile.in,v 1.4 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,8 +27,8 @@ DLZINCLUDES = @DLZ_DRIVER_INCLUDES@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \ ${ISC_INCLUDES} ${DLZINCLUDES} - -CDEFINES = @USE_DLZ@ + +CDEFINES = -DBIND9 @USE_DLZ@ CWARNINGS = DLZLIBS = @DLZ_DRIVER_LIBS@ diff --git a/contrib/sdb/bdb/zone2bdb.c b/contrib/sdb/bdb/zone2bdb.c index 36326afe53..e711853175 100644 --- a/contrib/sdb/bdb/zone2bdb.c +++ b/contrib/sdb/bdb/zone2bdb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone2bdb.c,v 1.2 2008/09/24 02:46:21 marka Exp $ */ +/* $Id: zone2bdb.c,v 1.3 2009/09/01 00:22:26 jinmei Exp $ */ #include @@ -137,7 +137,7 @@ main(int argc, char *argv[]) dns_fixedname_init(&origin); REQUIRE(dns_name_fromtext(dns_fixedname_name(&origin), &b, dns_rootname, - ISC_FALSE, NULL) == ISC_R_SUCCESS); + 0, NULL) == ISC_R_SUCCESS); REQUIRE(dns_db_create(mctx, "rbt", dns_fixedname_name(&origin), dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &db) == ISC_R_SUCCESS); diff --git a/contrib/sdb/ldap/zone2ldap.c b/contrib/sdb/ldap/zone2ldap.c index c2820fdc2b..e06f4f9578 100644 --- a/contrib/sdb/ldap/zone2ldap.c +++ b/contrib/sdb/ldap/zone2ldap.c @@ -201,7 +201,7 @@ main (int *argc, char **argv) isc_buffer_add (&buff, strlen (argzone)); dns_fixedname_init (&fixedzone); zone = dns_fixedname_name (&fixedzone); - result = dns_name_fromtext (zone, &buff, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext (zone, &buff, dns_rootname, 0, NULL); isc_result_check (result, "dns_name_fromtext"); result = dns_db_create (mctx, "rbt", zone, dns_dbtype_zone, diff --git a/contrib/sdb/pgsql/zonetodb.c b/contrib/sdb/pgsql/zonetodb.c index 61ec264433..f141aaee65 100644 --- a/contrib/sdb/pgsql/zonetodb.c +++ b/contrib/sdb/pgsql/zonetodb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zonetodb.c,v 1.21 2008/11/27 06:14:22 marka Exp $ */ +/* $Id: zonetodb.c,v 1.22 2009/09/01 00:22:26 jinmei Exp $ */ #include #include @@ -174,7 +174,7 @@ main(int argc, char **argv) { isc_buffer_add(&b, strlen(porigin)); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); - result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(origin, &b, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); db = NULL; diff --git a/contrib/sdb/sqlite/zone2sqlite.c b/contrib/sdb/sqlite/zone2sqlite.c index abaf52bf02..2ba63cc58a 100644 --- a/contrib/sdb/sqlite/zone2sqlite.c +++ b/contrib/sdb/sqlite/zone2sqlite.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone2sqlite.c,v 1.2 2008/09/24 02:46:21 marka Exp $ */ +/* $Id: zone2sqlite.c,v 1.3 2009/09/01 00:22:26 jinmei Exp $ */ #include #include @@ -181,7 +181,7 @@ main(int argc, char *argv[]) isc_buffer_add(&b, strlen(porigin)); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); - result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(origin, &b, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); db = NULL; diff --git a/lib/bind9/Makefile.in b/lib/bind9/Makefile.in index 7c1e5b0b9d..f03a8652e7 100644 --- a/lib/bind9/Makefile.in +++ b/lib/bind9/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.11 2007/06/19 23:47:16 tbox Exp $ +# $Id: Makefile.in,v 1.12 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -28,7 +28,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I. ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \ ${ISCCFG_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../lib/isc/libisc.@A@ diff --git a/lib/bind9/check.c b/lib/bind9/check.c index a44831bc51..423e1f8db6 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.106 2009/08/23 11:44:44 fdupont Exp $ */ +/* $Id: check.c,v 1.107 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -100,7 +100,7 @@ check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "rrset-order: invalid name '%s'", str); @@ -199,7 +199,7 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) { dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); tresult = dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad name '%s'", str); @@ -262,7 +262,7 @@ disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) { str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -349,7 +349,7 @@ mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx, str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -617,7 +617,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", @@ -680,7 +680,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, dlv, strlen(dlv)); isc_buffer_add(&b, strlen(dlv)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", dlv); @@ -715,7 +715,8 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_add(&b, strlen(dlv)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + DNS_NAME_DOWNCASE, + NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", @@ -771,7 +772,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "empty-server: invalid name '%s'", str); @@ -786,7 +787,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "empty-contact: invalid name '%s'", str); @@ -805,7 +806,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "disable-empty-zone: invalid name '%s'", @@ -990,7 +991,7 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(identity, logctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); @@ -1004,8 +1005,7 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), - &b, dns_rootname, - ISC_FALSE, NULL); + &b, dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(dname, logctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); @@ -1198,7 +1198,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, isc_buffer_init(&b, zname, strlen(zname)); isc_buffer_add(&b, strlen(zname)); tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, "zone '%s': is not a valid name", zname); @@ -1511,7 +1511,7 @@ check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab, isc_buffer_init(&b, keyid, strlen(keyid)); isc_buffer_add(&b, strlen(keyid)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(key, logctx, ISC_LOG_ERROR, "key '%s': bad key name", keyid); @@ -1681,7 +1681,7 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, isc_buffer_add(&b, strlen(keyval)); keyname = dns_fixedname_name(&fname); tresult = dns_name_fromtext(keyname, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(keys, logctx, ISC_LOG_ERROR, "bad key name '%s'", keyval); diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 170031fb1c..eef55f1e27 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.165 2009/07/01 23:47:36 tbox Exp $ +# $Id: Makefile.in,v 1.166 2009/09/01 00:22:26 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -34,7 +34,7 @@ USE_ISC_SPNEGO = @USE_ISC_SPNEGO@ CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \ ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ -CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_PKCS11@ @USE_GSSAPI@ \ +CDEFINES = -DBIND9 -DUSE_MD5 @USE_OPENSSL@ @USE_PKCS11@ @USE_GSSAPI@ \ ${USE_ISC_SPNEGO} CWARNINGS = @@ -68,7 +68,7 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ resolver.@O@ result.@O@ rootns.@O@ rriterator.@O@ sdb.@O@ \ sdlz.@O@ soa.@O@ ssu.@O@ \ stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \ - tsig.@O@ ttl.@O@ validator.@O@ \ + tsec.@O@ tsig.@O@ ttl.@O@ validator.@O@ \ version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@ OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} @@ -94,7 +94,7 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \ resolver.c result.c rootns.c rriterator.c sdb.c sdlz.c \ soa.c ssu.c \ stats.c tcpmsg.c time.c timer.c tkey.c \ - tsig.c ttl.c validator.c \ + tsec.c tsig.c ttl.c validator.c \ version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS} SRCS = ${DSTSRCS} ${DNSSRCS} diff --git a/lib/dns/byaddr.c b/lib/dns/byaddr.c index 234d6b2cd0..068c9985ea 100644 --- a/lib/dns/byaddr.c +++ b/lib/dns/byaddr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: byaddr.c,v 1.39 2007/06/19 23:47:16 tbox Exp $ */ +/* $Id: byaddr.c,v 1.40 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -43,25 +43,6 @@ * XXXRTH We could use a static event... */ -struct dns_byaddr { - /* Unlocked. */ - unsigned int magic; - isc_mem_t * mctx; - isc_mutex_t lock; - dns_fixedname_t name; - /* Locked by lock. */ - unsigned int options; - dns_lookup_t * lookup; - isc_task_t * task; - dns_byaddrevent_t * event; - isc_boolean_t canceled; -}; - -#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd') -#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC) - -#define MAX_RESTARTS 16 - static char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' @@ -125,10 +106,29 @@ dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options, len = (unsigned int)strlen(textname); isc_buffer_init(&buffer, textname, len); isc_buffer_add(&buffer, len); - return (dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + return (dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL)); } +#ifdef BIND9 +struct dns_byaddr { + /* Unlocked. */ + unsigned int magic; + isc_mem_t * mctx; + isc_mutex_t lock; + dns_fixedname_t name; + /* Locked by lock. */ + unsigned int options; + dns_lookup_t * lookup; + isc_task_t * task; + dns_byaddrevent_t * event; + isc_boolean_t canceled; +}; + +#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd') +#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC) + +#define MAX_RESTARTS 16 + static inline isc_result_t copy_ptr_targets(dns_byaddr_t *byaddr, dns_rdataset_t *rdataset) { isc_result_t result; @@ -314,3 +314,4 @@ dns_byaddr_destroy(dns_byaddr_t **byaddrp) { *byaddrp = NULL; } +#endif /* BIND9 */ diff --git a/lib/dns/cache.c b/lib/dns/cache.c index 5909879923..9752836f96 100644 --- a/lib/dns/cache.c +++ b/lib/dns/cache.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cache.c,v 1.84 2009/05/06 22:53:54 jinmei Exp $ */ +/* $Id: cache.c,v 1.85 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -450,6 +450,7 @@ dns_cache_setfilename(dns_cache_t *cache, const char *filename) { return (ISC_R_SUCCESS); } +#ifdef BIND9 isc_result_t dns_cache_load(dns_cache_t *cache) { isc_result_t result; @@ -465,6 +466,7 @@ dns_cache_load(dns_cache_t *cache) { return (result); } +#endif /* BIND9 */ isc_result_t dns_cache_dump(dns_cache_t *cache) { @@ -475,10 +477,14 @@ dns_cache_dump(dns_cache_t *cache) { if (cache->filename == NULL) return (ISC_R_SUCCESS); +#ifdef BIND9 LOCK(&cache->filelock); result = dns_master_dump(cache->mctx, cache->db, NULL, &dns_master_style_cache, cache->filename); UNLOCK(&cache->filelock); +#else + return (ISC_R_NOTIMPLEMENTED); +#endif return (result); } diff --git a/lib/dns/client.c b/lib/dns/client.c new file mode 100644 index 0000000000..dcb8817e2b --- /dev/null +++ b/lib/dns/client.c @@ -0,0 +1,2994 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: client.c,v 1.2 2009/09/01 00:22:26 jinmei Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c') +#define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC) + +#define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x') +#define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC) + +#define REQCTX_MAGIC ISC_MAGIC('R', 'q', 'c', 'x') +#define REQCTX_VALID(c) ISC_MAGIC_VALID(c, REQCTX_MAGIC) + +#define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x') +#define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC) + +#define MAX_RESTARTS 16 + +/*% + * DNS client object + */ +struct dns_client { + /* Unlocked */ + unsigned int magic; + unsigned int attributes; + isc_mutex_t lock; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_taskmgr_t *taskmgr; + isc_task_t *task; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; + dns_dispatchmgr_t *dispatchmgr; + dns_dispatch_t *dispatchv4; + dns_dispatch_t *dispatchv6; + + unsigned int update_timeout; + unsigned int update_udptimeout; + unsigned int update_udpretries; + unsigned int find_timeout; + unsigned int find_udpretries; + + /* Locked */ + unsigned int references; + dns_viewlist_t viewlist; + ISC_LIST(struct resctx) resctxs; + ISC_LIST(struct reqctx) reqctxs; + ISC_LIST(struct updatectx) updatectxs; +}; + +/*% + * Timeout/retry constants for dynamic update borrowed from nsupdate + */ +#define DEF_UPDATE_TIMEOUT 300 +#define MIN_UPDATE_TIMEOUT 30 +#define DEF_UPDATE_UDPTIMEOUT 3 +#define DEF_UPDATE_UDPRETRIES 3 + +#define DEF_FIND_TIMEOUT 5 +#define DEF_FIND_UDPRETRIES 3 + +#define DNS_CLIENTATTR_OWNCTX 0x01 + +#define DNS_CLIENTVIEW_NAME "dnsclient" + +/*% + * Internal state for a single name resolution procedure + */ +typedef struct resctx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + isc_boolean_t want_dnssec; + + /* Locked */ + ISC_LINK(struct resctx) link; + isc_task_t *task; + dns_view_t *view; + unsigned int restarts; + dns_fixedname_t name; + dns_rdatatype_t type; + dns_fetch_t *fetch; + dns_namelist_t namelist; + isc_result_t result; + dns_clientresevent_t *event; + isc_boolean_t canceled; + dns_rdataset_t *rdataset; + dns_rdataset_t *sigrdataset; +} resctx_t; + +/*% + * Argument of an internal event for synchronous name resolution. + */ +typedef struct resarg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + isc_result_t vresult; + dns_namelist_t *namelist; + dns_clientrestrans_t *trans; + isc_boolean_t canceled; +} resarg_t; + +/*% + * Internal state for a single DNS request + */ +typedef struct reqctx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + unsigned int parseoptions; + + /* Locked */ + ISC_LINK(struct reqctx) link; + isc_boolean_t canceled; + dns_tsigkey_t *tsigkey; + dns_request_t *request; + dns_clientreqevent_t *event; +} reqctx_t; + +/*% + * Argument of an internal event for synchronous DNS request. + */ +typedef struct reqarg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + dns_clientreqtrans_t *trans; + isc_boolean_t canceled; +} reqarg_t; + +/*% + * Argument of an internal event for synchronous name resolution. + */ +typedef struct updatearg { + /* Unlocked */ + isc_appctx_t *actx; + dns_client_t *client; + isc_mutex_t lock; + + /* Locked */ + isc_result_t result; + dns_clientupdatetrans_t *trans; + isc_boolean_t canceled; +} updatearg_t; + +/*% + * Internal state for a single dynamic update procedure + */ +typedef struct updatectx { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_client_t *client; + + /* Locked */ + dns_request_t *updatereq; + dns_request_t *soareq; + dns_clientrestrans_t *restrans; + dns_clientrestrans_t *restrans2; + isc_boolean_t canceled; + + /* Task Locked */ + ISC_LINK(struct updatectx) link; + dns_clientupdatestate_t state; + dns_rdataclass_t rdclass; + dns_view_t *view; + dns_message_t *updatemsg; + dns_message_t *soaquery; + dns_clientupdateevent_t *event; + dns_tsigkey_t *tsigkey; + dst_key_t *sig0key; + dns_name_t *firstname; + dns_name_t soaqname; + dns_fixedname_t zonefname; + dns_name_t *zonename; + isc_sockaddrlist_t servers; + unsigned int nservers; + isc_sockaddr_t *currentserver; + struct updatectx *bp4; + struct updatectx *bp6; +} updatectx_t; + +static isc_result_t request_soa(updatectx_t *uctx); +static void client_resfind(resctx_t *rctx, dns_fetchevent_t *event); +static isc_result_t send_update(updatectx_t *uctx); + +static isc_result_t +getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, + isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, + isc_boolean_t is_shared, dns_dispatch_t **dispp) +{ + unsigned int attrs, attrmask; + isc_sockaddr_t sa; + dns_dispatch_t *disp; + unsigned buffersize, maxbuffers, maxrequests, buckets, increment; + isc_result_t result; + + attrs = 0; + attrs |= DNS_DISPATCHATTR_UDP; + switch (family) { + case AF_INET: + attrs |= DNS_DISPATCHATTR_IPV4; + break; + case AF_INET6: + attrs |= DNS_DISPATCHATTR_IPV6; + break; + default: + INSIST(0); + } + attrmask = 0; + attrmask |= DNS_DISPATCHATTR_UDP; + attrmask |= DNS_DISPATCHATTR_TCP; + attrmask |= DNS_DISPATCHATTR_IPV4; + attrmask |= DNS_DISPATCHATTR_IPV6; + + isc_sockaddr_anyofpf(&sa, family); + + buffersize = 4096; + maxbuffers = is_shared ? 1000 : 8; + maxrequests = 32768; + buckets = is_shared ? 16411 : 3; + increment = is_shared ? 16433 : 5; + + disp = NULL; + result = dns_dispatch_getudp(dispatchmgr, socketmgr, + taskmgr, &sa, + buffersize, maxbuffers, maxrequests, + buckets, increment, + attrs, attrmask, &disp); + if (result == ISC_R_SUCCESS) + *dispp = disp; + + return (result); +} + +static isc_result_t +dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, + unsigned int options, isc_taskmgr_t *taskmgr, + unsigned int ntasks, isc_socketmgr_t *socketmgr, + isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr, + dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, + dns_view_t **viewp) +{ + isc_result_t result; + dns_view_t *view = NULL; + const char *dbtype; + + result = dns_view_create(mctx, rdclass, DNS_CLIENTVIEW_NAME, &view); + if (result != ISC_R_SUCCESS) + return (ISC_R_NOMEMORY); + + result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr, + timermgr, 0, dispatchmgr, + dispatchv4, dispatchv6); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + /* + * Set cache DB. + * XXX: it may be better if specific DB implementations can be + * specified via some configuration knob. + */ + if ((options & DNS_CLIENTCREATEOPT_USECACHE) != 0) + dbtype = "rbt"; + else + dbtype = "ecdb"; + result = dns_db_create(mctx, dbtype, dns_rootname, dns_dbtype_cache, + rdclass, 0, NULL, &view->cachedb); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + return (result); + } + + *viewp = view; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_client_create(dns_client_t **clientp, unsigned int options) { + isc_result_t result; + isc_mem_t *mctx = NULL; + isc_appctx_t *actx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_appctx_create(mctx, &actx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_app_ctxstart(actx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_socketmgr_createinctx(mctx, actx, &socketmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = isc_timermgr_createinctx(mctx, actx, &timermgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, + options, clientp); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (*clientp)->attributes |= DNS_CLIENTATTR_OWNCTX; + + /* client has its own reference to mctx, so we can detach it here */ + isc_mem_detach(&mctx); + + return (ISC_R_SUCCESS); + + cleanup: + if (timermgr != NULL) + isc_timermgr_destroy(&timermgr); + if (socketmgr != NULL) + isc_socketmgr_destroy(&socketmgr); + if (taskmgr != NULL) + isc_taskmgr_destroy(&taskmgr); + if (actx != NULL) + isc_appctx_destroy(&actx); + isc_mem_detach(&mctx); + + return (result); +} + +isc_result_t +dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, + isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, + unsigned int options, dns_client_t **clientp) +{ + dns_client_t *client; + isc_result_t result; + dns_dispatchmgr_t *dispatchmgr = NULL; + dns_dispatch_t *dispatchv4 = NULL; + dns_dispatch_t *dispatchv6 = NULL; + dns_view_t *view = NULL; + + REQUIRE(mctx != NULL); + REQUIRE(taskmgr != NULL); + REQUIRE(timermgr != NULL); + REQUIRE(socketmgr != NULL); + REQUIRE(clientp != NULL && *clientp == NULL); + + client = isc_mem_get(mctx, sizeof(*client)); + if (client == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&client->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, client, sizeof(*client)); + return (result); + } + + client->actx = actx; + client->taskmgr = taskmgr; + client->socketmgr = socketmgr; + client->timermgr = timermgr; + + client->task = NULL; + result = isc_task_create(client->taskmgr, 0, &client->task); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->dispatchmgr = dispatchmgr; + + /* TODO: whether to use dispatch v4 or v6 should be configurable */ + result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, &dispatchv4); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->dispatchv4 = dispatchv4; + result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, + taskmgr, ISC_TRUE, &dispatchv6); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->dispatchv6 = dispatchv6; + + /* Create the default view for class IN */ + result = dns_client_createview(mctx, dns_rdataclass_in, options, + taskmgr, 31, socketmgr, timermgr, + dispatchmgr, dispatchv4, dispatchv6, + &view); + if (result != ISC_R_SUCCESS) + goto cleanup; + ISC_LIST_INIT(client->viewlist); + ISC_LIST_APPEND(client->viewlist, view, link); + + dns_view_freeze(view); /* too early? */ + + ISC_LIST_INIT(client->resctxs); + ISC_LIST_INIT(client->reqctxs); + ISC_LIST_INIT(client->updatectxs); + + client->mctx = NULL; + isc_mem_attach(mctx, &client->mctx); + + client->update_timeout = DEF_UPDATE_TIMEOUT; + client->update_udptimeout = DEF_UPDATE_UDPTIMEOUT; + client->update_udpretries = DEF_UPDATE_UDPRETRIES; + client->find_timeout = DEF_FIND_TIMEOUT; + client->find_udpretries = DEF_FIND_UDPRETRIES; + + client->references = 1; + client->magic = DNS_CLIENT_MAGIC; + + *clientp = client; + + return (ISC_R_SUCCESS); + + cleanup: + if (dispatchv4 != NULL) + dns_dispatch_detach(&dispatchv4); + if (dispatchv6 != NULL) + dns_dispatch_detach(&dispatchv6); + if (dispatchmgr != NULL) + dns_dispatchmgr_destroy(&dispatchmgr); + if (client->task != NULL) + isc_task_detach(&client->task); + isc_mem_put(mctx, client, sizeof(*client)); + + return (result); +} + +static void +destroyclient(dns_client_t **clientp) { + dns_client_t *client = *clientp; + dns_view_t *view; + + while ((view = ISC_LIST_HEAD(client->viewlist)) != NULL) { + ISC_LIST_UNLINK(client->viewlist, view, link); + dns_view_detach(&view); + } + + if (client->dispatchv4 != NULL) + dns_dispatch_detach(&client->dispatchv4); + if (client->dispatchv6 != NULL) + dns_dispatch_detach(&client->dispatchv6); + + dns_dispatchmgr_destroy(&client->dispatchmgr); + + isc_task_detach(&client->task); + + /* + * If the client has created its own running environments, + * destroy them. + */ + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) != 0) { + isc_taskmgr_destroy(&client->taskmgr); + isc_timermgr_destroy(&client->timermgr); + isc_socketmgr_destroy(&client->socketmgr); + + isc_app_ctxfinish(client->actx); + isc_appctx_destroy(&client->actx); + } + + DESTROYLOCK(&client->lock); + client->magic = 0; + + isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); + + *clientp = NULL; +} + +void +dns_client_destroy(dns_client_t **clientp) { + dns_client_t *client; + isc_boolean_t destroyok = ISC_FALSE; + + REQUIRE(clientp != NULL); + client = *clientp; + REQUIRE(DNS_CLIENT_VALID(client)); + + LOCK(&client->lock); + client->references--; + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) { + destroyok = ISC_TRUE; + } + UNLOCK(&client->lock); + + if (destroyok) + destroyclient(&client); + + *clientp = NULL; +} + +isc_result_t +dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace, isc_sockaddrlist_t *addrs) +{ + isc_result_t result; + dns_view_t *view = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(addrs != NULL); + + if (namespace == NULL) + namespace = dns_rootname; + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + if (result != ISC_R_SUCCESS) { + UNLOCK(&client->lock); + return (result); + } + UNLOCK(&client->lock); + + result = dns_fwdtable_add(view->fwdtable, namespace, addrs, + dns_fwdpolicy_only); + + dns_view_detach(&view); + + return (result); +} + +isc_result_t +dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace) +{ + isc_result_t result; + dns_view_t *view = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + + if (namespace == NULL) + namespace = dns_rootname; + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + if (result != ISC_R_SUCCESS) { + UNLOCK(&client->lock); + return (result); + } + UNLOCK(&client->lock); + + result = dns_fwdtable_delete(view->fwdtable, namespace); + + dns_view_detach(&view); + + return (result); +} + +static isc_result_t +getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset; + + REQUIRE(mctx != NULL); + REQUIRE(rdatasetp != NULL && *rdatasetp == NULL); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) + return (ISC_R_NOMEMORY); + + dns_rdataset_init(rdataset); + + *rdatasetp = rdataset; + + return (ISC_R_SUCCESS); +} + +static void +putrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset; + + REQUIRE(rdatasetp != NULL); + rdataset = *rdatasetp; + REQUIRE(rdataset != NULL); + + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + + isc_mem_put(mctx, rdataset, sizeof(*rdataset)); + + *rdatasetp = NULL; +} + +static void +fetch_done(isc_task_t *task, isc_event_t *event) { + resctx_t *rctx = event->ev_arg; + dns_fetchevent_t *fevent; + + REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); + REQUIRE(RCTX_VALID(rctx)); + REQUIRE(rctx->task == task); + fevent = (dns_fetchevent_t *)event; + + client_resfind(rctx, fevent); +} + +static inline isc_result_t +start_fetch(resctx_t *rctx) { + isc_result_t result; + + /* + * The caller must be holding the rctx's lock. + */ + + REQUIRE(rctx->fetch == NULL); + + result = dns_resolver_createfetch(rctx->view->resolver, + dns_fixedname_name(&rctx->name), + rctx->type, + NULL, NULL, NULL, 0, + rctx->task, fetch_done, rctx, + rctx->rdataset, + rctx->sigrdataset, + &rctx->fetch); + + return (result); +} + +static isc_result_t +view_find(resctx_t *rctx, dns_db_t **dbp, dns_dbnode_t **nodep, + dns_name_t *foundname) +{ + isc_result_t result; + dns_name_t *name = dns_fixedname_name(&rctx->name); + dns_rdatatype_t type; + + if (rctx->type == dns_rdatatype_rrsig) + type = dns_rdatatype_any; + else + type = rctx->type; + + result = dns_view_find(rctx->view, name, type, 0, 0, ISC_FALSE, + dbp, nodep, foundname, rctx->rdataset, + rctx->sigrdataset); + + return (result); +} + +static void +client_resfind(resctx_t *rctx, dns_fetchevent_t *event) { + isc_mem_t *mctx; + isc_result_t result, tresult; + isc_result_t vresult = ISC_R_SUCCESS; + isc_boolean_t want_restart; + isc_boolean_t send_event = ISC_FALSE; + dns_name_t *name, *prefix; + dns_fixedname_t foundname, fixed; + dns_rdataset_t *trdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned int nlabels; + int order; + dns_namereln_t namereln; + dns_rdata_cname_t cname; + dns_rdata_dname_t dname; + + REQUIRE(RCTX_VALID(rctx)); + + LOCK(&rctx->lock); + + mctx = rctx->view->mctx; + + result = ISC_R_SUCCESS; + name = dns_fixedname_name(&rctx->name); + + do { + dns_name_t *fname = NULL; + dns_name_t *ansname = NULL; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + + rctx->restarts++; + want_restart = ISC_FALSE; + + if (event == NULL && !rctx->canceled) { + dns_fixedname_init(&foundname); + fname = dns_fixedname_name(&foundname); + INSIST(!dns_rdataset_isassociated(rctx->rdataset)); + INSIST(rctx->sigrdataset == NULL || + !dns_rdataset_isassociated(rctx->sigrdataset)); + result = view_find(rctx, &db, &node, fname); + if (result == ISC_R_NOTFOUND) { + /* + * We don't know anything about the name. + * Launch a fetch. + */ + if (node != NULL) { + INSIST(db != NULL); + dns_db_detachnode(db, &node); + } + if (db != NULL) + dns_db_detach(&db); + result = start_fetch(rctx); + if (result != ISC_R_SUCCESS) { + putrdataset(mctx, &rctx->rdataset); + if (rctx->sigrdataset != NULL) + putrdataset(mctx, + &rctx->sigrdataset); + send_event = ISC_TRUE; + } + goto done; + } + } else { + INSIST(event->fetch == rctx->fetch); + dns_resolver_destroyfetch(&rctx->fetch); + db = event->db; + node = event->node; + result = event->result; + vresult = event->vresult; + fname = dns_fixedname_name(&event->foundname); + INSIST(event->rdataset == rctx->rdataset); + INSIST(event->sigrdataset == rctx->sigrdataset); + } + + /* + * If we've been canceled, forget about the result. + */ + if (rctx->canceled) + result = ISC_R_CANCELED; + else { + /* + * Otherwise, get some resource for copying the + * result. + */ + ansname = isc_mem_get(mctx, sizeof(*ansname)); + if (ansname == NULL) + tresult = ISC_R_NOMEMORY; + else { + dns_name_t *aname; + + aname = dns_fixedname_name(&rctx->name); + dns_name_init(ansname, NULL); + tresult = dns_name_dup(aname, mctx, ansname); + if (tresult != ISC_R_SUCCESS) + isc_mem_put(mctx, ansname, + sizeof(*ansname)); + } + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + + switch (result) { + case ISC_R_SUCCESS: + send_event = ISC_TRUE; + /* + * This case is handled in the main line below. + */ + break; + case DNS_R_CNAME: + /* + * Add the CNAME to the answer list. + */ + trdataset = rctx->rdataset; + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + + /* + * Copy the CNAME's target into the lookup's + * query name and start over. + */ + tresult = dns_rdataset_first(trdataset); + if (tresult != ISC_R_SUCCESS) + goto done; + dns_rdataset_current(trdataset, &rdata); + tresult = dns_rdata_tostruct(&rdata, &cname, NULL); + dns_rdata_reset(&rdata); + if (tresult != ISC_R_SUCCESS) + goto done; + tresult = dns_name_copy(&cname.cname, name, NULL); + dns_rdata_freestruct(&cname); + if (tresult == ISC_R_SUCCESS) + want_restart = ISC_TRUE; + else + result = tresult; + goto done; + case DNS_R_DNAME: + /* + * Add the DNAME to the answer list. + */ + trdataset = rctx->rdataset; + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + + namereln = dns_name_fullcompare(name, fname, &order, + &nlabels); + INSIST(namereln == dns_namereln_subdomain); + /* + * Get the target name of the DNAME. + */ + tresult = dns_rdataset_first(trdataset); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + dns_rdataset_current(trdataset, &rdata); + tresult = dns_rdata_tostruct(&rdata, &dname, NULL); + dns_rdata_reset(&rdata); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + /* + * Construct the new query name and start over. + */ + dns_fixedname_init(&fixed); + prefix = dns_fixedname_name(&fixed); + dns_name_split(name, nlabels, prefix, NULL); + tresult = dns_name_concatenate(prefix, &dname.dname, + name, NULL); + dns_rdata_freestruct(&dname); + if (tresult == ISC_R_SUCCESS) + want_restart = ISC_TRUE; + else + result = tresult; + goto done; + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NCACHENXRRSET: + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + rctx->rdataset = NULL; + /* What about sigrdataset? */ + if (rctx->sigrdataset != NULL) + putrdataset(mctx, &rctx->sigrdataset); + send_event = ISC_TRUE; + goto done; + default: + if (rctx->rdataset != NULL) + putrdataset(mctx, &rctx->rdataset); + if (rctx->sigrdataset != NULL) + putrdataset(mctx, &rctx->sigrdataset); + send_event = ISC_TRUE; + goto done; + } + + if (rctx->type == dns_rdatatype_any) { + int n = 0; + dns_rdatasetiter_t *rdsiter = NULL; + + tresult = dns_db_allrdatasets(db, node, NULL, 0, + &rdsiter); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto done; + } + + tresult = dns_rdatasetiter_first(rdsiter); + while (tresult == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, + rctx->rdataset); + if (rctx->rdataset->type != 0) { + ISC_LIST_APPEND(ansname->list, + rctx->rdataset, + link); + n++; + rctx->rdataset = NULL; + } else { + /* + * We're not interested in this + * rdataset. + */ + dns_rdataset_disassociate( + rctx->rdataset); + } + tresult = dns_rdatasetiter_next(rdsiter); + + if (tresult == ISC_R_SUCCESS && + rctx->rdataset == NULL) { + tresult = getrdataset(mctx, + &rctx->rdataset); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + break; + } + } + } + if (n == 0) { + /* + * We didn't match any rdatasets (which means + * something went wrong in this + * implementation). + */ + result = DNS_R_SERVFAIL; /* better code? */ + } else { + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + } + dns_rdatasetiter_destroy(&rdsiter); + if (tresult != ISC_R_NOMORE) + result = DNS_R_SERVFAIL; /* ditto */ + else + result = ISC_R_SUCCESS; + goto done; + } else { + /* + * This is the "normal" case -- an ordinary question + * to which we've got the answer. + */ + ISC_LIST_APPEND(ansname->list, rctx->rdataset, link); + rctx->rdataset = NULL; + if (rctx->sigrdataset != NULL) { + ISC_LIST_APPEND(ansname->list, + rctx->sigrdataset, link); + rctx->sigrdataset = NULL; + } + ISC_LIST_APPEND(rctx->namelist, ansname, link); + ansname = NULL; + } + + done: + /* + * Free temporary resources + */ + if (ansname != NULL) { + dns_rdataset_t *rdataset; + + while ((rdataset = ISC_LIST_HEAD(ansname->list)) + != NULL) { + ISC_LIST_UNLINK(ansname->list, rdataset, link); + putrdataset(mctx, &rdataset); + } + dns_name_free(ansname, mctx); + isc_mem_put(mctx, ansname, sizeof(*ansname)); + } + + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + + /* + * Limit the number of restarts. + */ + if (want_restart && rctx->restarts == MAX_RESTARTS) { + want_restart = ISC_FALSE; + result = ISC_R_QUOTA; + send_event = ISC_TRUE; + } + + /* + * Prepare further find with new resources + */ + if (want_restart) { + INSIST(rctx->rdataset == NULL && + rctx->sigrdataset == NULL); + + result = getrdataset(mctx, &rctx->rdataset); + if (result == ISC_R_SUCCESS && rctx->want_dnssec) { + result = getrdataset(mctx, &rctx->sigrdataset); + if (result != ISC_R_SUCCESS) { + putrdataset(mctx, &rctx->rdataset); + } + } + + if (result != ISC_R_SUCCESS) { + want_restart = ISC_FALSE; + send_event = ISC_TRUE; + } + } + } while (want_restart); + + if (send_event) { + isc_task_t *task; + + while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) { + ISC_LIST_UNLINK(rctx->namelist, name, link); + ISC_LIST_APPEND(rctx->event->answerlist, name, link); + } + + rctx->event->result = result; + rctx->event->vresult = vresult; + task = rctx->event->ev_sender; + rctx->event->ev_sender = rctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event)); + } + + UNLOCK(&rctx->lock); +} + +static void +resolve_done(isc_task_t *task, isc_event_t *event) { + resarg_t *resarg = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + + UNUSED(task); + + LOCK(&resarg->lock); + + resarg->result = rev->result; + resarg->vresult = rev->vresult; + while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) { + ISC_LIST_UNLINK(rev->answerlist, name, link); + ISC_LIST_APPEND(*resarg->namelist, name, link); + } + + dns_client_destroyrestrans(&resarg->trans); + isc_event_free(&event); + + if (!resarg->canceled) { + UNLOCK(&resarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(resarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&resarg->lock); + DESTROYLOCK(&resarg->lock); + isc_mem_put(resarg->client->mctx, resarg, sizeof(*resarg)); + } +} + +isc_result_t +dns_client_resolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, dns_namelist_t *namelist) +{ + isc_result_t result; + isc_appctx_t *actx; + resarg_t *resarg; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist)); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + resarg = isc_mem_get(client->mctx, sizeof(*resarg)); + if (resarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&resarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + return (result); + } + + resarg->actx = actx; + resarg->client = client; + resarg->result = DNS_R_SERVFAIL; + resarg->namelist = namelist; + resarg->trans = NULL; + resarg->canceled = ISC_FALSE; + result = dns_client_startresolve(client, name, rdclass, type, options, + client->task, resolve_done, resarg, + &resarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&resarg->lock); + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&resarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = resarg->result; + if (result != ISC_R_SUCCESS && resarg->vresult != ISC_R_SUCCESS) { + /* + * If this lookup failed due to some error in DNSSEC + * validation, return the validation error code. + * XXX: or should we pass the validation result separately? + */ + result = resarg->vresult; + } + if (resarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + resarg->canceled = ISC_TRUE; + dns_client_cancelresolve(resarg->trans); + + UNLOCK(&resarg->lock); + + /* resarg will be freed in the event handler. */ + } else { + UNLOCK(&resarg->lock); + + DESTROYLOCK(&resarg->lock); + isc_mem_put(client->mctx, resarg, sizeof(*resarg)); + } + + return (result); +} + +isc_result_t +dns_client_startresolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_clientrestrans_t **transp) +{ + dns_view_t *view = NULL; + dns_clientresevent_t *event = NULL; + resctx_t *rctx = NULL; + isc_task_t *clone = NULL; + isc_mem_t *mctx; + isc_result_t result; + dns_rdataset_t *rdataset, *sigrdataset; + isc_boolean_t want_dnssec; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(transp != NULL && *transp == NULL); + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + mctx = client->mctx; + rdataset = NULL; + sigrdataset = NULL; + want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0); + + /* + * Prepare some intermediate resources + */ + clone = NULL; + isc_task_attach(task, &clone); + event = (dns_clientresevent_t *) + isc_event_allocate(mctx, clone, DNS_EVENT_CLIENTRESDONE, + action, arg, sizeof(*event)); + if (event == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + event->result = DNS_R_SERVFAIL; + ISC_LIST_INIT(event->answerlist); + + rctx = isc_mem_get(mctx, sizeof(*rctx)); + if (rctx == NULL) + result = ISC_R_NOMEMORY; + else { + result = isc_mutex_init(&rctx->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, rctx, sizeof(*rctx)); + rctx = NULL; + } + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = getrdataset(mctx, &rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + rctx->rdataset = rdataset; + + if (want_dnssec) { + result = getrdataset(mctx, &sigrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + rctx->sigrdataset = sigrdataset; + + dns_fixedname_init(&rctx->name); + result = dns_name_copy(name, dns_fixedname_name(&rctx->name), NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + rctx->client = client; + ISC_LINK_INIT(rctx, link); + rctx->canceled = ISC_FALSE; + rctx->task = client->task; + rctx->type = type; + rctx->view = view; + rctx->restarts = 0; + rctx->fetch = NULL; + rctx->want_dnssec = want_dnssec; + ISC_LIST_INIT(rctx->namelist); + rctx->event = event; + + rctx->magic = RCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->resctxs, rctx, link); + UNLOCK(&client->lock); + + client_resfind(rctx, NULL); + + *transp = (dns_clientrestrans_t *)rctx; + + return (ISC_R_SUCCESS); + + cleanup: + if (rdataset != NULL) + putrdataset(client->mctx, &rdataset); + if (sigrdataset != NULL) + putrdataset(client->mctx, &sigrdataset); + if (rctx != NULL) { + DESTROYLOCK(&rctx->lock); + isc_mem_put(mctx, rctx, sizeof(*rctx)); + } + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + isc_task_detach(&clone); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelresolve(dns_clientrestrans_t *trans) { + resctx_t *rctx; + + REQUIRE(trans != NULL); + rctx = (resctx_t *)trans; + REQUIRE(RCTX_VALID(rctx)); + + LOCK(&rctx->lock); + + if (!rctx->canceled) { + rctx->canceled = ISC_TRUE; + if (rctx->fetch != NULL) + dns_resolver_cancelfetch(rctx->fetch); + } + + UNLOCK(&rctx->lock); +} + +void +dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist) { + dns_name_t *name; + dns_rdataset_t *rdataset; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(namelist != NULL); + + while ((name = ISC_LIST_HEAD(*namelist)) != NULL) { + ISC_LIST_UNLINK(*namelist, name, link); + while ((rdataset = ISC_LIST_HEAD(name->list)) != NULL) { + ISC_LIST_UNLINK(name->list, rdataset, link); + putrdataset(client->mctx, &rdataset); + } + dns_name_free(name, client->mctx); + isc_mem_put(client->mctx, name, sizeof(*name)); + } +} + +void +dns_client_destroyrestrans(dns_clientrestrans_t **transp) { + resctx_t *rctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + + REQUIRE(transp != NULL); + rctx = (resctx_t *)*transp; + REQUIRE(RCTX_VALID(rctx)); + REQUIRE(rctx->fetch == NULL); + REQUIRE(rctx->event == NULL); + client = rctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + + mctx = client->mctx; + dns_view_detach(&rctx->view); + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(rctx, link)); + ISC_LIST_UNLINK(client->resctxs, rctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) + need_destroyclient = ISC_TRUE; + + UNLOCK(&client->lock); + + INSIST(ISC_LIST_EMPTY(rctx->namelist)); + + DESTROYLOCK(&rctx->lock); + rctx->magic = 0; + + isc_mem_put(mctx, rctx, sizeof(*rctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +isc_result_t +dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *keyname, isc_buffer_t *keydatabuf) +{ + isc_result_t result; + dns_view_t *view = NULL; + dst_key_t *dstkey = NULL; + + REQUIRE(DNS_CLIENT_VALID(client)); + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + result = dst_key_fromdns(keyname, rdclass, keydatabuf, client->mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_keytable_add(view->secroots, ISC_FALSE, &dstkey); + + dns_view_detach(&view); + + return (result); +} + +/*% + * Simple request routines + */ +static void +request_done(isc_task_t *task, isc_event_t *event) { + dns_requestevent_t *reqev = NULL; + dns_request_t *request; + isc_result_t result, eresult; + reqctx_t *ctx; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + result = eresult = reqev->result; + ctx = reqev->ev_arg; + REQUIRE(REQCTX_VALID(ctx)); + + isc_event_free(&event); + + LOCK(&ctx->lock); + + if (eresult == ISC_R_SUCCESS) { + result = dns_request_getresponse(request, ctx->event->rmessage, + ctx->parseoptions); + } + + if (ctx->tsigkey != NULL) + dns_tsigkey_detach(&ctx->tsigkey); + + if (ctx->canceled) + ctx->event->result = ISC_R_CANCELED; + else + ctx->event->result = result; + task = ctx->event->ev_sender; + ctx->event->ev_sender = ctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&ctx->event)); + + UNLOCK(&ctx->lock); +} + +static void +localrequest_done(isc_task_t *task, isc_event_t *event) { + reqarg_t *reqarg = event->ev_arg; + dns_clientreqevent_t *rev =(dns_clientreqevent_t *)event; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_CLIENTREQDONE); + + LOCK(&reqarg->lock); + + reqarg->result = rev->result; + dns_client_destroyreqtrans(&reqarg->trans); + isc_event_free(&event); + + if (!reqarg->canceled) { + UNLOCK(&reqarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(reqarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&reqarg->lock); + DESTROYLOCK(&reqarg->lock); + isc_mem_put(reqarg->client->mctx, reqarg, sizeof(*reqarg)); + } +} + +isc_result_t +dns_client_request(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries) +{ + isc_appctx_t *actx; + reqarg_t *reqarg; + isc_result_t result; + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(qmessage != NULL); + REQUIRE(rmessage != NULL); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTREQOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + reqarg = isc_mem_get(client->mctx, sizeof(*reqarg)); + if (reqarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&reqarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + return (result); + } + + reqarg->actx = actx; + reqarg->client = client; + reqarg->trans = NULL; + reqarg->canceled = ISC_FALSE; + + result = dns_client_startrequest(client, qmessage, rmessage, server, + options, parseoptions, tsec, timeout, + udptimeout, udpretries, + client->task, localrequest_done, + reqarg, &reqarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&reqarg->lock); + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&reqarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = reqarg->result; + if (reqarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + reqarg->canceled = ISC_TRUE; + dns_client_cancelresolve(reqarg->trans); + + UNLOCK(&reqarg->lock); + + /* reqarg will be freed in the event handler. */ + } else { + UNLOCK(&reqarg->lock); + + DESTROYLOCK(&reqarg->lock); + isc_mem_put(client->mctx, reqarg, sizeof(*reqarg)); + } + + return (result); +} + +isc_result_t +dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientreqtrans_t **transp) +{ + isc_result_t result; + dns_view_t *view = NULL; + isc_task_t *clone = NULL; + dns_clientreqevent_t *event = NULL; + reqctx_t *ctx = NULL; + dns_tsectype_t tsectype = dns_tsectype_none; + + UNUSED(options); + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(qmessage != NULL); + REQUIRE(rmessage != NULL); + REQUIRE(transp != NULL && *transp == NULL); + + if (tsec != NULL) { + tsectype = dns_tsec_gettype(tsec); + if (tsectype != dns_tsectype_tsig) + return (ISC_R_NOTIMPLEMENTED); /* XXX */ + } + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + qmessage->rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + clone = NULL; + isc_task_attach(task, &clone); + event = (dns_clientreqevent_t *) + isc_event_allocate(client->mctx, clone, + DNS_EVENT_CLIENTREQDONE, + action, arg, sizeof(*event)); + if (event == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + ctx = isc_mem_get(client->mctx, sizeof(*ctx)); + if (ctx == NULL) + result = ISC_R_NOMEMORY; + else { + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, ctx, sizeof(*ctx)); + ctx = NULL; + } + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + ctx->client = client; + ISC_LINK_INIT(ctx, link); + ctx->parseoptions = parseoptions; + ctx->canceled = ISC_FALSE; + ctx->event = event; + ctx->event->rmessage = rmessage; + ctx->tsigkey = NULL; + if (tsec != NULL) + dns_tsec_getkey(tsec, &ctx->tsigkey); + + ctx->magic = REQCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->reqctxs, ctx, link); + UNLOCK(&client->lock); + + ctx->request = NULL; + result = dns_request_createvia3(view->requestmgr, qmessage, NULL, + server, options, ctx->tsigkey, + timeout, udptimeout, udpretries, + client->task, request_done, ctx, + &ctx->request); + if (result == ISC_R_SUCCESS) { + dns_view_detach(&view); + *transp = (dns_clientreqtrans_t *)ctx; + return (ISC_R_SUCCESS); + } + + cleanup: + if (ctx != NULL) { + LOCK(&client->lock); + ISC_LIST_UNLINK(client->reqctxs, ctx, link); + UNLOCK(&client->lock); + DESTROYLOCK(&ctx->lock); + isc_mem_put(client->mctx, ctx, sizeof(*ctx)); + } + if (event != NULL) + isc_event_free(ISC_EVENT_PTR(&event)); + isc_task_detach(&clone); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelrequest(dns_clientreqtrans_t *trans) { + reqctx_t *ctx; + + REQUIRE(trans != NULL); + ctx = (reqctx_t *)trans; + REQUIRE(REQCTX_VALID(ctx)); + + LOCK(&ctx->lock); + + if (!ctx->canceled) { + ctx->canceled = ISC_TRUE; + if (ctx->request != NULL) + dns_request_cancel(ctx->request); + } + + UNLOCK(&ctx->lock); +} + +void +dns_client_destroyreqtrans(dns_clientreqtrans_t **transp) { + reqctx_t *ctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + + REQUIRE(transp != NULL); + ctx = (reqctx_t *)*transp; + REQUIRE(REQCTX_VALID(ctx)); + client = ctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(ctx->event == NULL); + REQUIRE(ctx->request != NULL); + + dns_request_destroy(&ctx->request); + mctx = client->mctx; + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(ctx, link)); + ISC_LIST_UNLINK(client->reqctxs, ctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) { + need_destroyclient = ISC_TRUE; + } + + UNLOCK(&client->lock); + + DESTROYLOCK(&ctx->lock); + ctx->magic = 0; + + isc_mem_put(mctx, ctx, sizeof(*ctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +/*% + * Dynamic update routines + */ +static isc_result_t +rcode2result(dns_rcode_t rcode) { + /* XXX: isn't there a similar function? */ + switch (rcode) { + case dns_rcode_formerr: + return (DNS_R_FORMERR); + case dns_rcode_servfail: + return (DNS_R_SERVFAIL); + case dns_rcode_nxdomain: + return (DNS_R_NXDOMAIN); + case dns_rcode_notimp: + return (DNS_R_NOTIMP); + case dns_rcode_refused: + return (DNS_R_REFUSED); + case dns_rcode_yxdomain: + return (DNS_R_YXDOMAIN); + case dns_rcode_yxrrset: + return (DNS_R_YXRRSET); + case dns_rcode_nxrrset: + return (DNS_R_NXRRSET); + case dns_rcode_notauth: + return (DNS_R_NOTAUTH); + case dns_rcode_notzone: + return (DNS_R_NOTZONE); + case dns_rcode_badvers: + return (DNS_R_BADVERS); + } + + return (ISC_R_FAILURE); +} + +static void +update_sendevent(updatectx_t *uctx, isc_result_t result) { + isc_task_t *task; + + dns_message_destroy(&uctx->updatemsg); + if (uctx->tsigkey != NULL) + dns_tsigkey_detach(&uctx->tsigkey); + if (uctx->sig0key != NULL) + dst_key_free(&uctx->sig0key); + + if (uctx->canceled) + uctx->event->result = ISC_R_CANCELED; + else + uctx->event->result = result; + uctx->event->state = uctx->state; + task = uctx->event->ev_sender; + uctx->event->ev_sender = uctx; + isc_task_sendanddetach(&task, ISC_EVENT_PTR(&uctx->event)); +} + +static void +update_done(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_requestevent_t *reqev = NULL; + dns_request_t *request; + dns_message_t *answer = NULL; + updatectx_t *uctx = event->ev_arg; + dns_client_t *client; + unsigned int timeout; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + REQUIRE(UCTX_VALID(uctx)); + client = uctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + + result = reqev->result; + if (result != ISC_R_SUCCESS) + goto out; + + result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, + &answer); + if (result != ISC_R_SUCCESS) + goto out; + uctx->state = dns_clientupdatestate_done; + result = dns_request_getresponse(request, answer, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result == ISC_R_SUCCESS && answer->rcode != dns_rcode_noerror) + result = rcode2result(answer->rcode); + + out: + if (answer != NULL) + dns_message_destroy(&answer); + isc_event_free(&event); + + LOCK(&uctx->lock); + uctx->currentserver = ISC_LIST_NEXT(uctx->currentserver, link); + dns_request_destroy(&uctx->updatereq); + if (result != ISC_R_SUCCESS && !uctx->canceled && + uctx->currentserver != NULL) { + dns_message_renderreset(uctx->updatemsg); + dns_message_settsigkey(uctx->updatemsg, NULL); + + timeout = client->update_timeout / uctx->nservers; + if (timeout < MIN_UPDATE_TIMEOUT) + timeout = MIN_UPDATE_TIMEOUT; + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->updatemsg, + NULL, + uctx->currentserver, 0, + uctx->tsigkey, + timeout, + client->update_udptimeout, + client->update_udpretries, + client->task, + update_done, uctx, + &uctx->updatereq); + UNLOCK(&uctx->lock); + + if (result == ISC_R_SUCCESS) { + /* XXX: should we keep the 'done' state here? */ + uctx->state = dns_clientupdatestate_sent; + return; + } + } else + UNLOCK(&uctx->lock); + + update_sendevent(uctx, result); +} + +static isc_result_t +send_update(updatectx_t *uctx) { + isc_result_t result; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + dns_client_t *client = uctx->client; + unsigned int timeout; + + REQUIRE(uctx->zonename != NULL && uctx->currentserver != NULL); + + result = dns_message_gettempname(uctx->updatemsg, &name); + if (result != ISC_R_SUCCESS) + return (result); + dns_name_init(name, NULL); + dns_name_clone(uctx->zonename, name); + result = dns_message_gettemprdataset(uctx->updatemsg, &rdataset); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(uctx->updatemsg, &name); + return (result); + } + dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(uctx->updatemsg, name, DNS_SECTION_ZONE); + if (uctx->tsigkey == NULL && uctx->sig0key != NULL) { + result = dns_message_setsig0key(uctx->updatemsg, + uctx->sig0key); + if (result != ISC_R_SUCCESS) + return (result); + } + timeout = client->update_timeout / uctx->nservers; + if (timeout < MIN_UPDATE_TIMEOUT) + timeout = MIN_UPDATE_TIMEOUT; + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->updatemsg, + NULL, uctx->currentserver, 0, + uctx->tsigkey, timeout, + client->update_udptimeout, + client->update_udpretries, + client->task, update_done, uctx, + &uctx->updatereq); + if (result == ISC_R_SUCCESS && + uctx->state == dns_clientupdatestate_prepare) { + uctx->state = dns_clientupdatestate_sent; + } + + return (result); +} + +static void +resolveaddr_done(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + int family; + dns_rdatatype_t qtype; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + updatectx_t *uctx; + isc_boolean_t completed = ISC_FALSE; + + UNUSED(task); + + REQUIRE(event->ev_arg != NULL); + uctx = *(updatectx_t **)event->ev_arg; + REQUIRE(UCTX_VALID(uctx)); + + if (event->ev_arg == &uctx->bp4) { + family = AF_INET; + qtype = dns_rdatatype_a; + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans); + UNLOCK(&uctx->lock); + } else { + INSIST(event->ev_arg == &uctx->bp6); + family = AF_INET6; + qtype = dns_rdatatype_aaaa; + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans2); + UNLOCK(&uctx->lock); + } + + result = rev->result; + if (result != ISC_R_SUCCESS) + goto done; + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != qtype) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata; + dns_rdata_in_a_t rdata_a; + dns_rdata_in_aaaa_t rdata_aaaa; + isc_sockaddr_t *sa; + + sa = isc_mem_get(uctx->client->mctx, + sizeof(*sa)); + if (sa == NULL) { + /* + * If we fail to get a sockaddr, + we simply move forward with the + * addresses we've got so far. + */ + goto done; + } + + dns_rdata_init(&rdata); + switch (family) { + case AF_INET: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + isc_sockaddr_fromin(sa, + &rdata_a.in_addr, + 53); + dns_rdata_freestruct(&rdata_a); + break; + case AF_INET6: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_aaaa, + NULL); + isc_sockaddr_fromin6(sa, + &rdata_aaaa.in6_addr, + 53); + dns_rdata_freestruct(&rdata_aaaa); + break; + } + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(uctx->servers, sa, link); + uctx->nservers++; + } + } + } + + done: + dns_client_freeresanswer(uctx->client, &rev->answerlist); + isc_event_free(&event); + + LOCK(&uctx->lock); + if (uctx->restrans == NULL && uctx->restrans2 == NULL) + completed = ISC_TRUE; + UNLOCK(&uctx->lock); + + if (completed) { + INSIST(uctx->currentserver == NULL); + uctx->currentserver = ISC_LIST_HEAD(uctx->servers); + if (uctx->currentserver != NULL && !uctx->canceled) + send_update(uctx); + else { + if (result == ISC_R_SUCCESS) + result = ISC_R_NOTFOUND; + update_sendevent(uctx, result); + } + } +} + +static isc_result_t +process_soa(updatectx_t *uctx, dns_rdataset_t *soaset, dns_name_t *soaname) { + isc_result_t result; + dns_rdata_t soarr = DNS_RDATA_INIT; + dns_rdata_soa_t soa; + dns_name_t primary; + + result = dns_rdataset_first(soaset); + if (result != ISC_R_SUCCESS) + return (result); + dns_rdata_init(&soarr); + dns_rdataset_current(soaset, &soarr); + result = dns_rdata_tostruct(&soarr, &soa, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + dns_name_init(&primary, NULL); + dns_name_clone(&soa.origin, &primary); + + if (uctx->zonename == NULL) { + uctx->zonename = dns_fixedname_name(&uctx->zonefname); + result = dns_name_copy(soaname, uctx->zonename, NULL); + if (result != ISC_R_SUCCESS) + goto out; + } + + if (uctx->currentserver != NULL) + result = send_update(uctx); + else { + /* + * Get addresses of the primary server. We don't use the ADB + * feature so that we could avoid caching data. + */ + LOCK(&uctx->lock); + uctx->bp4 = uctx; + result = dns_client_startresolve(uctx->client, &primary, + uctx->rdclass, + dns_rdatatype_a, + 0, uctx->client->task, + resolveaddr_done, &uctx->bp4, + &uctx->restrans); + if (result == ISC_R_SUCCESS) { + uctx->bp6 = uctx; + result = dns_client_startresolve(uctx->client, + &primary, + uctx->rdclass, + dns_rdatatype_aaaa, + 0, uctx->client->task, + resolveaddr_done, + &uctx->bp6, + &uctx->restrans2); + } + UNLOCK(&uctx->lock); + } + + out: + dns_rdata_freestruct(&soa); + + return (result); +} + +static void +receive_soa(isc_task_t *task, isc_event_t *event) { + dns_requestevent_t *reqev = NULL; + updatectx_t *uctx; + dns_client_t *client; + isc_result_t result, eresult; + dns_request_t *request; + dns_message_t *rcvmsg = NULL; + dns_section_t section; + dns_rdataset_t *soaset = NULL; + int pass = 0; + dns_name_t *name; + dns_message_t *soaquery = NULL; + isc_sockaddr_t *addr; + isc_boolean_t seencname = ISC_FALSE; + isc_boolean_t droplabel = ISC_FALSE; + dns_name_t tname; + unsigned int nlabels; + + UNUSED(task); + + REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); + reqev = (dns_requestevent_t *)event; + request = reqev->request; + result = eresult = reqev->result; + uctx = reqev->ev_arg; + client = uctx->client; + soaquery = uctx->soaquery; + addr = uctx->currentserver; + INSIST(addr != NULL); + + isc_event_free(&event); + + if (eresult != ISC_R_SUCCESS) { + result = eresult; + goto out; + } + + result = dns_message_create(uctx->client->mctx, + DNS_MESSAGE_INTENTPARSE, &rcvmsg); + if (result != ISC_R_SUCCESS) + goto out; + result = dns_request_getresponse(request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); + + if (result == DNS_R_TSIGERRORSET) { + dns_request_t *newrequest = NULL; + + /* Retry SOA request without TSIG */ + dns_message_destroy(&rcvmsg); + dns_message_renderreset(uctx->soaquery); + result = dns_request_createvia3(uctx->view->requestmgr, + uctx->soaquery, NULL, addr, 0, + NULL, + client->find_timeout * 20, + client->find_timeout, 3, + uctx->client->task, + receive_soa, uctx, + &newrequest); + if (result == ISC_R_SUCCESS) { + LOCK(&uctx->lock); + dns_request_destroy(&uctx->soareq); + uctx->soareq = newrequest; + UNLOCK(&uctx->lock); + + return; + } + goto out; + } + + section = DNS_SECTION_ANSWER; + + if (rcvmsg->rcode != dns_rcode_noerror && + rcvmsg->rcode != dns_rcode_nxdomain) { + result = rcode2result(rcvmsg->rcode); + goto out; + } + + lookforsoa: + if (pass == 0) + section = DNS_SECTION_ANSWER; + else if (pass == 1) + section = DNS_SECTION_AUTHORITY; + else { + droplabel = ISC_TRUE; + goto out; + } + + result = dns_message_firstname(rcvmsg, section); + if (result != ISC_R_SUCCESS) { + pass++; + goto lookforsoa; + } + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rcvmsg, section, &name); + soaset = NULL; + result = dns_message_findtype(name, dns_rdatatype_soa, 0, + &soaset); + if (result == ISC_R_SUCCESS) + break; + if (section == DNS_SECTION_ANSWER) { + dns_rdataset_t *tset = NULL; + if (dns_message_findtype(name, dns_rdatatype_cname, 0, + &tset) == ISC_R_SUCCESS + || + dns_message_findtype(name, dns_rdatatype_dname, 0, + &tset) == ISC_R_SUCCESS + ) + { + seencname = ISC_TRUE; + break; + } + } + + result = dns_message_nextname(rcvmsg, section); + } + + if (soaset == NULL && !seencname) { + pass++; + goto lookforsoa; + } + + if (seencname) { + droplabel = ISC_TRUE; + goto out; + } + + result = process_soa(uctx, soaset, name); + + out: + if (droplabel) { + result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); + INSIST(result == ISC_R_SUCCESS); + name = NULL; + dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); + nlabels = dns_name_countlabels(name); + if (nlabels == 1) + result = DNS_R_SERVFAIL; /* is there a better error? */ + else { + dns_name_init(&tname, NULL); + dns_name_getlabelsequence(name, 1, nlabels - 1, + &tname); + dns_name_clone(&tname, name); + dns_request_destroy(&request); + LOCK(&uctx->lock); + uctx->soareq = NULL; + UNLOCK(&uctx->lock); + dns_message_renderreset(soaquery); + dns_message_settsigkey(soaquery, NULL); + result = dns_request_createvia3(uctx->view->requestmgr, + soaquery, NULL, + uctx->currentserver, 0, + uctx->tsigkey, + client->find_timeout * + 20, + client->find_timeout, + 3, client->task, + receive_soa, uctx, + &uctx->soareq); + } + } + + if (!droplabel || result != ISC_R_SUCCESS) { + dns_message_destroy(&uctx->soaquery); + LOCK(&uctx->lock); + dns_request_destroy(&uctx->soareq); + UNLOCK(&uctx->lock); + } + + if (rcvmsg != NULL) + dns_message_destroy(&rcvmsg); + + if (result != ISC_R_SUCCESS) + update_sendevent(uctx, result); +} + +static isc_result_t +request_soa(updatectx_t *uctx) { + isc_result_t result; + dns_message_t *soaquery = uctx->soaquery; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + + if (soaquery == NULL) { + result = dns_message_create(uctx->client->mctx, + DNS_MESSAGE_INTENTRENDER, + &soaquery); + if (result != ISC_R_SUCCESS) + return (result); + } + soaquery->flags |= DNS_MESSAGEFLAG_RD; + result = dns_message_gettempname(soaquery, &name); + if (result != ISC_R_SUCCESS) + goto fail; + result = dns_message_gettemprdataset(soaquery, &rdataset); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa); + dns_name_clone(uctx->firstname, name); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); + rdataset = NULL; + name = NULL; + + result = dns_request_createvia3(uctx->view->requestmgr, + soaquery, NULL, uctx->currentserver, 0, + uctx->tsigkey, + uctx->client->find_timeout * 20, + uctx->client->find_timeout, 3, + uctx->client->task, receive_soa, uctx, + &uctx->soareq); + if (result == ISC_R_SUCCESS) { + uctx->soaquery = soaquery; + return (ISC_R_SUCCESS); + } + + fail: + if (rdataset != NULL) { + ISC_LIST_UNLINK(name->list, rdataset, link); /* for safety */ + dns_message_puttemprdataset(soaquery, &rdataset); + } + if (name != NULL) + dns_message_puttempname(soaquery, &name); + dns_message_destroy(&soaquery); + + return (result); +} + +static void +resolvesoa_done(isc_task_t *task, isc_event_t *event) { + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + updatectx_t *uctx; + dns_name_t *name, tname; + dns_rdataset_t *rdataset = NULL; + isc_result_t result = rev->result; + unsigned int nlabels; + + UNUSED(task); + + uctx = event->ev_arg; + REQUIRE(UCTX_VALID(uctx)); + + LOCK(&uctx->lock); + dns_client_destroyrestrans(&uctx->restrans); + UNLOCK(&uctx->lock); + + uctx = event->ev_arg; + if (result != ISC_R_SUCCESS && + result != DNS_R_NCACHENXDOMAIN && + result != DNS_R_NCACHENXRRSET) { + /* XXX: what about DNSSEC failure? */ + goto out; + } + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (dns_rdataset_isassociated(rdataset) && + rdataset->type == dns_rdatatype_soa) + break; + } + } + + if (rdataset == NULL) { + /* Drop one label and retry resolution. */ + nlabels = dns_name_countlabels(&uctx->soaqname); + if (nlabels == 1) { + result = DNS_R_SERVFAIL; /* is there a better error? */ + goto out; + } + dns_name_init(&tname, NULL); + dns_name_getlabelsequence(&uctx->soaqname, 1, nlabels - 1, + &tname); + dns_name_clone(&tname, &uctx->soaqname); + + result = dns_client_startresolve(uctx->client, &uctx->soaqname, + uctx->rdclass, + dns_rdatatype_soa, 0, + uctx->client->task, + resolvesoa_done, uctx, + &uctx->restrans); + } else + result = process_soa(uctx, rdataset, &uctx->soaqname); + + out: + dns_client_freeresanswer(uctx->client, &rev->answerlist); + isc_event_free(&event); + + if (result != ISC_R_SUCCESS) + update_sendevent(uctx, result); +} + +static isc_result_t +copy_name(isc_mem_t *mctx, dns_message_t *msg, dns_name_t *name, + dns_name_t **newnamep) +{ + isc_result_t result; + dns_name_t *newname = NULL; + isc_region_t r; + isc_buffer_t *namebuf = NULL, *rdatabuf = NULL; + dns_rdatalist_t *rdatalist; + dns_rdataset_t *rdataset, *newrdataset; + dns_rdata_t rdata = DNS_RDATA_INIT, *newrdata; + + result = dns_message_gettempname(msg, &newname); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + goto fail; + dns_name_init(newname, NULL); + dns_name_setbuffer(newname, namebuf); + dns_message_takebuffer(msg, &namebuf); + result = dns_name_copy(name, newname, NULL); + if (result != ISC_R_SUCCESS) + goto fail; + + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + rdatalist = NULL; + result = dns_message_gettemprdatalist(msg, &rdatalist); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdatalist_init(rdatalist); + rdatalist->type = rdataset->type; + rdatalist->rdclass = rdataset->rdclass; + rdatalist->covers = rdataset->covers; + rdatalist->ttl = rdataset->ttl; + + result = dns_rdataset_first(rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + + newrdata = NULL; + result = dns_message_gettemprdata(msg, &newrdata); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdata_toregion(&rdata, &r); + rdatabuf = NULL; + result = isc_buffer_allocate(mctx, &rdatabuf, + r.length); + if (result != ISC_R_SUCCESS) + goto fail; + isc_buffer_putmem(rdatabuf, r.base, r.length); + isc_buffer_usedregion(rdatabuf, &r); + dns_rdata_init(newrdata); + dns_rdata_fromregion(newrdata, rdata.rdclass, + rdata.type, &r); + newrdata->flags = rdata.flags; + + ISC_LIST_APPEND(rdatalist->rdata, newrdata, link); + dns_message_takebuffer(msg, &rdatabuf); + + result = dns_rdataset_next(rdataset); + } + + newrdataset = NULL; + result = dns_message_gettemprdataset(msg, &newrdataset); + if (result != ISC_R_SUCCESS) + goto fail; + dns_rdataset_init(newrdataset); + dns_rdatalist_tordataset(rdatalist, newrdataset); + + ISC_LIST_APPEND(newname->list, newrdataset, link); + } + + *newnamep = newname; + + return (ISC_R_SUCCESS); + + fail: + dns_message_puttempname(msg, &newname); + + return (result); + +} + +static void +internal_update_callback(isc_task_t *task, isc_event_t *event) { + updatearg_t *uarg = event->ev_arg; + dns_clientupdateevent_t *uev = (dns_clientupdateevent_t *)event; + + UNUSED(task); + + LOCK(&uarg->lock); + + uarg->result = uev->result; + + dns_client_destroyupdatetrans(&uarg->trans); + isc_event_free(&event); + + if (!uarg->canceled) { + UNLOCK(&uarg->lock); + + /* Exit from the internal event loop */ + isc_app_ctxsuspend(uarg->actx); + } else { + /* + * We have already exited from the loop (due to some + * unexpected event). Just clean the arg up. + */ + UNLOCK(&uarg->lock); + DESTROYLOCK(&uarg->lock); + isc_mem_put(uarg->client->mctx, uarg, sizeof(*uarg)); + } +} + +isc_result_t +dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options) +{ + isc_result_t result; + isc_appctx_t *actx; + updatearg_t *uarg; + + REQUIRE(DNS_CLIENT_VALID(client)); + + if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 && + (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) { + /* + * If the client is run under application's control, we need + * to create a new running (sub)environment for this + * particular resolution. + */ + return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */ + } else + actx = client->actx; + + uarg = isc_mem_get(client->mctx, sizeof(*uarg)); + if (uarg == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&uarg->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + return (result); + } + + uarg->actx = actx; + uarg->client = client; + uarg->result = ISC_R_FAILURE; + uarg->trans = NULL; + uarg->canceled = ISC_FALSE; + + result = dns_client_startupdate(client, rdclass, zonename, + prerequisites, updates, servers, + tsec, options, client->task, + internal_update_callback, uarg, + &uarg->trans); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&uarg->lock); + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + return (result); + } + + /* + * Start internal event loop. It blocks until the entire process + * is completed. + */ + result = isc_app_ctxrun(actx); + + LOCK(&uarg->lock); + if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) + result = uarg->result; + + if (uarg->trans != NULL) { + /* + * Unusual termination (perhaps due to signal). We need some + * tricky cleanup process. + */ + uarg->canceled = ISC_TRUE; + dns_client_cancelupdate(uarg->trans); + + UNLOCK(&uarg->lock); + + /* uarg will be freed in the event handler. */ + } else { + UNLOCK(&uarg->lock); + + DESTROYLOCK(&uarg->lock); + isc_mem_put(client->mctx, uarg, sizeof(*uarg)); + } + + return (result); +} + +isc_result_t +dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientupdatetrans_t **transp) +{ + dns_view_t *view = NULL; + isc_result_t result; + dns_name_t *name, *newname; + updatectx_t *uctx; + isc_task_t *clone = NULL; + dns_section_t section = DNS_SECTION_UPDATE; + isc_sockaddr_t *server, *sa = NULL; + dns_tsectype_t tsectype = dns_tsectype_none; + + UNUSED(options); + + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(transp != NULL && *transp == NULL); + REQUIRE(updates != NULL); + REQUIRE(task != NULL); + + if (tsec != NULL) { + tsectype = dns_tsec_gettype(tsec); + if (tsectype != dns_tsectype_tsig) + return (ISC_R_NOTIMPLEMENTED); /* XXX */ + } + + LOCK(&client->lock); + result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, + rdclass, &view); + UNLOCK(&client->lock); + if (result != ISC_R_SUCCESS) + return (result); + + /* Create a context and prepare some resources */ + uctx = isc_mem_get(client->mctx, sizeof(*uctx)); + if (uctx == NULL) { + dns_view_detach(&view); + return (ISC_R_NOMEMORY); + } + result = isc_mutex_init(&uctx->lock); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + isc_mem_put(client->mctx, uctx, sizeof(*uctx)); + return (ISC_R_NOMEMORY); + } + clone = NULL; + isc_task_attach(task, &clone); + uctx->client = client; + ISC_LINK_INIT(uctx, link); + uctx->state = dns_clientupdatestate_prepare; + uctx->view = view; + uctx->rdclass = rdclass; + uctx->canceled = ISC_FALSE; + uctx->updatemsg = NULL; + uctx->soaquery = NULL; + uctx->updatereq = NULL; + uctx->restrans = NULL; + uctx->restrans2 = NULL; + uctx->bp4 = NULL; + uctx->bp6 = NULL; + uctx->soareq = NULL; + uctx->event = NULL; + uctx->tsigkey = NULL; + uctx->sig0key = NULL; + uctx->zonename = NULL; + dns_name_init(&uctx->soaqname, NULL); + ISC_LIST_INIT(uctx->servers); + uctx->nservers = 0; + uctx->currentserver = NULL; + dns_fixedname_init(&uctx->zonefname); + if (tsec != NULL) + dns_tsec_getkey(tsec, &uctx->tsigkey); + uctx->event = (dns_clientupdateevent_t *) + isc_event_allocate(client->mctx, clone, DNS_EVENT_UPDATEDONE, + action, arg, sizeof(*uctx->event)); + if (uctx->event == NULL) + goto fail; + if (zonename != NULL) { + uctx->zonename = dns_fixedname_name(&uctx->zonefname); + result = dns_name_copy(zonename, uctx->zonename, NULL); + } + if (servers != NULL) { + for (server = ISC_LIST_HEAD(*servers); + server != NULL; + server = ISC_LIST_NEXT(server, link)) { + sa = isc_mem_get(client->mctx, sizeof(*sa)); + if (sa == NULL) + goto fail; + sa->type = server->type; + sa->length = server->length; + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(uctx->servers, sa, link); + if (uctx->currentserver == NULL) + uctx->currentserver = sa; + uctx->nservers++; + } + } + + /* Make update message */ + result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTRENDER, + &uctx->updatemsg); + if (result != ISC_R_SUCCESS) + goto fail; + uctx->updatemsg->opcode = dns_opcode_update; + + if (prerequisites != NULL) { + for (name = ISC_LIST_HEAD(*prerequisites); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + newname = NULL; + result = copy_name(client->mctx, uctx->updatemsg, + name, &newname); + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_addname(uctx->updatemsg, newname, + DNS_SECTION_PREREQUISITE); + } + } + + for (name = ISC_LIST_HEAD(*updates); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + newname = NULL; + result = copy_name(client->mctx, uctx->updatemsg, name, + &newname); + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_addname(uctx->updatemsg, newname, + DNS_SECTION_UPDATE); + } + + uctx->firstname = NULL; + result = dns_message_firstname(uctx->updatemsg, section); + if (result == ISC_R_NOMORE) { + section = DNS_SECTION_PREREQUISITE; + result = dns_message_firstname(uctx->updatemsg, section); + } + if (result != ISC_R_SUCCESS) + goto fail; + dns_message_currentname(uctx->updatemsg, section, &uctx->firstname); + + uctx->magic = UCTX_MAGIC; + + LOCK(&client->lock); + ISC_LIST_APPEND(client->updatectxs, uctx, link); + UNLOCK(&client->lock); + + if (uctx->zonename != NULL && uctx->currentserver != NULL) { + result = send_update(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else if (uctx->currentserver != NULL) { + result = request_soa(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else { + dns_name_clone(uctx->firstname, &uctx->soaqname); + result = dns_client_startresolve(uctx->client, &uctx->soaqname, + uctx->rdclass, + dns_rdatatype_soa, 0, + client->task, resolvesoa_done, + uctx, &uctx->restrans); + if (result != ISC_R_SUCCESS) + goto fail; + } + + *transp = (dns_clientupdatetrans_t *)uctx; + + return (ISC_R_SUCCESS); + + fail: + if (ISC_LINK_LINKED(uctx, link)) { + LOCK(&client->lock); + ISC_LIST_UNLINK(client->updatectxs, uctx, link); + UNLOCK(&client->lock); + } + if (uctx->updatemsg != NULL) + dns_message_destroy(&uctx->updatemsg); + while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) { + ISC_LIST_UNLINK(uctx->servers, sa, link); + isc_mem_put(client->mctx, sa, sizeof(*sa)); + } + if (uctx->event != NULL) + isc_event_free(ISC_EVENT_PTR(&uctx->event)); + if (uctx->tsigkey != NULL) + dns_tsigkey_detach(&uctx->tsigkey); + isc_task_detach(&clone); + DESTROYLOCK(&uctx->lock); + uctx->magic = 0; + isc_mem_put(client->mctx, uctx, sizeof(*uctx)); + dns_view_detach(&view); + + return (result); +} + +void +dns_client_cancelupdate(dns_clientupdatetrans_t *trans) { + updatectx_t *uctx; + + REQUIRE(trans != NULL); + uctx = (updatectx_t *)trans; + REQUIRE(UCTX_VALID(uctx)); + + LOCK(&uctx->lock); + + if (!uctx->canceled) { + uctx->canceled = ISC_TRUE; + if (uctx->updatereq != NULL) + dns_request_cancel(uctx->updatereq); + if (uctx->soareq != NULL) + dns_request_cancel(uctx->soareq); + if (uctx->restrans != NULL) + dns_client_cancelresolve(&uctx->restrans); + if (uctx->restrans2 != NULL) + dns_client_cancelresolve(&uctx->restrans2); + } + + UNLOCK(&uctx->lock); +} + +void +dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp) { + updatectx_t *uctx; + isc_mem_t *mctx; + dns_client_t *client; + isc_boolean_t need_destroyclient = ISC_FALSE; + isc_sockaddr_t *sa; + + REQUIRE(transp != NULL); + uctx = (updatectx_t *)*transp; + REQUIRE(UCTX_VALID(uctx)); + client = uctx->client; + REQUIRE(DNS_CLIENT_VALID(client)); + REQUIRE(uctx->updatereq == NULL && uctx->updatemsg == NULL && + uctx->soareq == NULL && uctx->soaquery == NULL && + uctx->event == NULL && uctx->tsigkey == NULL && + uctx->sig0key == NULL); + + mctx = client->mctx; + dns_view_detach(&uctx->view); + while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) { + ISC_LIST_UNLINK(uctx->servers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + LOCK(&client->lock); + + INSIST(ISC_LINK_LINKED(uctx, link)); + ISC_LIST_UNLINK(client->updatectxs, uctx, link); + + if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) && + ISC_LIST_EMPTY(client->reqctxs) && + ISC_LIST_EMPTY(client->updatectxs)) + need_destroyclient = ISC_TRUE; + + UNLOCK(&client->lock); + + DESTROYLOCK(&uctx->lock); + uctx->magic = 0; + + isc_mem_put(mctx, uctx, sizeof(*uctx)); + + if (need_destroyclient) + destroyclient(&client); + + *transp = NULL; +} + +isc_mem_t * +dns_client_mctx(dns_client_t *client) { + + REQUIRE(DNS_CLIENT_VALID(client)); + return (client->mctx); +} + +typedef struct { + isc_buffer_t buffer; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata; + size_t size; + isc_mem_t * mctx; + unsigned char data[0]; +} dns_client_updaterec_t; + +isc_result_t +dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner, + dns_rdatatype_t type, dns_rdata_t *source, + dns_ttl_t ttl, dns_name_t *target, + dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist, + dns_rdata_t *rdata, isc_mem_t *mctx) +{ + dns_client_updaterec_t *updaterec; + size_t size = sizeof(dns_client_updaterec_t); + isc_buffer_t *b = NULL; + + REQUIRE(op < updateop_max); + REQUIRE(owner != NULL); + REQUIRE((rdataset != NULL && rdatalist != NULL && rdata != NULL) || + (rdataset == NULL && rdatalist == NULL && rdata == NULL && + mctx != NULL)); + if (op == updateop_add) + REQUIRE(source != NULL); + if (source != NULL) { + REQUIRE(source->type == type); + REQUIRE(op == updateop_add || op == updateop_delete || + op == updateop_exist); + } + + size += owner->length; + if (source != NULL) + size += source->length; + + if (rdataset == NULL) { + updaterec = isc_mem_get(mctx, size); + if (updaterec == NULL) + return (ISC_R_NOMEMORY); + rdataset = &updaterec->rdataset; + rdatalist = &updaterec->rdatalist; + rdata = &updaterec->rdata; + dns_rdataset_init(rdataset); + dns_rdatalist_init(&updaterec->rdatalist); + dns_rdata_init(&updaterec->rdata); + isc_buffer_init(b, b + 1, + size - sizeof(dns_client_updaterec_t)); + dns_name_copy(owner, target, b); + if (source != NULL) { + isc_region_t r; + dns_rdata_clone(source, rdata); + dns_rdata_toregion(rdata, &r); + rdata->data = isc_buffer_used(b); + isc_buffer_copyregion(b, &r); + + } + updaterec->mctx = NULL; + isc_mem_attach(mctx, &updaterec->mctx); + } else if (source != NULL) + dns_rdata_clone(source, rdata); + + switch (op) { + case updateop_add: + break; + case updateop_delete: + if (source != NULL) { + ttl = 0; + dns_rdata_makedelete(rdata); + } else + dns_rdata_deleterrset(rdata, type); + break; + case updateop_notexist: + dns_rdata_notexist(rdata, type); + break; + case updateop_exist: + if (source == NULL) { + ttl = 0; + dns_rdata_exists(rdata, type); + } + case updateop_none: + break; + default: + INSIST(0); + } + + rdatalist->type = rdata->type; + rdatalist->rdclass = rdata->rdclass; + if (source != NULL) { + rdatalist->covers = dns_rdata_covers(rdata); + rdatalist->ttl = ttl; + } + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_APPEND(target->list, rdataset, link); + if (b != NULL) { + target->attributes |= DNS_NAMEATTR_HASUPDATEREC; + dns_name_setbuffer(target, b); + } + if (op == updateop_add || op == updateop_delete) + target->attributes |= DNS_NAMEATTR_UPDATE; + else + target->attributes |= DNS_NAMEATTR_PREREQUISITE; + return (ISC_R_SUCCESS); +} + +void +dns_client_freeupdate(dns_name_t **namep) { + dns_client_updaterec_t *updaterec; + dns_rdatalist_t *rdatalist; + dns_rdataset_t *rdataset; + dns_rdata_t *rdata; + dns_name_t *name; + + REQUIRE(namep != NULL && *namep != NULL); + + name = *namep; + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_HEAD(name->list)) { + ISC_LIST_UNLINK(name->list, rdataset, link); + rdatalist = NULL; + dns_rdatalist_fromrdataset(rdataset, &rdatalist); + if (rdatalist == NULL) { + dns_rdataset_disassociate(rdataset); + continue; + } + for (rdata = ISC_LIST_HEAD(rdatalist->rdata); + rdata != NULL; + rdata = ISC_LIST_HEAD(rdatalist->rdata)) + ISC_LIST_UNLINK(rdatalist->rdata, rdata, link); + dns_rdataset_disassociate(rdataset); + } + + if ((name->attributes & DNS_NAMEATTR_HASUPDATEREC) != 0) { + updaterec = (dns_client_updaterec_t *)name->buffer; + INSIST(updaterec != NULL); + isc_mem_putanddetach(&updaterec->mctx, updaterec, + updaterec->size); + *namep = NULL; + } +} diff --git a/lib/dns/db.c b/lib/dns/db.c index f120fcbb19..bc64bd85c7 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.c,v 1.93 2009/07/19 23:47:55 tbox Exp $ */ +/* $Id: db.c,v 1.94 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -63,14 +63,18 @@ struct dns_dbimplementation { */ #include "rbtdb.h" +#ifdef BIND9 #include "rbtdb64.h" +#endif static ISC_LIST(dns_dbimplementation_t) implementations; static isc_rwlock_t implock; static isc_once_t once = ISC_ONCE_INIT; static dns_dbimplementation_t rbtimp; +#ifdef BIND9 static dns_dbimplementation_t rbt64imp; +#endif static void initialize(void) { @@ -82,15 +86,19 @@ initialize(void) { rbtimp.driverarg = NULL; ISC_LINK_INIT(&rbtimp, link); +#ifdef BIND9 rbt64imp.name = "rbt64"; rbt64imp.create = dns_rbtdb64_create; rbt64imp.mctx = NULL; rbt64imp.driverarg = NULL; ISC_LINK_INIT(&rbt64imp, link); +#endif ISC_LIST_INIT(implementations); ISC_LIST_APPEND(implementations, &rbtimp, link); +#ifdef BIND9 ISC_LIST_APPEND(implementations, &rbt64imp, link); +#endif } static inline dns_dbimplementation_t * @@ -292,6 +300,7 @@ dns_db_class(dns_db_t *db) { return (db->rdclass); } +#ifdef BIND9 isc_result_t dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { @@ -383,6 +392,7 @@ dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename, return ((db->methods->dump)(db, version, filename, masterformat)); } +#endif /* BIND9 */ /*** *** Version Methods diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 9103dd69d9..e13230557e 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.163 2009/04/28 21:39:00 jinmei Exp $ */ +/* $Id: dispatch.c,v 1.164 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -417,7 +417,7 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, /*% * ARC4 random number generator derived from OpenBSD. - * Only dispatch_arc4random() and dispatch_arc4uniformrandom() are expected + * Only dispatch_random() and dispatch_uniformrandom() are expected * to be called from general dispatch routines; the rest of them are subroutines * for these two. * @@ -437,8 +437,11 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp, * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef BIND9 static void -dispatch_arc4init(arc4ctx_t *actx, isc_entropy_t *entropy, isc_mutex_t *lock) { +dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy, + isc_mutex_t *lock) +{ int n; for (n = 0; n < 256; n++) actx->s[n] = n; @@ -527,7 +530,7 @@ dispatch_arc4stir(arc4ctx_t *actx) { } static isc_uint16_t -dispatch_arc4random(arc4ctx_t *actx) { +dispatch_random(arc4ctx_t *actx) { isc_uint16_t result; if (actx->lock != NULL) @@ -543,9 +546,38 @@ dispatch_arc4random(arc4ctx_t *actx) { return (result); } +#else +/* + * For general purpose library, we don't have to be too strict about the + * quality of random values. Performance doesn't matter much, either. + * So we simply use the isc_random module to keep the library as small as + * possible. + */ + +static void +dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy, + isc_mutex_t *lock) +{ + UNUSED(actx); + UNUSED(entropy); + UNUSED(lock); + + return; +} static isc_uint16_t -dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { +dispatch_random(arc4ctx_t *actx) { + isc_uint32_t r; + + UNUSED(actx); + + isc_random_get(&r); + return (r & 0xffff); +} +#endif /* BIND9 */ + +static isc_uint16_t +dispatch_uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { isc_uint16_t min, r; if (upper_bound < 2) @@ -568,7 +600,7 @@ dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) { * to re-roll. */ for (;;) { - r = dispatch_arc4random(actx); + r = dispatch_random(actx); if (r >= min) break; } @@ -851,7 +883,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, */ localaddr = disp->local; for (i = 0; i < 64; i++) { - port = ports[dispatch_arc4uniformrandom(DISP_ARC4CTX(disp), + port = ports[dispatch_uniformrandom(DISP_ARC4CTX(disp), nports)]; isc_sockaddr_setport(&localaddr, port); @@ -956,6 +988,7 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { INSIST(dispsock->portentry != NULL); deref_portentry(disp, &dispsock->portentry); +#ifdef BIND9 if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) destroy_dispsocket(disp, &dispsock); else { @@ -979,6 +1012,13 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { destroy_dispsocket(disp, &dispsock); } } +#else + /* This kind of optimization isn't necessary for normal use */ + UNUSED(qid); + UNUSED(result); + + destroy_dispsocket(disp, &dispsock); +#endif } /* @@ -1704,8 +1744,10 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { DESTROYLOCK(&mgr->pool_lock); +#ifdef BIND9 if (mgr->entropy != NULL) isc_entropy_detach(&mgr->entropy); +#endif /* BIND9 */ if (mgr->qid != NULL) qid_destroy(mctx, &mgr->qid); @@ -1744,9 +1786,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, return (result); isc_socket_setname(sock, "dispatcher", NULL); } else { +#ifdef BIND9 result = isc_socket_open(sock); if (result != ISC_R_SUCCESS) return (result); +#else + INSIST(0); +#endif } #ifndef ISC_ALLOW_MAPPED @@ -1756,8 +1802,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, if (result != ISC_R_SUCCESS) { if (*sockp == NULL) isc_socket_detach(&sock); - else + else { +#ifdef BIND9 isc_socket_close(sock); +#else + INSIST(0); +#endif + } return (result); } @@ -1889,10 +1940,14 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, if (result != ISC_R_SUCCESS) goto kill_dpool; +#ifdef BIND9 if (entropy != NULL) isc_entropy_attach(entropy, &mgr->entropy); +#else + UNUSED(entropy); +#endif - dispatch_arc4init(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock); + dispatch_initrandom(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock); *mgrp = mgr; return (ISC_R_SUCCESS); @@ -2393,7 +2448,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, ISC_LIST_INIT(disp->activesockets); ISC_LIST_INIT(disp->inactivesockets); disp->nsockets = 0; - dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL); + dispatch_initrandom(&disp->arc4ctx, mgr->entropy, NULL); disp->port_table = NULL; disp->portpool = NULL; @@ -2690,7 +2745,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, for (i = 0; i < 1024; i++) { in_port_t prt; - prt = ports[dispatch_arc4uniformrandom( + prt = ports[dispatch_uniformrandom( DISP_ARC4CTX(disp), nports)]; isc_sockaddr_setport(&localaddr_bound, prt); @@ -2826,8 +2881,10 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, disp->task[i] = NULL; result = isc_task_create(taskmgr, 0, &disp->task[i]); if (result != ISC_R_SUCCESS) { - while (--i >= 0) - isc_task_destroy(&disp->task[i]); + while (--i >= 0) { + isc_task_shutdown(disp->task[i]); + isc_task_detach(&disp->task[i]); + } goto kill_socket; } isc_task_setname(disp->task[i], "udpdispatch", disp); @@ -3027,7 +3084,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, /* * Try somewhat hard to find an unique ID. */ - id = (dns_messageid_t)dispatch_arc4random(DISP_ARC4CTX(disp)); + id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); bucket = dns_hash(qid, dest, id, localport); ok = ISC_FALSE; for (i = 0; i < 64; i++) { diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 232fba7c0f..71fd242ca6 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: dst_api.c,v 1.26 2009/08/14 06:28:40 each Exp $ + * $Id: dst_api.c,v 1.27 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -69,7 +69,9 @@ #define DST_AS_STR(t) ((t).value.as_textregion.base) static dst_func_t *dst_t_func[DST_MAX_ALGS]; +#ifdef BIND9 static isc_entropy_t *dst_entropy_pool = NULL; +#endif static unsigned int dst_entropy_flags = 0; static isc_boolean_t dst_initialized = ISC_FALSE; @@ -126,7 +128,7 @@ static isc_result_t addsuffix(char *filename, unsigned int len, return (_r); \ } while (0); \ -#ifdef OPENSSL +#if defined(OPENSSL) && defined(BIND9) static void * default_memalloc(void *arg, size_t size) { UNUSED(arg); @@ -146,12 +148,17 @@ isc_result_t dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { isc_result_t result; - REQUIRE(mctx != NULL && ectx != NULL); + REQUIRE(mctx != NULL); +#ifdef BIND9 + REQUIRE(ectx != NULL); +#else + UNUSED(ectx); +#endif REQUIRE(dst_initialized == ISC_FALSE); dst__memory_pool = NULL; -#ifdef OPENSSL +#if defined(OPENSSL) && defined(BIND9) UNUSED(mctx); /* * When using --with-openssl, there seems to be no good way of not @@ -170,7 +177,9 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { #else isc_mem_attach(mctx, &dst__memory_pool); #endif +#ifdef BIND9 isc_entropy_attach(ectx, &dst_entropy_pool); +#endif dst_entropy_flags = eflags; dst_result_register(); @@ -218,9 +227,10 @@ dst_lib_destroy(void) { #endif if (dst__memory_pool != NULL) isc_mem_detach(&dst__memory_pool); +#ifdef BIND9 if (dst_entropy_pool != NULL) isc_entropy_detach(&dst_entropy_pool); - +#endif } isc_boolean_t @@ -1045,7 +1055,7 @@ dst_key_read_public(const char *filename, int type, isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); isc_buffer_add(&b, strlen(DST_AS_STR(token))); ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (ret != ISC_R_SUCCESS) goto cleanup; @@ -1397,13 +1407,25 @@ addsuffix(char *filename, unsigned int len, const char *odirname, isc_result_t dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { +#ifdef BIND9 unsigned int flags = dst_entropy_flags; if (pseudo) flags &= ~ISC_ENTROPY_GOODONLY; return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); +#else + UNUSED(buf); + UNUSED(len); + UNUSED(pseudo); + + return (ISC_R_NOTIMPLEMENTED); +#endif } unsigned int dst__entropy_status(void) { +#ifdef BIND9 return (isc_entropy_status(dst_entropy_pool)); +#else + return (0); +#endif } diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c new file mode 100644 index 0000000000..c8cee3af6d --- /dev/null +++ b/lib/dns/ecdb.c @@ -0,0 +1,797 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: ecdb.c,v 1.2 2009/09/01 00:22:26 jinmei Exp $ */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B') +#define VALID_ECDB(db) ((db) != NULL && \ + (db)->common.impmagic == ECDB_MAGIC) + +#define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N') +#define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC) + +#if DNS_RDATASET_FIXED +#error "Fixed rdataset isn't supported in this implementation" +#endif + +/*% + * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides + * temporary storage for ongoing name resolution with the common DB interfaces. + * It actually doesn't cache anything. The implementation expects any stored + * data is released within a short period, and does not care about the + * scalability in terms of the number of nodes. + */ + +typedef struct dns_ecdb { + /* Unlocked */ + dns_db_t common; + isc_mutex_t lock; + + /* Locked */ + unsigned int references; + ISC_LIST(struct dns_ecdbnode) nodes; +} dns_ecdb_t; + +typedef struct dns_ecdbnode { + /* Unlocked */ + unsigned int magic; + isc_mutex_t lock; + dns_ecdb_t *ecdb; + dns_name_t name; + ISC_LINK(struct dns_ecdbnode) link; + + /* Locked */ + ISC_LIST(struct rdatasetheader) rdatasets; + unsigned int references; +} dns_ecdbnode_t; + +typedef struct rdatasetheader { + dns_rdatatype_t type; + dns_ttl_t ttl; + dns_trust_t trust; + dns_rdatatype_t covers; + unsigned int attributes; + + ISC_LINK(struct rdatasetheader) link; +} rdatasetheader_t; + +/* Copied from rbtdb.c */ +#define RDATASET_ATTR_NXDOMAIN 0x0010 +#define NXDOMAIN(header) \ + (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0) + +static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, + dns_dbtype_t type, + dns_rdataclass_t rdclass, + unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp); + +static void rdataset_disassociate(dns_rdataset_t *rdataset); +static isc_result_t rdataset_first(dns_rdataset_t *rdataset); +static isc_result_t rdataset_next(dns_rdataset_t *rdataset); +static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); +static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target); +static unsigned int rdataset_count(dns_rdataset_t *rdataset); + +static dns_rdatasetmethods_t rdataset_methods = { + rdataset_disassociate, + rdataset_first, + rdataset_next, + rdataset_current, + rdataset_clone, + rdataset_count, + NULL, /* addnoqname */ + NULL, /* getnoqname */ + NULL, /* addclosest */ + NULL, /* getclosest */ + NULL, /* getadditional */ + NULL, /* setadditional */ + NULL /* putadditional */ +}; + +typedef struct ecdb_rdatasetiter { + dns_rdatasetiter_t common; + rdatasetheader_t *current; +} ecdb_rdatasetiter_t; + +static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); +static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator); +static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator); +static void rdatasetiter_current(dns_rdatasetiter_t *iterator, + dns_rdataset_t *rdataset); + +static dns_rdatasetitermethods_t rdatasetiter_methods = { + rdatasetiter_destroy, + rdatasetiter_first, + rdatasetiter_next, + rdatasetiter_current +}; + +isc_result_t +dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) { + REQUIRE(mctx != NULL); + REQUIRE(dbimp != NULL && *dbimp == NULL); + + return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp)); +} + +void +dns_ecdb_unregister(dns_dbimplementation_t **dbimp) { + REQUIRE(dbimp != NULL && *dbimp != NULL); + + dns_db_unregister(dbimp); +} + +/*% + * DB routines + */ + +static void +attach(dns_db_t *source, dns_db_t **targetp) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)source; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(targetp != NULL && *targetp == NULL); + + LOCK(&ecdb->lock); + ecdb->references++; + UNLOCK(&ecdb->lock); + + *targetp = source; +} + +static void +destroy_ecdb(dns_ecdb_t **ecdbp) { + dns_ecdb_t *ecdb = *ecdbp; + isc_mem_t *mctx = ecdb->common.mctx; + + if (dns_name_dynamic(&ecdb->common.origin)) + dns_name_free(&ecdb->common.origin, mctx); + + DESTROYLOCK(&ecdb->lock); + + ecdb->common.impmagic = 0; + ecdb->common.magic = 0; + + isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb)); + + *ecdbp = NULL; +} + +static void +detach(dns_db_t **dbp) { + dns_ecdb_t *ecdb; + isc_boolean_t need_destroy = ISC_FALSE; + + REQUIRE(dbp != NULL); + ecdb = (dns_ecdb_t *)*dbp; + REQUIRE(VALID_ECDB(ecdb)); + + LOCK(&ecdb->lock); + ecdb->references--; + if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) + need_destroy = ISC_TRUE; + UNLOCK(&ecdb->lock); + + if (need_destroy) + destroy_ecdb(&ecdb); + + *dbp = NULL; +} + +static void +attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *node = (dns_ecdbnode_t *)source; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(node)); + REQUIRE(targetp != NULL && *targetp == NULL); + + LOCK(&node->lock); + INSIST(node->references > 0); + node->references++; + INSIST(node->references != 0); /* Catch overflow. */ + UNLOCK(&node->lock); + + *targetp = node; +} + +static void +destroynode(dns_ecdbnode_t *node) { + isc_mem_t *mctx; + dns_ecdb_t *ecdb = node->ecdb; + isc_boolean_t need_destroydb = ISC_FALSE; + rdatasetheader_t *header; + + mctx = ecdb->common.mctx; + + LOCK(&ecdb->lock); + ISC_LIST_UNLINK(ecdb->nodes, node, link); + if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) + need_destroydb = ISC_TRUE; + UNLOCK(&ecdb->lock); + + dns_name_free(&node->name, mctx); + + while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) { + unsigned int headersize; + + ISC_LIST_UNLINK(node->rdatasets, header, link); + headersize = + dns_rdataslab_size((unsigned char *)header, + sizeof(*header)); + isc_mem_put(mctx, header, headersize); + } + + DESTROYLOCK(&node->lock); + + node->magic = 0; + isc_mem_put(mctx, node, sizeof(*node)); + + if (need_destroydb) + destroy_ecdb(&ecdb); +} + +static void +detachnode(dns_db_t *db, dns_dbnode_t **nodep) { + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *node; + isc_boolean_t need_destroy = ISC_FALSE; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(nodep != NULL); + node = (dns_ecdbnode_t *)*nodep; + REQUIRE(VALID_ECDBNODE(node)); + + UNUSED(ecdb); /* in case REQUIRE() is empty */ + + LOCK(&node->lock); + INSIST(node->references > 0); + node->references--; + if (node->references == 0) + need_destroy = ISC_TRUE; + UNLOCK(&node->lock); + + if (need_destroy) + destroynode(node); + + *nodep = NULL; +} + +static isc_result_t +find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + + REQUIRE(VALID_ECDB(ecdb)); + + UNUSED(name); + UNUSED(version); + UNUSED(type); + UNUSED(options); + UNUSED(now); + UNUSED(nodep); + UNUSED(foundname); + UNUSED(rdataset); + UNUSED(sigrdataset); + + return (ISC_R_NOTFOUND); +} + +static isc_result_t +findzonecut(dns_db_t *db, dns_name_t *name, + unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + + REQUIRE(VALID_ECDB(ecdb)); + + UNUSED(name); + UNUSED(options); + UNUSED(now); + UNUSED(nodep); + UNUSED(foundname); + UNUSED(rdataset); + UNUSED(sigrdataset); + + return (ISC_R_NOTFOUND); +} + +static isc_result_t +findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + isc_mem_t *mctx; + dns_ecdbnode_t *node; + isc_result_t result; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(nodep != NULL && *nodep == NULL); + + UNUSED(name); + + if (create != ISC_TRUE) { + /* an 'ephemeral' node is never reused. */ + return (ISC_R_NOTFOUND); + } + + mctx = ecdb->common.mctx; + node = isc_mem_get(mctx, sizeof(*node)); + if (node == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&node->lock); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_mutex_init() failed: %s", + isc_result_totext(result)); + isc_mem_put(mctx, node, sizeof(*node)); + return (ISC_R_UNEXPECTED); + } + + dns_name_init(&node->name, NULL); + result = dns_name_dup(name, mctx, &node->name); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&node->lock); + isc_mem_put(mctx, node, sizeof(*node)); + return (result); + } + node->ecdb= ecdb; + node->references = 1; + ISC_LIST_INIT(node->rdatasets); + + ISC_LINK_INIT(node, link); + + LOCK(&ecdb->lock); + ISC_LIST_APPEND(ecdb->nodes, node, link); + UNLOCK(&ecdb->lock); + + node->magic = ECDBNODE_MAGIC; + + *nodep = node; + + return (ISC_R_SUCCESS); +} + +static void +bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node, + rdatasetheader_t *header, dns_rdataset_t *rdataset) +{ + unsigned char *raw; + + /* + * Caller must be holding the node lock. + */ + + REQUIRE(!dns_rdataset_isassociated(rdataset)); + + rdataset->methods = &rdataset_methods; + rdataset->rdclass = ecdb->common.rdclass; + rdataset->type = header->type; + rdataset->covers = header->covers; + rdataset->ttl = header->ttl; + rdataset->trust = header->trust; + if (NXDOMAIN(header)) + rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN; + + rdataset->private1 = ecdb; + rdataset->private2 = node; + raw = (unsigned char *)header + sizeof(*header); + rdataset->private3 = raw; + rdataset->count = 0; + + /* + * Reset iterator state. + */ + rdataset->privateuint4 = 0; + rdataset->private5 = NULL; + + INSIST(node->references > 0); + node->references++; +} + +static isc_result_t +addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, + dns_rdataset_t *addedrdataset) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + isc_region_t r; + isc_result_t result = ISC_R_SUCCESS; + isc_mem_t *mctx; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; + rdatasetheader_t *header; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(ecdbnode)); + + UNUSED(version); + UNUSED(now); + UNUSED(options); + + mctx = ecdb->common.mctx; + + LOCK(&ecdbnode->lock); + + /* + * Sanity check: this implementation does not allow overriding an + * existing rdataset of the same type. + */ + for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL; + header = ISC_LIST_NEXT(header, link)) { + INSIST(header->type != rdataset->type || + header->covers != rdataset->covers); + } + + result = dns_rdataslab_fromrdataset(rdataset, mctx, + &r, sizeof(rdatasetheader_t)); + if (result != ISC_R_SUCCESS) + goto unlock; + + header = (rdatasetheader_t *)r.base; + header->type = rdataset->type; + header->ttl = rdataset->ttl; + header->trust = rdataset->trust; + header->covers = rdataset->covers; + header->attributes = 0; + if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) + header->attributes |= RDATASET_ATTR_NXDOMAIN; + ISC_LINK_INIT(header, link); + ISC_LIST_APPEND(ecdbnode->rdatasets, header, link); + + if (addedrdataset == NULL) + goto unlock; + + bind_rdataset(ecdb, ecdbnode, header, addedrdataset); + + unlock: + UNLOCK(&ecdbnode->lock); + + return (result); +} + +static isc_result_t +deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers) +{ + UNUSED(db); + UNUSED(node); + UNUSED(version); + UNUSED(type); + UNUSED(covers); + + return (ISC_R_NOTIMPLEMENTED); +} + +static isc_result_t +createiterator(dns_db_t *db, isc_boolean_t relative_names, + dns_dbiterator_t **iteratorp) +{ + UNUSED(db); + UNUSED(relative_names); + UNUSED(iteratorp); + + return (ISC_R_NOTIMPLEMENTED); +} + +static isc_result_t +allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) +{ + dns_ecdb_t *ecdb = (dns_ecdb_t *)db; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node; + isc_mem_t *mctx; + ecdb_rdatasetiter_t *iterator; + + REQUIRE(VALID_ECDB(ecdb)); + REQUIRE(VALID_ECDBNODE(ecdbnode)); + + mctx = ecdb->common.mctx; + + iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t)); + if (iterator == NULL) + return (ISC_R_NOMEMORY); + + iterator->common.magic = DNS_RDATASETITER_MAGIC; + iterator->common.methods = &rdatasetiter_methods; + iterator->common.db = db; + iterator->common.node = NULL; + attachnode(db, node, &iterator->common.node); + iterator->common.version = version; + iterator->common.now = now; + + *iteratorp = (dns_rdatasetiter_t *)iterator; + + return (ISC_R_SUCCESS); +} + +static dns_dbmethods_t ecdb_methods = { + attach, + detach, + NULL, /* beginload */ + NULL, /* endload */ + NULL, /* dump */ + NULL, /* currentversion */ + NULL, /* newversion */ + NULL, /* attachversion */ + NULL, /* closeversion */ + findnode, + find, + findzonecut, + attachnode, + detachnode, + NULL, /* expirenode */ + NULL, /* printnode */ + createiterator, /* createiterator */ + NULL, /* findrdataset */ + allrdatasets, + addrdataset, + NULL, /* subtractrdataset */ + deleterdataset, + NULL, /* issecure */ + NULL, /* nodecount */ + NULL, /* ispersistent */ + NULL, /* overmem */ + NULL, /* settask */ + NULL, /* getoriginnode */ + NULL, /* transfernode */ + NULL, /* getnsec3parameters */ + NULL, /* findnsec3node */ + NULL, /* setsigningtime */ + NULL, /* getsigningtime */ + NULL, /* resigned */ + NULL, /* isdnssec */ + NULL /* getrrsetstats */ +}; + +static isc_result_t +dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, + dns_rdataclass_t rdclass, unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp) +{ + dns_ecdb_t *ecdb; + isc_result_t result; + + REQUIRE(mctx != NULL); + REQUIRE(origin == dns_rootname); + REQUIRE(type == dns_dbtype_cache); + REQUIRE(dbp != NULL && *dbp == NULL); + + UNUSED(argc); + UNUSED(argv); + UNUSED(driverarg); + + ecdb = isc_mem_get(mctx, sizeof(*ecdb)); + if (ecdb == NULL) + return (ISC_R_NOMEMORY); + + ecdb->common.attributes = DNS_DBATTR_CACHE; + ecdb->common.rdclass = rdclass; + ecdb->common.methods = &ecdb_methods; + dns_name_init(&ecdb->common.origin, NULL); + result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, ecdb, sizeof(*ecdb)); + return (result); + } + + result = isc_mutex_init(&ecdb->lock); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_mutex_init() failed: %s", + isc_result_totext(result)); + if (dns_name_dynamic(&ecdb->common.origin)) + dns_name_free(&ecdb->common.origin, mctx); + isc_mem_put(mctx, ecdb, sizeof(*ecdb)); + return (ISC_R_UNEXPECTED); + } + + ecdb->references = 1; + ISC_LIST_INIT(ecdb->nodes); + + ecdb->common.mctx = NULL; + isc_mem_attach(mctx, &ecdb->common.mctx); + ecdb->common.impmagic = ECDB_MAGIC; + ecdb->common.magic = DNS_DB_MAGIC; + + *dbp = (dns_db_t *)ecdb; + + return (ISC_R_SUCCESS); +} + +/*% + * Rdataset Methods + */ + +static void +rdataset_disassociate(dns_rdataset_t *rdataset) { + dns_db_t *db = rdataset->private1; + dns_dbnode_t *node = rdataset->private2; + + dns_db_detachnode(db, &node); +} + +static isc_result_t +rdataset_first(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + if (count == 0) { + rdataset->private5 = NULL; + return (ISC_R_NOMORE); + } + raw += 2; + /* + * The privateuint4 field is the number of rdata beyond the cursor + * position, so we decrement the total count by one before storing + * it. + */ + count--; + rdataset->privateuint4 = count; + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +rdataset_next(dns_rdataset_t *rdataset) { + unsigned int count; + unsigned int length; + unsigned char *raw; + + count = rdataset->privateuint4; + if (count == 0) + return (ISC_R_NOMORE); + count--; + rdataset->privateuint4 = count; + raw = rdataset->private5; + length = raw[0] * 256 + raw[1]; + raw += length + 2; + rdataset->private5 = raw; + + return (ISC_R_SUCCESS); +} + +static void +rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { + unsigned char *raw = rdataset->private5; + isc_region_t r; + unsigned int length; + unsigned int flags = 0; + + REQUIRE(raw != NULL); + + length = raw[0] * 256 + raw[1]; + raw += 2; + if (rdataset->type == dns_rdatatype_rrsig) { + if (*raw & DNS_RDATASLAB_OFFLINE) + flags |= DNS_RDATA_OFFLINE; + length--; + raw++; + } + r.length = length; + r.base = raw; + dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r); + rdata->flags |= flags; +} + +static void +rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { + dns_db_t *db = source->private1; + dns_dbnode_t *node = source->private2; + dns_dbnode_t *cloned_node = NULL; + + attachnode(db, node, &cloned_node); + *target = *source; + + /* + * Reset iterator state. + */ + target->privateuint4 = 0; + target->private5 = NULL; +} + +static unsigned int +rdataset_count(dns_rdataset_t *rdataset) { + unsigned char *raw = rdataset->private3; + unsigned int count; + + count = raw[0] * 256 + raw[1]; + + return (count); +} + +/* + * Rdataset Iterator Methods + */ + +static void +rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { + ecdb_rdatasetiter_t *ecdbiterator; + isc_mem_t *mctx; + + REQUIRE(iteratorp != NULL); + ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp; + REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common)); + + mctx = ecdbiterator->common.db->mctx; + + ecdbiterator->common.magic = 0; + + dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node); + isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t)); + + *iteratorp = NULL; +} + +static isc_result_t +rdatasetiter_first(dns_rdatasetiter_t *iterator) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node; + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + if (ISC_LIST_EMPTY(ecdbnode->rdatasets)) + return (ISC_R_NOMORE); + ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets); + return (ISC_R_SUCCESS); +} + +static isc_result_t +rdatasetiter_next(dns_rdatasetiter_t *iterator) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + + REQUIRE(DNS_RDATASETITER_VALID(iterator)); + + ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link); + if (ecdbiterator->current == NULL) + return (ISC_R_NOMORE); + else + return (ISC_R_SUCCESS); +} + +static void +rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { + ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; + dns_ecdb_t *ecdb; + + ecdb = (dns_ecdb_t *)iterator->db; + REQUIRE(VALID_ECDB(ecdb)); + + bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset); +} diff --git a/lib/dns/forward.c b/lib/dns/forward.c index 39e2ef5df0..bc1a94bd33 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: forward.c,v 1.12 2007/06/19 23:47:16 tbox Exp $ */ +/* $Id: forward.c,v 1.13 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -132,6 +132,22 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name, return (result); } +isc_result_t +dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name) { + isc_result_t result; + + REQUIRE(VALID_FWDTABLE(fwdtable)); + + RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE); + RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); + + if (result == DNS_R_PARTIALMATCH) + result = ISC_R_NOTFOUND; + + return (result); +} + isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_forwarders_t **forwardersp) diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c index 11eadb9675..6f2e3b0783 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gssapictx.c,v 1.12 2008/04/03 06:09:04 tbox Exp $ */ +/* $Id: gssapictx.c,v 1.13 2009/09/01 00:22:26 jinmei Exp $ */ #include @@ -630,7 +630,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, isc_buffer_add(&namebuf, r.length); RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname, - ISC_FALSE, NULL)); + 0, NULL)); if (gnamebuf.length != 0) { gret = gss_release_buffer(&minor, &gnamebuf); diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h new file mode 100644 index 0000000000..4017528dc1 --- /dev/null +++ b/lib/dns/include/dns/client.h @@ -0,0 +1,621 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: client.h,v 1.2 2009/09/01 00:22:26 jinmei Exp $ */ + +#ifndef DNS_CLIENT_H +#define DNS_CLIENT_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file + * + * \brief + * The DNS client module provides convenient programming interfaces to various + * DNS services, such as name resolution with or without DNSSEC validation or + * dynamic DNS update. This module is primarily expected to be used by other + * applications than BIND9-related ones that need such advanced DNS features. + * + * MP: + *\li In the typical usage of this module, application threads will not share + * the same data structures created and manipulated in this module. + * However, the module still ensures appropriate synchronization of such + * data structures. + * + * Resources: + *\li TBS + * + * Security: + *\li This module does not handle any low-level data directly, and so no + * security issue specific to this module is anticipated. + */ + +#include +#include + +#include +#include + +#include + +typedef enum { + updateop_none = 0, + updateop_add = 1, + updateop_delete = 2, + updateop_exist = 3, + updateop_notexist = 4, + updateop_max = 5 +} dns_client_updateop_t; + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*% + * Optional flags for dns_client_create(x). + */ +/*%< Enable caching resolution results (experimental). */ +#define DNS_CLIENTCREATEOPT_USECACHE 0x8000 + +/*% + * Optional flags for dns_client_(start)resolve. + */ +/*%< Disable DNSSEC validation. */ +#define DNS_CLIENTRESOPT_NODNSSEC 0x01 +/*%< Allow running external context. */ +#define DNS_CLIENTRESOPT_ALLOWRUN 0x02 + +/*% + * Optional flags for dns_client_(start)request. + */ +/*%< Allow running external context. */ +#define DNS_CLIENTREQOPT_ALLOWRUN 0x01 + +/*% + * A dns_clientresevent_t is sent when name resolution performed by a client + * completes. 'result' stores the result code of the entire resolution + * procedure. 'vresult' specifically stores the result code of DNSSEC + * validation if it is performed. When name resolution successfully completes, + * 'answerlist' is typically non empty, containing answer names along with + * RRsets. It is the receiver's responsibility to free this list by calling + * dns_client_freeresanswer() before freeing the event structure. + */ +typedef struct dns_clientresevent { + ISC_EVENT_COMMON(struct dns_clientresevent); + isc_result_t result; + isc_result_t vresult; + dns_namelist_t answerlist; +} dns_clientresevent_t; /* too long? */ + +/*% + * Status of a dynamic update procedure. + */ +typedef enum { + dns_clientupdatestate_prepare, /*%< no updates have been sent */ + dns_clientupdatestate_sent, /*%< updates were sent, no response */ + dns_clientupdatestate_done /*%< update was sent and succeeded */ +} dns_clientupdatestate_t; + +/*% + * A dns_clientreqevent_t is sent when a DNS request is completed by a client. + * 'result' stores the result code of the entire transaction. + * If the transaction is successfully completed but the response packet cannot + * be parsed, 'result' will store the result code of dns_message_parse(). + * If the response packet is received, 'rmessage' will contain the response + * message, whether it is successfully parsed or not. + */ +typedef struct dns_clientreqevent { + ISC_EVENT_COMMON(struct dns_clientreqevent); + isc_result_t result; + dns_message_t *rmessage; +} dns_clientreqevent_t; /* too long? */ + +/*% + * A dns_clientupdateevent_t is sent when dynamic update performed by a client + * completes. 'result' stores the result code of the entire update procedure. + * 'state' specifies the status of the update procedure when this event is + * sent. This can be used as a hint by the receiver to determine whether + * the update attempt was ever made. In particular, if the state is + * dns_clientupdatestate_prepare, the receiver can be sure that the requested + * update was not applied. + */ +typedef struct dns_clientupdateevent { + ISC_EVENT_COMMON(struct dns_clientupdateevent); + isc_result_t result; + dns_clientupdatestate_t state; +} dns_clientupdateevent_t; /* too long? */ + +isc_result_t +dns_client_create(dns_client_t **clientp, unsigned int options); + +isc_result_t +dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, + isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, + unsigned int options, dns_client_t **clientp); +/*%< + * Create a DNS client. These functions create a new client object with + * minimal internal resources such as the default 'view' for the IN class and + * IPv4/IPv6 dispatches for the view. + * + * dns_client_createx() takes 'manager' arguments so that the caller can + * control the behavior of the client through the underlying event framework. + * On the other hand, dns_client_create() simplifies the interface and creates + * the managers internally. A DNS client object created via + * dns_client_create() is expected to be used by an application that only needs + * simple synchronous services or by a thread-based application. + * + * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options', + * dns_client_create(x) will create a cache database with the view. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'actx' is a valid application context. + * + *\li 'taskmgr' is a valid task manager. + * + *\li 'socketmgr' is a valid socket manager. + * + *\li 'timermgr' is a valid timer manager. + * + *\li clientp != NULL && *clientp == NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_destroy(dns_client_t **clientp); +/*%< + * Destroy 'client'. + * + * Requires: + * + *\li '*clientp' is a valid client. + * + * Ensures: + * + *\li *clientp == NULL. + */ + +isc_result_t +dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace, isc_sockaddrlist_t *addrs); +/*%< + * Specify a list of addresses of recursive name servers that the client will + * use for name resolution. A view for the 'rdclass' class must be created + * beforehand. If 'namespace' is non NULL, the specified server will be used + * if and only if the query name is a subdomain of 'namespace'. When servers + * for multiple 'namespace's are provided, and a query name is covered by + * more than one 'namespace', the servers for the best (longest) matching + * namespace will be used. If 'namespace' is NULL, it works as if + * dns_rootname (.) were specified. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namespace' is NULL or a valid name. + * + *\li 'addrs' != NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *namespace); +/*%< + * Remove configured recursive name servers for the 'rdclass' and 'namespace' + * from the client. See the description of dns_client_setservers() for + * the requirements about 'rdclass' and 'namespace'. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namespace' is NULL or a valid name. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_resolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, dns_namelist_t *namelist); + +isc_result_t +dns_client_startresolve(dns_client_t *client, dns_name_t *name, + dns_rdataclass_t rdclass, dns_rdatatype_t type, + unsigned int options, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_clientrestrans_t **transp); +/*%< + * Perform name resolution for 'name', 'rdclass', and 'type'. + * + * If any trusted keys are configured and the query name is considered to + * belong to a secure zone, these functions also validate the responses + * using DNSSEC by default. If the DNS_CLIENTRESOPT_NODNSSEC flag is set + * in 'options', DNSSEC validation is disabled regardless of the configured + * trusted keys or the query name. + * + * dns_client_resolve() provides a synchronous service. This function starts + * name resolution internally and blocks until it completes. On success, + * 'namelist' will contain a list of answer names, each of which has + * corresponding RRsets. The caller must provide a valid empty list, and + * is responsible for freeing the list content via dns_client_freeresanswer(). + * If the name resolution fails due to an error in DNSSEC validation, + * dns_client_resolve() returns the result code indicating the validation + * error. Otherwise, it returns the result code of the entire resolution + * process, either success or failure. + * + * It is typically expected that the client object passed to + * dns_client_resolve() was created via dns_client_create() and has its own + * managers and contexts. However, if the DNS_CLIENTRESOPT_ALLOWRUN flag is + * set in 'options', this function performs the synchronous service even if + * it does not have its own manager and context structures. + * + * dns_client_startresolve() is an asynchronous version of dns_client_resolve() + * and does not block. When name resolution is completed, 'action' will be + * called with the argument of a 'dns_clientresevent_t' object, which contains + * the resulting list of answer names (on success). On return, '*transp' is + * set to an opaque transaction ID so that the caller can cancel this + * resolution process. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'addrs' != NULL. + * + *\li 'name' is a valid name. + * + *\li 'namelist' != NULL and is not empty. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_cancelresolve(dns_clientrestrans_t *trans); +/*%< + * Cancel an ongoing resolution procedure started via + * dns_client_startresolve(). + * + * Notes: + * + *\li If the resolution procedure has not completed, post its CLIENTRESDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyrestrans(dns_clientrestrans_t **transp); +/*%< + * Destroy name resolution transaction state identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the CLIENTRESDONE event (either because the + * resolution completed or because dns_client_cancelresolve() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +void +dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist); +/*%< + * Free resources allocated for the content of 'namelist'. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'namelist' != NULL. + */ + +isc_result_t +dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *keyname, isc_buffer_t *keydatabuf); +/*%< + * Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass' + * class must be created beforehand. 'keyname' is the DNS name of the key, + * and 'keydatabuf' stores the resource data of the key. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'keyname' is a valid name. + * + *\li 'keydatabuf' is a valid buffer. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +isc_result_t +dns_client_request(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries); + +isc_result_t +dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage, + dns_message_t *rmessage, isc_sockaddr_t *server, + unsigned int options, unsigned int parseoptions, + dns_tsec_t *tsec, unsigned int timeout, + unsigned int udptimeout, unsigned int udpretries, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientreqtrans_t **transp); + +/*%< + * Send a DNS request containig a query message 'query' to 'server'. + * + * 'parseoptions' will be used when the response packet is parsed, and will be + * passed to dns_message_parse() via dns_request_getresponse(). See + * dns_message_parse() for more details. + * + * 'tsec' is a transaction security object containing, e.g. a TSIG key for + * authenticating the request/response transaction. This is optional and can + * be NULL, in which case this library performs the transaction without any + * transaction authentication. + * + * 'timeout', 'udptimeout', and 'udpretries' are passed to + * dns_request_createvia3(). See dns_request_createvia3() for more details. + * + * dns_client_request() provides a synchronous service. This function sends + * the request and blocks until a response is received. On success, + * 'rmessage' will contain the response message. The caller must provide a + * valid initialized message. + * + * It is usually expected that the client object passed to + * dns_client_request() was created via dns_client_create() and has its own + * managers and contexts. However, if the DNS_CLIENTREQOPT_ALLOWRUN flag is + * set in 'options', this function performs the synchronous service even if + * it does not have its own manager and context structures. + * + * dns_client_startrequest() is an asynchronous version of dns_client_request() + * and does not block. When the transaction is completed, 'action' will be + * called with the argument of a 'dns_clientreqevent_t' object, which contains + * the response message (on success). On return, '*transp' is set to an opaque + * transaction ID so that the caller can cancel this request. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'qmessage' and 'rmessage' are valid initialized message. + * + *\li 'server' is a valid socket address structure. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + * + *\li Any result that dns_message_parse() can return. + */ + +void +dns_client_cancelrequest(dns_clientreqtrans_t *transp); +/*%< + * Cancel an ongoing DNS request procedure started via + * dns_client_startrequest(). + * + * Notes: + * + *\li If the request procedure has not completed, post its CLIENTREQDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyreqtrans(dns_clientreqtrans_t **transp); +/*% + * Destroy DNS request transaction state identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the CLIENTREQDONE event (either because the + * request completed or because dns_client_cancelrequest() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +isc_result_t +dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options); + +isc_result_t +dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, + dns_name_t *zonename, dns_namelist_t *prerequisites, + dns_namelist_t *updates, isc_sockaddrlist_t *servers, + dns_tsec_t *tsec, unsigned int options, + isc_task_t *task, isc_taskaction_t action, void *arg, + dns_clientupdatetrans_t **transp); +/*%< + * Perform DNS dynamic update for 'updates' of the 'rdclass' class with + * optional 'prerequisites'. + * + * 'updates' are a list of names with associated RRsets to be updated. + * + * 'prerequisites' are a list of names with associated RRsets corresponding to + * the prerequisites of the updates. This is optional and can be NULL, in + * which case the prerequisite section of the update message will be empty. + * + * Both 'updates' and 'prerequisites' must be constructed as specified in + * RFC2136. + * + * 'zonename' is the name of the zone in which the updated names exist. + * This is optional and can be NULL. In this case, these functions internally + * identify the appropriate zone through some queries for the SOA RR starting + * with the first name in prerequisites or updates. + * + * 'servers' is a list of authoritative servers to which the update message + * should be sent. This is optional and can be NULL. In this case, these + * functions internally identify the appropriate primary server name and its + * addresses through some queries for the SOA RR (like the case of zonename) + * and supplemental A/AAAA queries for the server name. + * Note: The client module generally assumes the given addresses are of the + * primary server of the corresponding zone. It will work even if a secondary + * server address is specified as long as the server allows update forwarding, + * it is generally discouraged to include secondary server addresses unless + * there's strong reason to do so. + * + * 'tsec' is a transaction security object containing, e.g. a TSIG key for + * authenticating the update transaction (and the supplemental query/response + * transactions if the server is specified). This is optional and can be + * NULL, in which case the library tries the update without any transaction + * authentication. + * + * dns_client_update() provides a synchronous service. This function blocks + * until the entire update procedure completes, including the additional + * queries when necessary. + * + * dns_client_startupdate() is an asynchronous version of dns_client_update(). + * It immediately returns (typically with *transp being set to a non-NULL + * pointer), and performs the update procedure through a set of internal + * events. All transactions including the additional query exchanges are + * performed as a separate event, so none of these events cause blocking + * operation. When the update procedure completes, the specified function + * 'action' will be called with the argument of a 'dns_clientupdateevent_t' + * structure. On return, '*transp' is set to an opaque transaction ID so that + * the caller can cancel this update process. + * + * Notes: + *\li No options are currently defined. + * + * Requires: + * + *\li 'client' is a valid client. + * + *\li 'updates' != NULL. + * + *\li 'task' is a valid task. + * + *\li 'transp' != NULL && *transp == NULL; + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_client_cancelupdate(dns_clientupdatetrans_t *trans); +/*%< + * Cancel an ongoing dynamic update procedure started via + * dns_client_startupdate(). + * + * Notes: + * + *\li If the update procedure has not completed, post its UPDATEDONE + * event with a result code of #ISC_R_CANCELED. + * + * Requires: + * + *\li 'trans' is a valid transaction ID. + */ + +void +dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp); +/*%< + * Destroy dynamic update transaction identified by '*transp'. + * + * Requires: + * + *\li '*transp' is a valid transaction ID. + * + *\li The caller has received the UPDATEDONE event (either because the + * update completed or because dns_client_cancelupdate() was called). + * + * Ensures: + * + *\li *transp == NULL. + */ + +isc_result_t +dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner, + dns_rdatatype_t type, dns_rdata_t *source, + dns_ttl_t ttl, dns_name_t *target, + dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist, + dns_rdata_t *rdata, isc_mem_t *mctx); +/*%< + * TBD + */ + +void +dns_client_freeupdate(dns_name_t **namep); +/*%< + * TBD + */ + +isc_mem_t * +dns_client_mctx(dns_client_t *client); + +ISC_LANG_ENDDECLS + +#endif /* DNS_CLIENT_H */ diff --git a/lib/dns/include/dns/ecdb.h b/lib/dns/include/dns/ecdb.h new file mode 100644 index 0000000000..8d638d6f63 --- /dev/null +++ b/lib/dns/include/dns/ecdb.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: ecdb.h,v 1.2 2009/09/01 00:22:26 jinmei Exp $ */ + +#ifndef DNS_ECDB_H +#define DNS_ECDB_H 1 + +/***** + ***** Module Info + *****/ + +/* TBD */ + +/*** + *** Imports + ***/ + +#include + +/*** + *** Types + ***/ + +/*** + *** Functions + ***/ + +/* TBD: describe those */ + +isc_result_t +dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp); + +void +dns_ecdb_unregister(dns_dbimplementation_t **dbimp); + +ISC_LANG_ENDDECLS + +#endif /* DNS_ECDB_H */ diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index ec4aee0185..c92f44be02 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: events.h,v 1.52 2009/06/30 02:52:32 each Exp $ */ +/* $Id: events.h,v 1.53 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -70,6 +70,8 @@ #define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40) #define DNS_EVENT_RBTPRUNE (ISC_EVENTCLASS_DNS + 41) #define DNS_EVENT_MANAGEKEYS (ISC_EVENTCLASS_DNS + 42) +#define DNS_EVENT_CLIENTRESDONE (ISC_EVENTCLASS_DNS + 43) +#define DNS_EVENT_CLIENTREQDONE (ISC_EVENTCLASS_DNS + 44) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h index 512c5e3c6e..fa5a10c31d 100644 --- a/lib/dns/include/dns/forward.h +++ b/lib/dns/include/dns/forward.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: forward.h,v 1.11 2007/06/19 23:47:16 tbox Exp $ */ +/* $Id: forward.h,v 1.12 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_FORWARD_H #define DNS_FORWARD_H 1 @@ -66,6 +66,21 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name, * \li #ISC_R_NOMEMORY */ +isc_result_t +dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name); +/*%< + * Removes an entry for 'name' from the forwarding table. If an entry + * that exactly matches 'name' does not exist, ISC_R_NOTFOUND will be returned. + * + * Requires: + * \li fwdtable is a valid forwarding table. + * \li name is a valid name + * + * Returns: + * \li #ISC_R_SUCCESS + * \li #ISC_R_NOTFOUND + */ + isc_result_t dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_forwarders_t **forwardersp); diff --git a/lib/dns/include/dns/lib.h b/lib/dns/include/dns/lib.h index fd3325b940..49c12c7c78 100644 --- a/lib/dns/include/dns/lib.h +++ b/lib/dns/include/dns/lib.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: lib.h,v 1.17 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_LIB_H #define DNS_LIB_H 1 @@ -40,6 +40,20 @@ dns_lib_initmsgcat(void); * has not already been initialized. */ +isc_result_t +dns_lib_init(void); +/*%< + * A set of initialization procedure used in the DNS library. This function + * is provided for an application that is not aware of the underlying ISC or + * DNS libraries much. + */ + +void +dns_lib_shutdown(void); +/*%< + * Free temporary resources allocated in dns_lib_init(). + */ + ISC_LANG_ENDDECLS #endif /* DNS_LIB_H */ diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index c499e5a239..044b0103dd 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.h,v 1.127 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: message.h,v 1.128 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_MESSAGE_H #define DNS_MESSAGE_H 1 @@ -81,8 +81,7 @@ * name = NULL; * name = dns_message_gettempname(message, &name); * dns_name_init(name, NULL); - * result = dns_name_fromtext(name, &source, dns_rootname, ISC_FALSE, - * buffer); + * result = dns_name_fromtext(name, &source, dns_rootname, 0, buffer); * dns_message_takebuffer(message, &buffer); * \endcode * diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index 4c6c523112..bd81d037ad 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.h,v 1.130 2009/06/30 02:52:32 each Exp $ */ +/* $Id: name.h,v 1.131 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_NAME_H #define DNS_NAME_H 1 @@ -127,21 +127,27 @@ struct dns_name { #define DNS_NAME_MAGIC ISC_MAGIC('D','N','S','n') -#define DNS_NAMEATTR_ABSOLUTE 0x0001 -#define DNS_NAMEATTR_READONLY 0x0002 -#define DNS_NAMEATTR_DYNAMIC 0x0004 -#define DNS_NAMEATTR_DYNOFFSETS 0x0008 -#define DNS_NAMEATTR_NOCOMPRESS 0x0010 +#define DNS_NAMEATTR_ABSOLUTE 0x00000001 +#define DNS_NAMEATTR_READONLY 0x00000002 +#define DNS_NAMEATTR_DYNAMIC 0x00000004 +#define DNS_NAMEATTR_DYNOFFSETS 0x00000008 +#define DNS_NAMEATTR_NOCOMPRESS 0x00000010 /* * Attributes below 0x0100 reserved for name.c usage. */ -#define DNS_NAMEATTR_CACHE 0x0100 /*%< Used by resolver. */ -#define DNS_NAMEATTR_ANSWER 0x0200 /*%< Used by resolver. */ -#define DNS_NAMEATTR_NCACHE 0x0400 /*%< Used by resolver. */ -#define DNS_NAMEATTR_CHAINING 0x0800 /*%< Used by resolver. */ -#define DNS_NAMEATTR_CHASE 0x1000 /*%< Used by resolver. */ -#define DNS_NAMEATTR_WILDCARD 0x2000 /*%< Used by server. */ +#define DNS_NAMEATTR_CACHE 0x00000100 /*%< Used by resolver. */ +#define DNS_NAMEATTR_ANSWER 0x00000200 /*%< Used by resolver. */ +#define DNS_NAMEATTR_NCACHE 0x00000400 /*%< Used by resolver. */ +#define DNS_NAMEATTR_CHAINING 0x00000800 /*%< Used by resolver. */ +#define DNS_NAMEATTR_CHASE 0x00001000 /*%< Used by resolver. */ +#define DNS_NAMEATTR_WILDCARD 0x00002000 /*%< Used by server. */ +#define DNS_NAMEATTR_PREREQUISITE 0x00004000 /*%< Used by client. */ +#define DNS_NAMEATTR_UPDATE 0x00008000 /*%< Used by client. */ +#define DNS_NAMEATTR_HASUPDATEREC 0x00010000 /*%< Used by client. */ +/* + * Various flags. + */ #define DNS_NAME_DOWNCASE 0x0001 #define DNS_NAME_CHECKNAMES 0x0002 /*%< Used by rdata. */ #define DNS_NAME_CHECKNAMESFAIL 0x0004 /*%< Used by rdata. */ @@ -1294,6 +1300,13 @@ dns_name_destroy(void); * non-NULL argument prior to calling dns_name_destroy(); */ +isc_result_t +dns_name_fromstr(dns_name_t *name, const char *source, const char *origin, + unsigned int options, isc_buffer_t *target); +/*%< + * TBD + */ + ISC_LANG_ENDDECLS /* diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 7b1d7f2c5e..6051752cb0 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.h,v 1.73 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: rdata.h,v 1.74 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_RDATA_H #define DNS_RDATA_H 1 @@ -95,6 +95,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -698,6 +699,21 @@ dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad); * 'bad' to be NULL or valid. */ +void +dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type); + +void +dns_rdata_makedelete(dns_rdata_t *rdata); + +const char * +dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section); + ISC_LANG_ENDDECLS #endif /* DNS_RDATA_H */ diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 04a7a1e0a5..bdf4c64333 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.h,v 1.63 2009/01/27 22:29:59 jinmei Exp $ */ +/* $Id: resolver.h,v 1.64 2009/09/01 00:22:26 jinmei Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -81,6 +81,7 @@ typedef struct dns_fetchevent { dns_fixedname_t foundname; isc_sockaddr_t * client; dns_messageid_t id; + isc_result_t vresult; } dns_fetchevent_t; /* diff --git a/lib/dns/include/dns/tsec.h b/lib/dns/include/dns/tsec.h new file mode 100644 index 0000000000..2d85e4b0a0 --- /dev/null +++ b/lib/dns/include/dns/tsec.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: tsec.h,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#ifndef DNS_TSEC_H +#define DNS_TSEC_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file + * + * \brief + * The TSEC (Transaction Security) module is an abstraction layer for managing + * DNS transaction mechanisms such as TSIG or SIG(0). A TSEC structure is a + * mechanism-independent object containing key information specific to the + * mechanism, and is expected to be used as an argument to other modules + * that use transaction security in a mechanism-independent manner. + * + * MP: + *\li A TSEC structure is expected to be thread-specific. No inter-thread + * synchronization is ensured in multiple access to a single TSEC + * structure. + * + * Resources: + *\li TBS + * + * Security: + *\li This module does not handle any low-level data directly, and so no + * security issue specific to this module is anticipated. + */ + +#include + +#include + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*% + * Transaction security types. + */ +typedef enum { + dns_tsectype_none, + dns_tsectype_tsig, + dns_tsectype_sig0 +} dns_tsectype_t; + +isc_result_t +dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, + dns_tsec_t **tsecp); +/*%< + * Create a TSEC structure and stores a type-dependent key structure in it. + * For a TSIG key (type is dns_tsectype_tsig), dns_tsec_create() creates a + * TSIG key structure from '*key' and keeps it in the structure. For other + * types, this function simply retains '*key' in the structure. In either + * case, the ownership of '*key' is transferred to the TSEC module; the caller + * must not modify or destroy it after the call to dns_tsec_create(). + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'type' is a valid value of dns_tsectype_t (see above). + * + *\li 'key' is a valid key. + * + *\li tsecp != NULL && *tsecp == NULL. + * + * Returns: + * + *\li #ISC_R_SUCCESS On success. + * + *\li Anything else Failure. + */ + +void +dns_tsec_destroy(dns_tsec_t **tsecp); +/*%< + * Destroy the TSEC structure. The stored key is also detached or destroyed. + * + * Requires + * + *\li '*tsecp' is a valid TSEC structure. + * + * Ensures + * + *\li *tsecp == NULL. + * + */ + +dns_tsectype_t +dns_tsec_gettype(dns_tsec_t *tsec); +/*%< + * Return the TSEC type of '*tsec'. + * + * Requires + * + *\li 'tsec' is a valid TSEC structure. + * + */ + +void +dns_tsec_getkey(dns_tsec_t *tsec, void *keyp); +/*%< + * Return the TSEC key of '*tsec' in '*keyp'. + * + * Requires + * + *\li keyp != NULL + * + * Ensures + * + *\li *tsecp points to a valid key structure depending on the TSEC type. + */ + +#endif /* DNS_TSEC_H */ diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 2e100d317e..79be222e10 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.135 2009/07/19 04:18:05 each Exp $ */ +/* $Id: types.h,v 1.136 2009/09/01 00:22:27 jinmei Exp $ */ #ifndef DNS_TYPES_H #define DNS_TYPES_H 1 @@ -44,6 +44,10 @@ typedef struct dns_adbentry dns_adbentry_t; typedef struct dns_adbfind dns_adbfind_t; typedef ISC_LIST(dns_adbfind_t) dns_adbfindlist_t; typedef struct dns_byaddr dns_byaddr_t; +typedef struct dns_client dns_client_t; +typedef void dns_clientrestrans_t; +typedef void dns_clientreqtrans_t; +typedef void dns_clientupdatetrans_t; typedef struct dns_cache dns_cache_t; typedef isc_uint16_t dns_cert_t; typedef struct dns_compress dns_compress_t; @@ -114,6 +118,7 @@ typedef struct dns_stats dns_stats_t; typedef isc_uint32_t dns_rdatastatstype_t; typedef struct dns_tkeyctx dns_tkeyctx_t; typedef isc_uint16_t dns_trust_t; +typedef struct dns_tsec dns_tsec_t; typedef struct dns_tsig_keyring dns_tsig_keyring_t; typedef struct dns_tsigkey dns_tsigkey_t; typedef isc_uint32_t dns_ttl_t; diff --git a/lib/dns/lib.c b/lib/dns/lib.c index 6f98b5374e..becc19d1b5 100644 --- a/lib/dns/lib.c +++ b/lib/dns/lib.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.c,v 1.16 2007/06/19 23:47:16 tbox Exp $ */ +/* $Id: lib.c,v 1.17 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -23,11 +23,20 @@ #include -#include +#include +#include #include +#include +#include #include +#include +#include #include +#include + +#include + /*** *** Globals @@ -63,3 +72,97 @@ dns_lib_initmsgcat(void) { RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS); } + +static isc_once_t init_once = ISC_ONCE_INIT; +static isc_mem_t *dns_g_mctx = NULL; +#ifndef BIND9 +static dns_dbimplementation_t *dbimp = NULL; +#endif +static isc_boolean_t initialize_done = ISC_FALSE; +static isc_mutex_t reflock; +static unsigned int references = 0; + +static void +initialize() { + isc_result_t result; + + REQUIRE(initialize_done == ISC_FALSE); + + result = isc_mem_create(0, 0, &dns_g_mctx); + if (result != ISC_R_SUCCESS) + return; + dns_result_register(); +#ifndef BIND9 + result = dns_ecdb_register(dns_g_mctx, &dbimp); + if (result != ISC_R_SUCCESS) + goto cleanup_mctx; +#endif + result = isc_hash_create(dns_g_mctx, NULL, DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + goto cleanup_db; + + result = dst_lib_init(dns_g_mctx, NULL, 0); + if (result != ISC_R_SUCCESS) + goto cleanup_hash; + + result = isc_mutex_init(&reflock); + if (result != ISC_R_SUCCESS) + goto cleanup_dst; + + initialize_done = ISC_TRUE; + return; + + cleanup_dst: + dst_lib_destroy(); + cleanup_hash: + isc_hash_destroy(); + cleanup_db: +#ifndef BIND9 + dns_ecdb_unregister(&dbimp); + cleanup_mctx: +#endif + isc_mem_detach(&dns_g_mctx); +} + +isc_result_t +dns_lib_init(void) { + isc_result_t result; + + /* + * Since this routine is expected to be used by a normal application, + * it should be better to return an error, instead of an emergency + * abort, on any failure. + */ + result = isc_once_do(&init_once, initialize); + if (result != ISC_R_SUCCESS) + return (result); + + if (!initialize_done) + return (ISC_R_FAILURE); + + LOCK(&reflock); + references++; + UNLOCK(&reflock); + + return (ISC_R_SUCCESS); +} + +void +dns_lib_shutdown(void) { + isc_boolean_t cleanup_ok = ISC_FALSE; + + LOCK(&reflock); + if (--references == 0) + cleanup_ok = ISC_TRUE; + UNLOCK(&reflock); + + if (!cleanup_ok) + return; + + dst_lib_destroy(); + isc_hash_destroy(); +#ifndef BIND9 + dns_ecdb_unregister(&dbimp); +#endif + isc_mem_detach(&dns_g_mctx); +} diff --git a/lib/dns/master.c b/lib/dns/master.c index 35543520ba..49e2985c2c 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.177 2009/06/30 02:52:32 each Exp $ */ +/* $Id: master.c,v 1.178 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -1382,7 +1382,7 @@ load_text(dns_loadctx_t *lctx) { isc_buffer_setactive(&buffer, token.value.as_region.length); result = dns_name_fromtext(new_name, &buffer, - ictx->origin, ISC_FALSE, NULL); + ictx->origin, 0, NULL); if (MANYERRS(lctx, result)) { SETRESULT(lctx, result); LOGIT(result); diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index ce9496279a..a451d98dfd 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.c,v 1.97 2009/01/17 23:47:42 tbox Exp $ */ +/* $Id: masterdump.c,v 1.98 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -162,6 +162,7 @@ static char spaces[N_SPACES+1] = " "; #define N_TABS 10 static char tabs[N_TABS+1] = "\t\t\t\t\t\t\t\t\t\t"; +#ifdef BIND9 struct dns_dumpctx { unsigned int magic; isc_mem_t *mctx; @@ -189,6 +190,7 @@ struct dns_dumpctx { dns_totext_ctx_t *ctx, isc_buffer_t *buffer, FILE *f); }; +#endif /* BIND9 */ #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) @@ -698,6 +700,7 @@ dns_master_questiontotext(dns_name_t *owner_name, ISC_FALSE, target)); } +#ifdef BIND9 /* * Print an rdataset. 'buffer' is a scratch buffer, which must have been * dynamically allocated by the caller. It must be large enough to @@ -1775,6 +1778,7 @@ dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, return (result); } +#endif /* BIND9 */ isc_result_t dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags, diff --git a/lib/dns/name.c b/lib/dns/name.c index c5c374042d..1102ea166a 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.c,v 1.167 2009/03/11 23:47:35 tbox Exp $ */ +/* $Id: name.c,v 1.168 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -1019,6 +1019,31 @@ dns_name_toregion(dns_name_t *name, isc_region_t *r) { DNS_NAME_TOREGION(name, r); } +isc_result_t +dns_name_fromstr(dns_name_t *name, const char *source, const char *origin, + unsigned int options, isc_buffer_t *target) +{ + dns_name_t *o; + dns_fixedname_t fixed; + isc_buffer_t b; + isc_result_t result; + + REQUIRE(source != NULL); + if (origin != NULL) { + isc_buffer_init(&b, origin, strlen(origin)); + isc_buffer_add(&b, strlen(origin)); + dns_fixedname_init(&fixed); + o = dns_fixedname_name(&fixed); + result = dns_name_fromtext(o, &b, dns_rootname, options, NULL); + if (result != ISC_R_SUCCESS) + return(result); + } else + o = dns_rootname; + + isc_buffer_init(&b, source, strlen(source)); + isc_buffer_add(&b, strlen(source)); + return (dns_name_fromtext(name, &b, o, options, target)); +} isc_result_t dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, @@ -2385,7 +2410,7 @@ dns_name_fromstring(dns_name_t *target, const char *src, isc_mem_t *mctx) { dns_fixedname_init(&fn); name = dns_fixedname_name(&fn); - result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 12474cb822..d83b253c6f 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.c,v 1.31 2008/04/03 06:09:04 tbox Exp $ */ +/* $Id: peer.c,v 1.32 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -536,7 +536,7 @@ dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) { isc_buffer_init(&b, keyval, strlen(keyval)); isc_buffer_add(&b, strlen(keyval)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index bcd01a1e61..0bbf3d9c97 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.277 2009/07/13 07:02:46 marka Exp $ */ +/* $Id: rbtdb.c,v 1.278 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -625,8 +625,10 @@ typedef struct rbtdb_dbiterator { static void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event); static void overmem(dns_db_t *db, isc_boolean_t overmem); +#ifdef BIND9 static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, isc_boolean_t *nsec3createflag); +#endif /*% * 'init_count' is used to initialize 'newheader->count' which inturn @@ -1925,6 +1927,13 @@ cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) { static void iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { +#ifndef BIND9 + UNUSED(db); + UNUSED(version); + UNUSED(origin); + + return; +#else dns_rdataset_t keyset; dns_rdataset_t nsecset, signsecset; dns_rdata_t rdata = DNS_RDATA_INIT; @@ -1988,12 +1997,14 @@ iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) { version->secure = dns_db_partial; else version->secure = dns_db_insecure; +#endif } /*%< * Walk the origin node looking for NSEC3PARAM records. * Cache the nsec3 parameters. */ +#ifdef BIND9 static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, isc_boolean_t *nsec3createflag) @@ -2098,6 +2109,7 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, isc_rwlocktype_read); RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); } +#endif static void closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { @@ -6505,9 +6517,17 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, REQUIRE(VALID_RBTDB(rbtdb)); +#ifdef BIND9 return (dns_master_dump2(rbtdb->common.mctx, db, version, &dns_master_style_default, filename, masterformat)); +#else + UNUSED(version); + UNUSED(filename); + UNUSED(masterformat); + + return (ISC_R_NOTIMPLEMENTED); +#endif /* BIND9 */ } static void @@ -8089,6 +8109,21 @@ rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_name_t *fname, dns_message_t *msg, isc_stdtime_t now) { +#ifndef BIND9 + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + UNUSED(acache); + UNUSED(zonep); + UNUSED(dbp); + UNUSED(versionp); + UNUSED(nodep); + UNUSED(fname); + UNUSED(msg); + UNUSED(now); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8205,8 +8240,10 @@ acache_callback(dns_acacheentry_t *entry, void **arg) { dns_db_detach((dns_db_t **)(void*)&rbtdb); *arg = NULL; +#endif /* BIND9 */ } +#ifdef BIND9 static void acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry, acache_cbarg_t **cbargp) @@ -8227,6 +8264,7 @@ acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry, *cbargp = NULL; } +#endif /* BIND9 */ static isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, @@ -8235,6 +8273,19 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *fname) { +#ifndef BIND9 + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + UNUSED(acache); + UNUSED(zone); + UNUSED(db); + UNUSED(version); + UNUSED(node); + UNUSED(fname); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8358,12 +8409,21 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, } return (result); +#endif } static isc_result_t rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_rdatatype_t qtype) { +#ifndef BIND9 + UNUSED(acache); + UNUSED(rdataset); + UNUSED(type); + UNUSED(qtype); + + return (ISC_R_NOTIMPLEMENTED); +#else dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtnode_t *rbtnode = rdataset->private2; unsigned char *raw = rdataset->private3; /* RDATASLAB */ @@ -8428,6 +8488,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset, } return (ISC_R_SUCCESS); +#endif } /*% diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 032c3d8ccd..5f8f0d6198 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.200 2008/12/12 04:37:23 marka Exp $ */ +/* $Id: rdata.c,v 1.201 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1767,3 +1768,93 @@ dns_rdatatype_isknown(dns_rdatatype_t type) { return (ISC_TRUE); return (ISC_FALSE); } + +void +dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_none; +} + +void +dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + rdata->data = NULL; + rdata->length = 0; + rdata->flags = DNS_RDATA_UPDATE; + rdata->type = type; + rdata->rdclass = dns_rdataclass_any; +} + +void +dns_rdata_makedelete(dns_rdata_t *rdata) { + REQUIRE(rdata != NULL); + + rdata->rdclass = dns_rdataclass_none; +} + +const char * +dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) { + + REQUIRE(rdata != NULL); + REQUIRE(DNS_RDATA_INITIALIZED(rdata)); + + switch (section) { + case DNS_SECTION_PREREQUISITE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain doesn't exist"); + default: + return ("rrset doesn't exist"); + } + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("domain exists"); + default: + return ("rrset exists (value independent)"); + } + default: + return ("rrset exists (value dependent)"); + } + case DNS_SECTION_UPDATE: + switch (rdata->rdclass) { + case dns_rdataclass_none: + return ("delete"); + case dns_rdataclass_any: + switch (rdata->type) { + case dns_rdatatype_any: + return ("delete all rrsets"); + default: + return ("delete rrset"); + } + default: + return ("add"); + } + } + return ("invalid"); +} diff --git a/lib/dns/request.c b/lib/dns/request.c index d0637ad688..ba19154b15 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: request.c,v 1.84 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: request.c,v 1.85 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -449,7 +449,8 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) { } static isc_result_t -new_request(isc_mem_t *mctx, dns_request_t **requestp) { +new_request(isc_mem_t *mctx, dns_request_t **requestp) +{ dns_request_t *request; request = isc_mem_get(mctx, sizeof(*request)); diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 3bec9adb05..4cfc737e00 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.404 2009/08/13 04:33:51 marka Exp $ */ +/* $Id: resolver.c,v 1.405 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -1013,6 +1013,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) { ISC_LIST_UNLINK(fctx->events, event, ev_link); task = event->ev_sender; event->ev_sender = fctx; + event->vresult = fctx->vresult; if (!HAVE_ANSWER(fctx)) event->result = result; @@ -3889,6 +3890,7 @@ validated(isc_task_t *task, isc_event_t *event) { REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); vevent = (dns_validatorevent_t *)event; + fctx->vresult = vevent->result; FCTXTRACE("received validation completion event"); @@ -7151,6 +7153,7 @@ dns_resolver_create(dns_view_t *view, return (result); } +#ifdef BIND9 static void prime_done(isc_task_t *task, isc_event_t *event) { dns_resolver_t *res; @@ -7256,6 +7259,7 @@ dns_resolver_prime(dns_resolver_t *res) { } } } +#endif /* BIND9 */ void dns_resolver_freeze(dns_resolver_t *res) { diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 6dc02f351a..34c3455d06 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.69 2009/06/26 06:21:02 marka Exp $ */ +/* $Id: sdb.c,v 1.70 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -450,7 +450,7 @@ getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) { isc_buffer_init(&b, name, strlen(name)); isc_buffer_add(&b, strlen(name)); - result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); + result = dns_name_fromtext(newname, &b, origin, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 176470d875..2138e38eb8 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.21 2009/06/26 06:21:03 marka Exp $ */ +/* $Id: sdlz.c,v 1.22 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -1620,7 +1620,7 @@ dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, isc_buffer_init(&b, name, strlen(name)); isc_buffer_add(&b, strlen(name)); - result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); + result = dns_name_fromtext(newname, &b, origin, 0, NULL); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 9e59dfaf8e..5d6d5484cf 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -16,7 +16,7 @@ */ /* - * $Id: tkey.c,v 1.90 2008/04/03 00:45:23 marka Exp $ + * $Id: tkey.c,v 1.91 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ #include @@ -724,8 +724,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, } isc_buffer_init(&b, randomtext, sizeof(randomtext)); isc_buffer_add(&b, sizeof(randomtext)); - result = dns_name_fromtext(keyname, &b, NULL, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto failure; } diff --git a/lib/dns/tsec.c b/lib/dns/tsec.c new file mode 100644 index 0000000000..dbd0b85cb8 --- /dev/null +++ b/lib/dns/tsec.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: tsec.c,v 1.2 2009/09/01 00:22:26 jinmei Exp $ */ + +#include + +#include +#include +#include + +#include + +#define DNS_TSEC_MAGIC ISC_MAGIC('T', 's', 'e', 'c') +#define DNS_TSEC_VALID(t) ISC_MAGIC_VALID(t, DNS_TSEC_MAGIC) + +/*% + * DNS Transaction Security object. We assume this is not shared by + * multiple threads, and so the structure does not contain a lock. + */ +struct dns_tsec { + unsigned int magic; + dns_tsectype_t type; + isc_mem_t *mctx; + union { + dns_tsigkey_t *tsigkey; + dst_key_t *key; + } ukey; +}; + +isc_result_t +dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, + dns_tsec_t **tsecp) +{ + isc_result_t result; + dns_tsec_t *tsec; + dns_tsigkey_t *tsigkey = NULL; + dns_name_t *algname; + + REQUIRE(mctx != NULL); + REQUIRE(tsecp != NULL && *tsecp == NULL); + + tsec = isc_mem_get(mctx, sizeof(*tsec)); + if (tsec == NULL) + return (ISC_R_NOMEMORY); + + tsec->type = type; + tsec->mctx = mctx; + + switch (type) { + case dns_tsectype_tsig: + switch (dst_key_alg(key)) { + case DST_ALG_HMACMD5: + algname = dns_tsig_hmacmd5_name; + break; + case DST_ALG_HMACSHA1: + algname = dns_tsig_hmacsha1_name; + break; + case DST_ALG_HMACSHA224: + algname = dns_tsig_hmacsha224_name; + break; + case DST_ALG_HMACSHA256: + algname = dns_tsig_hmacsha256_name; + break; + case DST_ALG_HMACSHA384: + algname = dns_tsig_hmacsha384_name; + break; + case DST_ALG_HMACSHA512: + algname = dns_tsig_hmacsha512_name; + break; + default: + isc_mem_put(mctx, tsec, sizeof(*tsec)); + return (DNS_R_BADALG); + } + result = dns_tsigkey_createfromkey(dst_key_name(key), + algname, key, ISC_FALSE, + NULL, 0, 0, mctx, NULL, + &tsigkey); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, tsec, sizeof(*tsec)); + return (result); + } + tsec->ukey.tsigkey = tsigkey; + break; + case dns_tsectype_sig0: + tsec->ukey.key = key; + break; + default: + INSIST(0); + } + + tsec->magic = DNS_TSEC_MAGIC; + + *tsecp = tsec; + + return (ISC_R_SUCCESS); +} + +void +dns_tsec_destroy(dns_tsec_t **tsecp) { + dns_tsec_t *tsec; + + REQUIRE(tsecp != NULL && *tsecp != NULL); + tsec = *tsecp; + REQUIRE(DNS_TSEC_VALID(tsec)); + + switch (tsec->type) { + case dns_tsectype_tsig: + dns_tsigkey_detach(&tsec->ukey.tsigkey); + break; + case dns_tsectype_sig0: + dst_key_free(&tsec->ukey.key); + break; + default: + INSIST(0); + } + + tsec->magic = 0; + isc_mem_put(tsec->mctx, tsec, sizeof(*tsec)); + + *tsecp = NULL; +} + +dns_tsectype_t +dns_tsec_gettype(dns_tsec_t *tsec) { + REQUIRE(DNS_TSEC_VALID(tsec)); + + return (tsec->type); +} + +void +dns_tsec_getkey(dns_tsec_t *tsec, void *keyp) { + REQUIRE(DNS_TSEC_VALID(tsec)); + REQUIRE(keyp != NULL); + + switch (tsec->type) { + case dns_tsectype_tsig: + dns_tsigkey_attach(tsec->ukey.tsigkey, (dns_tsigkey_t **)keyp); + break; + case dns_tsectype_sig0: + *(dst_key_t **)keyp = tsec->ukey.key; + break; + default: + INSIST(0); + } +} diff --git a/lib/dns/view.c b/lib/dns/view.c index 57dc617472..0c477c3656 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.155 2009/06/30 02:52:32 each Exp $ */ +/* $Id: view.c,v 1.156 2009/09/01 00:22:26 jinmei Exp $ */ /*! \file */ @@ -86,6 +86,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, if (result != ISC_R_SUCCESS) goto cleanup_name; +#ifdef BIND9 view->zonetable = NULL; result = dns_zt_create(mctx, rdclass, &view->zonetable); if (result != ISC_R_SUCCESS) { @@ -95,6 +96,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, result = ISC_R_UNEXPECTED; goto cleanup_mutex; } +#endif view->secroots = NULL; view->fwdtable = NULL; result = dns_fwdtable_create(mctx, &view->fwdtable); @@ -177,9 +179,11 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->maxudp = 0; dns_fixedname_init(&view->dlv_fixed); +#ifdef BIND9 result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; +#endif result = dns_peerlist_new(view->mctx, &view->peers); if (result != ISC_R_SUCCESS) @@ -209,9 +213,11 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_peerlist_detach(&view->peers); cleanup_order: +#ifdef BIND9 dns_order_detach(&view->order); cleanup_dynkeys: +#endif dns_tsigkeyring_destroy(&view->dynamickeys); cleanup_references: @@ -221,9 +227,11 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_fwdtable_destroy(&view->fwdtable); cleanup_zt: +#ifdef BIND9 dns_zt_detach(&view->zonetable); cleanup_mutex: +#endif DESTROYLOCK(&view->lock); cleanup_name: @@ -244,8 +252,10 @@ destroy(dns_view_t *view) { REQUIRE(ADBSHUTDOWN(view)); REQUIRE(REQSHUTDOWN(view)); +#ifdef BIND9 if (view->order != NULL) dns_order_detach(&view->order); +#endif if (view->peers != NULL) dns_peerlist_detach(&view->peers); if (view->dynamickeys != NULL) @@ -256,11 +266,13 @@ destroy(dns_view_t *view) { dns_adb_detach(&view->adb); if (view->resolver != NULL) dns_resolver_detach(&view->resolver); +#ifdef BIND9 if (view->acache != NULL) { if (view->cachedb != NULL) dns_acache_putdb(view->acache, view->cachedb); dns_acache_detach(&view->acache); } +#endif if (view->requestmgr != NULL) dns_requestmgr_detach(&view->requestmgr); if (view->task != NULL) @@ -399,12 +411,14 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { dns_adb_shutdown(view->adb); if (!REQSHUTDOWN(view)) dns_requestmgr_shutdown(view->requestmgr); +#ifdef BIND9 if (view->acache != NULL) dns_acache_shutdown(view->acache); if (view->flush) dns_zt_flushanddetach(&view->zonetable); else dns_zt_detach(&view->zonetable); +#endif done = all_done(view); UNLOCK(&view->lock); } @@ -425,6 +439,7 @@ dns_view_detach(dns_view_t **viewp) { view_flushanddetach(viewp, ISC_FALSE); } +#ifdef BIND9 static isc_result_t dialup(dns_zone_t *zone, void *dummy) { UNUSED(dummy); @@ -437,6 +452,7 @@ dns_view_dialup(dns_view_t *view) { REQUIRE(DNS_VIEW_VALID(view)); (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL); } +#endif void dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) { @@ -628,8 +644,10 @@ dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { view->cacheshared = shared; if (view->cache != NULL) { +#ifdef BIND9 if (view->acache != NULL) dns_acache_putdb(view->acache, view->cachedb); +#endif dns_db_detach(&view->cachedb); dns_cache_detach(&view->cache); } @@ -637,8 +655,10 @@ dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) { dns_cache_attachdb(cache, &view->cachedb); INSIST(DNS_DB_VALID(view->cachedb)); +#ifdef BIND9 if (view->acache != NULL) dns_acache_setdb(view->acache, view->cachedb); +#endif } isc_boolean_t @@ -673,6 +693,7 @@ dns_view_setdstport(dns_view_t *view, in_port_t dstport) { view->dstport = dstport; } +#ifdef BIND9 isc_result_t dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { isc_result_t result; @@ -684,6 +705,7 @@ dns_view_addzone(dns_view_t *view, dns_zone_t *zone) { return (result); } +#endif void dns_view_freeze(dns_view_t *view) { @@ -697,6 +719,7 @@ dns_view_freeze(dns_view_t *view) { view->frozen = ISC_TRUE; } +#ifdef BIND9 isc_result_t dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { isc_result_t result; @@ -711,6 +734,7 @@ dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) { return (result); } +#endif isc_result_t dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, @@ -725,6 +749,10 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, dns_rdataset_t zrdataset, zsigrdataset; dns_zone_t *zone; +#ifndef BIND9 + UNUSED(use_hints); +#endif + /* * Find an rdataset whose owner name is 'name', and whose type is * 'type'. @@ -750,6 +778,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, zone = NULL; db = NULL; node = NULL; +#ifdef BIND9 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { result = dns_zone_getdb(zone, &db); @@ -759,6 +788,11 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, goto cleanup; } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) dns_db_attach(view->cachedb, &db); +#else + result = ISC_R_NOTFOUND; + if (view->cachedb != NULL) + dns_db_attach(view->cachedb, &db); +#endif /* BIND9 */ else goto cleanup; @@ -841,6 +875,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, result = ISC_R_SUCCESS; } +#ifdef BIND9 if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); @@ -875,6 +910,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, if (db == NULL && node != NULL) dns_db_detachnode(view->hints, &node); } +#endif /* BIND9 */ cleanup: if (dns_rdataset_isassociated(&zrdataset)) { @@ -903,8 +939,10 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, } else INSIST(node == NULL); +#ifdef BIND9 if (zone != NULL) dns_zone_detach(&zone); +#endif return (result); } @@ -997,9 +1035,13 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, /* * Find the right database. */ +#ifdef BIND9 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) result = dns_zone_getdb(zone, &db); +#else + result = ISC_R_NOTFOUND; +#endif if (result == ISC_R_NOTFOUND) { /* * We're not directly authoritative for this query name, nor @@ -1131,8 +1173,10 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, } if (db != NULL) dns_db_detach(&db); +#ifdef BIND9 if (zone != NULL) dns_zone_detach(&zone); +#endif return (result); } @@ -1159,6 +1203,7 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name, return (ISC_R_SUCCESS); } +#ifdef BIND9 isc_result_t dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allclasses, dns_rdataclass_t rdclass, @@ -1223,6 +1268,7 @@ dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { return (dns_zt_loadnew(view->zonetable, stop)); } +#endif /* BIND9 */ isc_result_t dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp) @@ -1266,6 +1312,7 @@ dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) { view->dynamickeys)); } +#ifdef BIND9 isc_result_t dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { isc_result_t result; @@ -1280,6 +1327,7 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { dns_adb_dump(view->adb, fp); return (ISC_R_SUCCESS); } +#endif isc_result_t dns_view_flushcache(dns_view_t *view) { @@ -1299,12 +1347,16 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { if (result != ISC_R_SUCCESS) return (result); } +#ifdef BIND9 if (view->acache != NULL) dns_acache_putdb(view->acache, view->cachedb); +#endif dns_db_detach(&view->cachedb); dns_cache_attachdb(view->cache, &view->cachedb); +#ifdef BIND9 if (view->acache != NULL) dns_acache_setdb(view->acache, view->cachedb); +#endif dns_adb_flush(view->adb); return (ISC_R_SUCCESS); @@ -1436,11 +1488,13 @@ dns_view_getrootdelonly(dns_view_t *view) { return (view->rootdelonly); } +#ifdef BIND9 isc_result_t dns_view_freezezones(dns_view_t *view, isc_boolean_t value) { REQUIRE(DNS_VIEW_VALID(view)); return (dns_zt_freezezones(view->zonetable, value)); } +#endif void dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) { diff --git a/lib/export/Makefile.in b/lib/export/Makefile.in new file mode 100644 index 0000000000..5bbc93f400 --- /dev/null +++ b/lib/export/Makefile.in @@ -0,0 +1,27 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# Note: the order of SUBDIRS is important. +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: +SUBDIRS = isc dns isccfg irs samples +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in new file mode 100644 index 0000000000..3942ef156d --- /dev/null +++ b/lib/export/dns/Makefile.in @@ -0,0 +1,172 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/dns + +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: + +@BIND9_VERSION@ + +@LIBDNS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \ + ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ + +CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ + +CWARNINGS = + +ISCLIBS = ../isc/libisc.@A@ + +ISCDEPLIBS = ../isc/libisc.@A@ + +LIBS = @LIBS@ + +# Alphabetically +DSTOBJS = dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \ + gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ \ + openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \ + opensslrsa_link.@O@ + +DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ + cache.@O@ callbacks.@O@ client.@O@ compress.@O@ \ + db.@O@ dbiterator.@O@ diff.@O@ dispatch.@O@ dlz.@O@ dnssec.@O@ \ + ds.@O@ \ + forward.@O@ iptable.@O@ \ + keytable.@O@ \ + lib.@O@ log.@O@ \ + master.@O@ masterdump.@O@ message.@O@ \ + name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ \ + peer.@O@ portlist.@O@ \ + rbt.@O@ rbtdb.@O@ rcode.@O@ rdata.@O@ \ + rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ + request.@O@ resolver.@O@ result.@O@ soa.@O@ stats.@O@ \ + tcpmsg.@O@ time.@O@ tsec.@O@ tsig.@O@ ttl.@O@ \ + validator.@O@ version.@O@ view.@O@ +PORTDNSOBJS = ecdb.@O@ + +OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} ${PORTDNSOBJS} + +# Alphabetically +DSTSRCS = dst_api.c dst_lib.c dst_parse.c \ + dst_result.c gssapi_link.c gssapictx.c \ + hmac_link.c key.c \ + openssl_link.c openssldh_link.c \ + openssldsa_link.c opensslrsa_link.c + +DNSSRCS = acl.c adb.c byaddr.c \ + cache.c callbacks.c client.c compress.c \ + db.c dbiterator.c diff.c dispatch.c dlz.c dnssec.c ds.c \ + forward.c iptable.c \ + keytable.c \ + lib.c log.c \ + master.c masterdump.c message.c \ + name.c ncache.c nsec.c nsec3.c \ + peer.c portlist.c \ + rbt.c rbtdb.c rcode.c rdata.c \ + rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ + request.c res.c resolver.c result.c soa.c stats.c \ + tcpmsg.c time.c tsec.c tsig.c ttl.c \ + validator.c version.c view.c +PORTDNSSRCS = ecdb.c + +SRCS = ${DSTSRCS} ${DNSSRCS} ${PORTDNSSRCS} + +SUBDIRS = include +TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h timestamp + +DEPENDEXTRA = ./gen -F include/dns/rdatastruct.h \ + -s ${srcdir} -d >> Makefile ; + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libdns.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libdns.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} + +timestamp: libdns.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libdns.@A@ timestamp + rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h + rm -f include/dns/rdatastruct.h + +newrr:: + rm -f code.h include/dns/enumtype.h include/dns/enumclass.h + rm -f include/dns/rdatastruct.h + +include: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h + +rdata.@O@: code.h + +include/dns/enumtype.h: gen + ./gen -s ${srcdir} -t > $@ + +include/dns/enumclass.h: gen + ./gen -s ${srcdir} -c > $@ + +include/dns/rdatastruct.h: gen \ + ${srcdir}/rdata/rdatastructpre.h \ + ${srcdir}/rdata/rdatastructsuf.h + ./gen -s ${srcdir} -i \ + -P ${srcdir}/rdata/rdatastructpre.h \ + -S ${srcdir}/rdata/rdatastructsuf.h > $@ + +code.h: gen + ./gen -s ${srcdir} > code.h + +gen: ${srcdir}/gen.c + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ${srcdir}/gen.c ${LIBS} + +#We don't need rbtdb64 for this library +#rbtdb64.@O@: rbtdb.c + +depend: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h code.h +subdirs: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h code.h +${OBJS}: include/dns/enumtype.h include/dns/enumclass.h \ + include/dns/rdatastruct.h diff --git a/lib/export/dns/include/Makefile.in b/lib/export/dns/include/Makefile.in new file mode 100644 index 0000000000..d28e14a1cc --- /dev/null +++ b/lib/export/dns/include/Makefile.in @@ -0,0 +1,23 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = dns dst +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/dns/include/dns/Makefile.in b/lib/export/dns/include/dns/Makefile.in new file mode 100644 index 0000000000..13486159a1 --- /dev/null +++ b/lib/export/dns/include/dns/Makefile.in @@ -0,0 +1,56 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = acl.h adb.h byaddr.h \ + cache.h callbacks.h cert.h client.h compress.h \ + db.h dbiterator.h diff.h dispatch.h dlz.h dnssec.h \ + ds.h events.h fixedname.h ecdb.h \ + forward.h iptable.h \ + keytable.h keyvalues.h \ + lib.h log.h \ + master.h masterdump.h message.h \ + name.h ncache.h nsec.h nsec3.h \ + peer.h portlist.h \ + rbt.h rbtdb.h rcode.h rdata.h rdataclass.h \ + rdatalist.h rdataset.h rdatasetiter.h rdataslab.h rdatatype.h \ + request.h resolver.h result.h \ + secalg.h secproto.h soa.h stats.h \ + tcpmsg.h time.h tsec.h tsig.h ttl.h types.h \ + validator.h version.h view.h + +GENHEADERS = enumclass.h enumtype.h rdatastruct.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dns + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dns/$$i \ + ${DESTDIR}${export_includedir}/dns ; \ + done + for i in ${GENHEADERS}; do \ + ${INSTALL_DATA} $$i ${DESTDIR}${export_includedir}/dns ; \ + done diff --git a/lib/export/dns/include/dst/Makefile.in b/lib/export/dns/include/dst/Makefile.in new file mode 100644 index 0000000000..c1d1340c6c --- /dev/null +++ b/lib/export/dns/include/dst/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = dst.h gssapi.h lib.h result.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dst + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dst/$$i \ + ${DESTDIR}${export_includedir}/dst ; \ + done diff --git a/lib/export/irs/Makefile.in b/lib/export/irs/Makefile.in new file mode 100644 index 0000000000..91925c9ba3 --- /dev/null +++ b/lib/export/irs/Makefile.in @@ -0,0 +1,85 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/irs + +@BIND9_VERSION@ + +@LIBIRS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -I./include -I${srcdir}/include \ + ${ISCCFG_INCLUDES} -I../dns/include ${DNS_INCLUDES} \ + ${ISC_INCLUDES} +CDEFINES = +CWARNINGS = + +# Alphabetically +OBJS = context.@O@ \ + dnsconf.@O@ \ + gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \ + resconf.@O@ + +# Alphabetically +SRCS = context.c \ + dnsconf.c \ + gai_sterror.c getaddrinfo.c getnameinfo.c \ + resconf.c + +ISCLIBS = ../isc/libisc.@A@ +DNSLIBS = ../dns/libdns.@A@ +ISCCFGLIBS = ../isccfg/libisccfg.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libirs.@SA@: ${OBJS} version.@O@ + ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ + ${RANLIB} $@ + +libirs.la: ${OBJS} version.@O@ + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} version.@O@ ${LIBS} ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} + +timestamp: libirs.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libirs.@A@ libirs.la timestamp diff --git a/lib/export/irs/include/Makefile.in b/lib/export/irs/include/Makefile.in new file mode 100644 index 0000000000..6fad286ea9 --- /dev/null +++ b/lib/export/irs/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/irs/include/irs/Makefile.in b/lib/export/irs/include/irs/Makefile.in new file mode 100644 index 0000000000..334b355de8 --- /dev/null +++ b/lib/export/irs/include/irs/Makefile.in @@ -0,0 +1,46 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = context.h dnsconf.h resconf.h types.h version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/$$i \ + ${DESTDIR}${export_includedir}/irs ; \ + done + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/netdb.h \ + ${DESTDIR}${export_includedir}/irs + ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/platform.h \ + ${DESTDIR}${export_includedir}/irs + +distclean:: + rm -f netdb.h platform.h diff --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in new file mode 100644 index 0000000000..30531b4f9c --- /dev/null +++ b/lib/export/isc/Makefile.in @@ -0,0 +1,136 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc + +@BIND9_VERSION@ + +@LIBISC_API@ + +CINCLUDES = -I${srcdir}/unix/include \ + -I${srcdir}/@ISC_THREAD_DIR@/include \ + -I${srcdir}/@ISC_ARCH_DIR@/include \ + -I${srcdir}/include @ISC_OPENSSL_INC@ +CDEFINES = @USE_OPENSSL@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ + -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \ + -DUSE_TIMERIMPREGISTER +CWARNINGS = + +# Alphabetically +# {file,dir}.c is necessary for isclog +# symtab.c is necessary for isccfg +APIOBJS = app_api.@O@ mem_api.@O@ socket_api.@O@ \ + task_api.@O@ timer_api.@O@ + +ISCDRIVEROBJS = mem.@O@ unix/socket.@O@ task.@O@ timer.@O@ lib.@O@ \ + heap.@O@ #timer module depends on this + +UNIXOBJS = @ISC_ISCIPV6_O@ \ + unix/app.@O@ \ + unix/dir.@O@ \ + unix/errno2result.@O@ \ + unix/file.@O@ \ + unix/fsaccess.@O@ \ + unix/stdio.@O@ \ + unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@ + +NLSOBJS = nls/msgcat.@O@ + +THREADOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ \ + @ISC_THREAD_DIR@/thread.@O@ + +WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ + win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \ + win32/thread.@O@ win32/time.@O@ + +# Alphabetically +OBJS = @ISC_EXTRA_OBJS@ \ + assertions.@O@ base32.@O@ \ + base64.@O@ buffer.@O@ bufferlist.@O@ \ + error.@O@ event.@O@ \ + hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ + inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ + md5.@O@ mutexblock.@O@ \ + netaddr.@O@ netscope.@O@ \ + ondestroy.@O@ \ + parseint.@O@ portset.@O@ radix.@O@ \ + random.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \ + serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ string.@O@ \ + symtab.@O@ \ + version.@O@ \ + ${APIOBJS} ${ISCDRIVEROBJS} \ + ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} + +# Alphabetically +APISRCS = app_api.c mem_api.c socket_api.c \ + task_api.c timer_api.c + +ISCDRIVERSRCS = mem.c task.c lib.c timer.c heap.c + +SRCS = @ISC_EXTRA_SRCS@ \ + assertions.c base32.c \ + base64.c buffer.c bufferlist.c \ + error.c event.c \ + hash.c hex.c hmacmd5.c hmacsha.c \ + inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ + md5.c mutexblock.c \ + netaddr.c netscope.c \ + ondestroy.c \ + parseint.c portset.c radix.c \ + random.c refcount.c region.c result.c rwlock.c \ + serial.c sha1.c sha2.c sockaddr.c stats.c string.c symtab.c \ + version.c \ + ${APISRCS} ${ISCDRIVERSRCS} + +LIBS = @LIBS@ + +SUBDIRS = include unix nls @ISC_THREAD_DIR@ +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libisc.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisc.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} + +timestamp: libisc.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libisc.@A@ libisc.la timestamp diff --git a/lib/export/isc/include/Makefile.in b/lib/export/isc/include/Makefile.in new file mode 100644 index 0000000000..4a5e0c6be1 --- /dev/null +++ b/lib/export/isc/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/include/isc/Makefile.in b/lib/export/isc/include/isc/Makefile.in new file mode 100644 index 0000000000..1e0ff001ea --- /dev/null +++ b/lib/export/isc/include/isc/Makefile.in @@ -0,0 +1,63 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = app.h assertions.h base64.h bitstring.h boolean.h buffer.h \ + bufferlist.h commandline.h entropy.h error.h event.h \ + eventclass.h file.h formatcheck.h fsaccess.h \ + hash.h heap.h hex.h hmacmd5.h \ + httpd.h \ + interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \ + lfsr.h lib.h list.h log.h \ + magic.h md5.h mem.h msgcat.h msgs.h \ + mutexblock.h namespace.h netaddr.h ondestroy.h os.h parseint.h \ + print.h quota.h radix.h random.h ratelimiter.h \ + refcount.h region.h resource.h \ + result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \ + sockaddr.h socket.h stdio.h stdlib.h string.h \ + symtab.h \ + task.h taskpool.h timer.h types.h util.h version.h \ + xml.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done + ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/platform.h \ + ${DESTDIR}${export_includedir}/isc + ${INSTALL_DATA} ${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include/isc/atomic.h \ + ${DESTDIR}${export_includedir}/isc + +distclean:: + rm -f platform.h diff --git a/lib/export/isc/nls/Makefile.in b/lib/export/isc/nls/Makefile.in new file mode 100644 index 0000000000..e272f369e7 --- /dev/null +++ b/lib/export/isc/nls/Makefile.in @@ -0,0 +1,35 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nls + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/unix/include \ + ${ISC_INCLUDES} + +CDEFINES = +CWARNINGS = + +OBJS = msgcat.@O@ + +SRCS = msgcat.c + +SUBDIRS = +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/Makefile.in b/lib/export/isc/nothreads/Makefile.in new file mode 100644 index 0000000000..571f429269 --- /dev/null +++ b/lib/export/isc/nothreads/Makefile.in @@ -0,0 +1,38 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nothreads + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../unix/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = +CWARNINGS = + +OBJS = condition.@O@ mutex.@O@ thread.@O@ + +SRCS = condition.c mutex.c thread.c + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/include/Makefile.in b/lib/export/isc/nothreads/include/Makefile.in new file mode 100644 index 0000000000..4a5e0c6be1 --- /dev/null +++ b/lib/export/isc/nothreads/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/nothreads/include/isc/Makefile.in b/lib/export/isc/nothreads/include/isc/Makefile.in new file mode 100644 index 0000000000..eb25c885bc --- /dev/null +++ b/lib/export/isc/nothreads/include/isc/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = condition.h mutex.h once.h thread.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/nothreads/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isc/pthreads/Makefile.in b/lib/export/isc/pthreads/Makefile.in new file mode 100644 index 0000000000..624d44f3ef --- /dev/null +++ b/lib/export/isc/pthreads/Makefile.in @@ -0,0 +1,38 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/pthreads + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../unix/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = +CWARNINGS = + +OBJS = condition.@O@ mutex.@O@ thread.@O@ + +SRCS = condition.c mutex.c thread.c + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/pthreads/include/Makefile.in b/lib/export/isc/pthreads/include/Makefile.in new file mode 100644 index 0000000000..4a5e0c6be1 --- /dev/null +++ b/lib/export/isc/pthreads/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/pthreads/include/isc/Makefile.in b/lib/export/isc/pthreads/include/isc/Makefile.in new file mode 100644 index 0000000000..77d5c0774b --- /dev/null +++ b/lib/export/isc/pthreads/include/isc/Makefile.in @@ -0,0 +1,36 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = condition.h mutex.h once.h thread.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/pthreads/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isc/unix/Makefile.in b/lib/export/isc/unix/Makefile.in new file mode 100644 index 0000000000..ccd60ce3b8 --- /dev/null +++ b/lib/export/isc/unix/Makefile.in @@ -0,0 +1,57 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/unix + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include \ + -I${srcdir}/../@ISC_THREAD_DIR@/include \ + -I../include \ + -I${srcdir}/../include \ + -I${srcdir}/.. + +CDEFINES = -DUSE_SOCKETIMPREGISTER -DUSE_APPIMPREGISTER + +CWARNINGS = + +# Alphabetically +ISCDRIVEROBJS = app.@O@ socket.@O@ + +OBJS = @ISC_IPV6_O@ \ + dir.@O@ \ + errno2result.@O@ \ + file.@O@ fsaccess.@O@ \ + stdio.@O@ stdtime.@O@ strerror.@O@ \ + time.@O@ \ + ${ISCDRIVEROBJS} + +# Alphabetically +ISCDRIVERSRCS = app.c socket.c + +SRCS = @ISC_IPV6_C@ \ + dir.c \ + errno2result.c \ + file.c fsaccess.c \ + stdio.c stdtime.c strerror.c \ + time.c \ + ${ISCDRIVERSRCS} + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/unix/include/Makefile.in b/lib/export/isc/unix/include/Makefile.in new file mode 100644 index 0000000000..4a5e0c6be1 --- /dev/null +++ b/lib/export/isc/unix/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isc/unix/include/isc/Makefile.in b/lib/export/isc/unix/include/isc/Makefile.in new file mode 100644 index 0000000000..f19b8c6576 --- /dev/null +++ b/lib/export/isc/unix/include/isc/Makefile.in @@ -0,0 +1,37 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +HEADERS = dir.h int.h net.h netdb.h offset.h stdtime.h \ + syslog.h time.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(top_srcdir)/lib/isc/unix/include/isc/$$i \ + ${DESTDIR}${export_includedir}/isc ; \ + done diff --git a/lib/export/isccfg/Makefile.in b/lib/export/isccfg/Makefile.in new file mode 100644 index 0000000000..d4e255dab8 --- /dev/null +++ b/lib/export/isccfg/Makefile.in @@ -0,0 +1,82 @@ +# Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2001-2003 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isccfg + +@BIND9_VERSION@ + +@LIBISCCFG_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCLIBS = ../isc/libisc.@A@ +DNSLIBS = ../dns/libdns.@A@ + +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCFGDEPLIBS = libisccfg.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include + +# Alphabetically +OBJS = dnsconf.@O@ log.@O@ parser.@O@ version.@O@ + +# Alphabetically +SRCS = dnsconf.c log.c parser.c version.c + +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: ${srcdir}/version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libisccfg.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisccfg.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la \ + -rpath ${export_libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} ${DNSLIBS} ${ISCLIBS} + +timestamp: libisccfg.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ \ + ${DESTDIR}${export_libdir} + +clean distclean:: + rm -f libisccfg.@A@ timestamp diff --git a/lib/export/isccfg/include/Makefile.in b/lib/export/isccfg/include/Makefile.in new file mode 100644 index 0000000000..0c3d185381 --- /dev/null +++ b/lib/export/isccfg/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srdir@ +top_srcdir = @top_srcdir@ + + +SUBDIRS = isccfg +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/export/isccfg/include/isccfg/Makefile.in b/lib/export/isccfg/include/isccfg/Makefile.in new file mode 100644 index 0000000000..49a6530c1a --- /dev/null +++ b/lib/export/isccfg/include/isccfg/Makefile.in @@ -0,0 +1,42 @@ +# Copyright (C) 20097 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = cfg.h grammar.h log.h dnsconf.h version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs \ + ${DESTDIR}${export_includedir}/isccfg + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${top_srcdir}/lib/isccfg/include/isccfg/$$i \ + ${DESTDIR}${export_includedir}/isccfg ; \ + done diff --git a/lib/export/samples/Makefile-postinstall.in b/lib/export/samples/Makefile-postinstall.in new file mode 100644 index 0000000000..6908147641 --- /dev/null +++ b/lib/export/samples/Makefile-postinstall.in @@ -0,0 +1,78 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile-postinstall.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +#prefix = @prefix@ +#exec_prefix = @exec_prefix@ + +CDEFINES = +CWARNINGS = + +DNSLIBS = -ldns @DNS_CRYPTO_LIBS@ +ISCLIBS = -lisc +ISCCFGLIBS = -lisccfg +IRSLIBS = -lirs + +LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \ + sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@ \ + dlvchecks@EXEEXT@ + +OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \ + sample-request.@O@ nsprobe.@O@ dlvchecks.@O@ + +SRCS = sample.c sample-async.c sample-gai.c sample-update.c \ + sample-request.c nsprobe.c dlvchecks..c + +@BIND9_MAKE_RULES@ + +# The following two may depend on BIND9_MAKE_RULES +CINCLUDES = -I@export_includedir@ +LDFLAGS = -L@export_libdir@ + +sample@EXEEXT@: sample.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample.@O@ ${LIBS} + +sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-async.@O@ ${LIBS} + +sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-gai.@O@ ${IRSLIBS} ${LIBS} + +sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-update.@O@ ${LIBS} + +sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-request.@O@ ${LIBS} + +nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + nsprobe.@O@ ${LIBS} + +dlvchecks@EXEEXT@: dlvchecks.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dlvchecks.@O@ ${LIBS} + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/lib/export/samples/Makefile.in b/lib/export/samples/Makefile.in new file mode 100644 index 0000000000..97e1a7c3a6 --- /dev/null +++ b/lib/export/samples/Makefile.in @@ -0,0 +1,96 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include -I../dns/include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} \ + -I${top_srcdir}/lib/irs/include + +CDEFINES = +CWARNINGS = + +DNSLIBS = ../dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +ISCLIBS = ../isc/libisc.@A@ +ISCCFGLIBS = ../isccfg/libisccfg.@A@ +IRSLIBS = ../irs/libirs.@A@ + +DNSDEPLIBS = ../dns/libdns.@A@ +ISCDEPLIBS = ../isc/libisc.@A@ +ISCCFGDEPLIBS = ../isccfg/libisccfg.@A@ +IRSDEPLIBS = ../irs/libirs.@A@ + +DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} + +LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \ + sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@ + +OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \ + sample-request.@O@ nsprobe.@O@ + +UOBJS = + +SRCS = sample.c sample-async.c sample-gai.c sample-update.c \ + sample-request.c nsprobe.c + +MANPAGES = + +HTMLPAGES = + +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +@BIND9_MAKE_RULES@ + +sample@EXEEXT@: sample.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample.@O@ ${LIBS} + +sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-async.@O@ ${LIBS} + +sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-gai.@O@ ${IRSLIBS} ${LIBS} + +sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-update.@O@ ${LIBS} + +sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + sample-request.@O@ ${LIBS} + +nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + nsprobe.@O@ ${LIBS} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/lib/export/samples/nsprobe.c b/lib/export/samples/nsprobe.c new file mode 100644 index 0000000000..fa3dfd4720 --- /dev/null +++ b/lib/export/samples/nsprobe.c @@ -0,0 +1,1215 @@ +/* + * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: nsprobe.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PROBES 1000 + +static dns_client_t *client = NULL; +static isc_task_t *probe_task = NULL; +static isc_appctx_t *actx = NULL; +static isc_mem_t *mctx = NULL; +static unsigned int outstanding_probes = 0; +const char *cacheserver = "127.0.0.1"; +static FILE *fp; + +typedef enum { + none, + exist, + nxdomain, + othererr, + multiplesoa, + multiplecname, + brokenanswer, + lame, + timedout, + notype, + unexpected +} query_result_t; + +struct server { + ISC_LINK(struct server) link; + + isc_sockaddr_t address; + query_result_t result_a; + query_result_t result_aaaa; +}; + +struct probe_ns { + ISC_LINK(struct probe_ns) link; + + dns_fixedname_t fixedname; + dns_name_t *name; + struct server *current_server; + ISC_LIST(struct server) servers; +}; + +struct probe_trans { + isc_boolean_t inuse; + char *domain; + dns_fixedname_t fixedname; + dns_name_t *qname; + const char **qlabel; + isc_boolean_t qname_found; + dns_clientrestrans_t *resid; + dns_message_t *qmessage; + dns_message_t *rmessage; + dns_clientreqtrans_t *reqid; + + /* NS list */ + struct probe_ns *current_ns; + ISC_LIST(struct probe_ns) nslist; +}; + +struct stat { + unsigned long valid; + unsigned long ignore; + unsigned long nxdomain; + unsigned long othererr; + unsigned long multiplesoa; + unsigned long multiplecname; + unsigned long brokenanswer; + unsigned long lame; + unsigned long unknown; +} server_stat, domain_stat; + +static unsigned long number_of_domains = 0; +static unsigned long number_of_servers = 0; +static unsigned long multiple_error_domains = 0; +static isc_boolean_t debug_mode = ISC_FALSE; +static int verbose_level = 0; +static const char *qlabels[] = {"www.", "ftp.", NULL}; +static struct probe_trans probes[MAX_PROBES]; + +static isc_result_t probe_domain(struct probe_trans *trans); +static void reset_probe(struct probe_trans *trans); +static isc_result_t fetch_nsaddress(struct probe_trans *trans); +static isc_result_t probe_name(struct probe_trans *trans, + dns_rdatatype_t type); + +/* Dump an rdataset for debug */ +static isc_result_t +print_rdataset(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + if (!debug_mode) + return (ISC_R_SUCCESS); + + isc_buffer_init(&target, t, sizeof(t)); + + if (!dns_rdataset_isassociated(rdataset)) + return (ISC_R_SUCCESS); + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +print_name(dns_name_t *name) { + isc_result_t result; + isc_buffer_t target; + isc_region_t r; + char t[4096]; + + isc_buffer_init(&target, t, sizeof(t)); + result = dns_name_totext(name, ISC_TRUE, &target); + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + } else + printf("(invalid name)"); + + return (result); +} + +static isc_result_t +print_address(FILE *fp, isc_sockaddr_t *addr) { + char buf[NI_MAXHOST]; + + if (getnameinfo(&addr->type.sa, addr->length, buf, sizeof(buf), + NULL, 0, NI_NUMERICHOST) == 0) { + fprintf(fp, "%s", buf); + } else { + fprintf(fp, "(invalid address)"); + } + + return (ISC_R_SUCCESS); +} + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (*taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (*timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (*socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (*actxp != NULL) + isc_appctx_destroy(actxp); + + if (*mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +/* + * Common routine to make query data + */ +static isc_result_t +make_querymessage(dns_message_t *message, dns_name_t *qname0, + dns_rdatatype_t rdtype) +{ + dns_name_t *qname = NULL; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + + message->opcode = dns_opcode_query; + message->rdclass = dns_rdataclass_in; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_name_init(qname, NULL); + dns_name_clone(qname0, qname); + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + if (message != NULL) + dns_message_destroy(&message); + return (result); +} + +/* + * Update statistics + */ +static inline void +increment_entry(unsigned long *entryp) { + (*entryp)++; + INSIST(*entryp != 0); /* check overflow */ +} + +static void +update_stat(struct probe_trans *trans) { + struct probe_ns *pns; + struct server *server; + struct stat local_stat; + unsigned int err_count = 0; + const char *stattype; + + increment_entry(&number_of_domains); + memset(&local_stat, 0, sizeof(local_stat)); + + /* Update per sever statistics */ + for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); server != NULL; + server = ISC_LIST_NEXT(server, link)) { + increment_entry(&number_of_servers); + + if (server->result_aaaa == exist || + server->result_aaaa == notype) { + /* + * Don't care about the result of A query if + * the answer to AAAA query was expected. + */ + stattype = "valid"; + increment_entry(&server_stat.valid); + increment_entry(&local_stat.valid); + } else if (server->result_a == exist) { + switch (server->result_aaaa) { + case exist: + case notype: + stattype = "valid"; + increment_entry(&server_stat.valid); + increment_entry(&local_stat.valid); + break; + case timedout: + stattype = "ignore"; + increment_entry(&server_stat.ignore); + increment_entry(&local_stat.ignore); + break; + case nxdomain: + stattype = "nxdomain"; + increment_entry(&server_stat.nxdomain); + increment_entry(&local_stat.nxdomain); + break; + case othererr: + stattype = "othererr"; + increment_entry(&server_stat.othererr); + increment_entry(&local_stat.othererr); + break; + case multiplesoa: + stattype = "multiplesoa"; + increment_entry(&server_stat.multiplesoa); + increment_entry(&local_stat.multiplesoa); + break; + case multiplecname: + stattype = "multiplecname"; + increment_entry(&server_stat.multiplecname); + increment_entry(&local_stat.multiplecname); + break; + case brokenanswer: + stattype = "brokenanswer"; + increment_entry(&server_stat.brokenanswer); + increment_entry(&local_stat.brokenanswer); + break; + case lame: + stattype = "lame"; + increment_entry(&server_stat.lame); + increment_entry(&local_stat.lame); + break; + default: + stattype = "unknown"; + increment_entry(&server_stat.unknown); + increment_entry(&local_stat.unknown); + break; + } + } else { + stattype = "unknown"; + increment_entry(&server_stat.unknown); + increment_entry(&local_stat.unknown); + } + + if (verbose_level > 1 || + (verbose_level == 1 && + strcmp(stattype, "valid") != 0 && + strcmp(stattype, "unknown") != 0)) { + print_name(pns->name); + putchar('('); + print_address(stdout, &server->address); + printf(") for %s:%s\n", trans->domain, + stattype); + } + } + } + + /* Update per domain statistics */ + if (local_stat.ignore > 0) { + if (verbose_level > 0) + printf("%s:ignore\n", trans->domain); + increment_entry(&domain_stat.ignore); + err_count++; + } + if (local_stat.nxdomain > 0) { + if (verbose_level > 0) + printf("%s:nxdomain\n", trans->domain); + increment_entry(&domain_stat.nxdomain); + err_count++; + } + if (local_stat.othererr > 0) { + if (verbose_level > 0) + printf("%s:othererr\n", trans->domain); + increment_entry(&domain_stat.othererr); + err_count++; + } + if (local_stat.multiplesoa > 0) { + if (verbose_level > 0) + printf("%s:multiplesoa\n", trans->domain); + increment_entry(&domain_stat.multiplesoa); + err_count++; + } + if (local_stat.multiplecname > 0) { + if (verbose_level > 0) + printf("%s:multiplecname\n", trans->domain); + increment_entry(&domain_stat.multiplecname); + err_count++; + } + if (local_stat.brokenanswer > 0) { + if (verbose_level > 0) + printf("%s:brokenanswer\n", trans->domain); + increment_entry(&domain_stat.brokenanswer); + err_count++; + } + if (local_stat.lame > 0) { + if (verbose_level > 0) + printf("%s:lame\n", trans->domain); + increment_entry(&domain_stat.lame); + err_count++; + } + + if (err_count > 1) + increment_entry(&multiple_error_domains); + + /* + * We regard the domain as valid if and only if no authoritative server + * has a problem and at least one server is known to be valid. + */ + if (local_stat.valid > 0 && err_count == 0) { + if (verbose_level > 1) + printf("%s:valid\n", trans->domain); + increment_entry(&domain_stat.valid); + } + + /* + * If the domain has no available server or all servers have the + * 'unknown' result, the domain's result is also regarded as unknown. + */ + if (local_stat.valid == 0 && err_count == 0) { + if (verbose_level > 1) + printf("%s:unknown\n", trans->domain); + increment_entry(&domain_stat.unknown); + } +} + +/* + * Search for an existent name with an A RR + */ + +static isc_result_t +set_nextqname(struct probe_trans *trans) { + isc_result_t result; + size_t domainlen; + isc_buffer_t b; + char buf[4096]; /* XXX ad-hoc constant, but should be enough */ + + if (*trans->qlabel == NULL) + return (ISC_R_NOMORE); + + result = isc_string_copy(buf, sizeof(buf), *trans->qlabel); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_string_append(buf, sizeof(buf), trans->domain); + if (result != ISC_R_SUCCESS) + return (result); + + domainlen = strlen(buf); + isc_buffer_init(&b, buf, domainlen); + isc_buffer_add(&b, domainlen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, + 0, NULL); + + trans->qlabel++; + + return (result); +} + +static void +request_done(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event; + dns_message_t *rmessage; + struct probe_ns *pns; + struct server *server; + isc_result_t result; + query_result_t *resultp; + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_rdatatype_t type; + + REQUIRE(task == probe_task); + REQUIRE(trans != NULL && trans->inuse == ISC_TRUE); + rmessage = rev->rmessage; + REQUIRE(rmessage == trans->rmessage); + INSIST(outstanding_probes > 0); + + server = trans->current_ns->current_server; + INSIST(server != NULL); + + if (server->result_a == none) { + type = dns_rdatatype_a; + resultp = &server->result_a; + } else { + resultp = &server->result_aaaa; + type = dns_rdatatype_aaaa; + } + + if (rev->result == ISC_R_SUCCESS) { + if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0) + *resultp = lame; + else if (rmessage->rcode == dns_rcode_nxdomain) + *resultp = nxdomain; + else if (rmessage->rcode != dns_rcode_noerror) + *resultp = othererr; + else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) { + /* no error but empty answer */ + *resultp = notype; + } else { + result = dns_message_firstname(rmessage, + DNS_SECTION_ANSWER); + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_ANSWER, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type == + dns_rdatatype_cname || + rdataset->type == + dns_rdatatype_dname) { + /* Should chase the chain? */ + *resultp = exist; + goto found; + } else if (rdataset->type == type) { + *resultp = exist; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_ANSWER); + } + + /* + * Something unexpected happened: the response + * contained a non-empty authoritative answer, but we + * could not find an expected result. + */ + *resultp = unexpected; + } + } else if (rev->result == DNS_R_RECOVERABLE || + rev->result == DNS_R_BADLABELTYPE) { + /* Broken response. Try identifying known cases. */ + *resultp = brokenanswer; + + if (rmessage->counts[DNS_SECTION_ANSWER] > 0) { + result = dns_message_firstname(rmessage, + DNS_SECTION_ANSWER); + while (result == ISC_R_SUCCESS) { + /* + * Check to see if the response has multiple + * CNAME RRs. Update the result code if so. + */ + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_ANSWER, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + if (rdataset->type == + dns_rdatatype_cname && + dns_rdataset_count(rdataset) > 1) { + *resultp = multiplecname; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_ANSWER); + } + } + + if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) { + result = dns_message_firstname(rmessage, + DNS_SECTION_AUTHORITY); + while (result == ISC_R_SUCCESS) { + /* + * Check to see if the response has multiple + * SOA RRs. Update the result code if so. + */ + name = NULL; + dns_message_currentname(rmessage, + DNS_SECTION_AUTHORITY, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, + link)) { + if (rdataset->type == + dns_rdatatype_soa && + dns_rdataset_count(rdataset) > 1) { + *resultp = multiplesoa; + goto found; + } + } + result = dns_message_nextname(rmessage, + DNS_SECTION_AUTHORITY); + } + } + } else if (rev->result == ISC_R_TIMEDOUT) + *resultp = timedout; + else { + fprintf(stderr, "unexpected result: %d (domain=%s, server=", + rev->result, trans->domain); + print_address(stderr, &server->address); + fputc('\n', stderr); + *resultp = unexpected; + } + + found: + INSIST(*resultp != none); + if (type == dns_rdatatype_a && *resultp == exist) + trans->qname_found = ISC_TRUE; + + dns_client_destroyreqtrans(&trans->reqid); + isc_event_free(&event); + dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE); + + result = probe_name(trans, type); + if (result == ISC_R_NOMORE) { + /* We've tried all addresses of all servers. */ + if (type == dns_rdatatype_a && trans->qname_found) { + /* + * If we've explored A RRs and found an existent + * record, we can move to AAAA. + */ + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + probe_name(trans, dns_rdatatype_aaaa); + result = ISC_R_SUCCESS; + } else if (type == dns_rdatatype_a) { + /* + * No server provided an existent A RR of this name. + * Try next label. + */ + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + result = set_nextqname(trans); + if (result == ISC_R_SUCCESS) { + trans->current_ns = + ISC_LIST_HEAD(trans->nslist); + for (pns = trans->current_ns; pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); + server != NULL; + server = ISC_LIST_NEXT(server, + link)) { + INSIST(server->result_aaaa == + none); + server->result_a = none; + } + } + result = probe_name(trans, dns_rdatatype_a); + } + } + if (result != ISC_R_SUCCESS) { + /* + * We've explored AAAA RRs or failed to find a valid + * query label. Wrap up the result and move to the + * next domain. + */ + reset_probe(trans); + } + } else if (result != ISC_R_SUCCESS) + reset_probe(trans); /* XXX */ +} + +static isc_result_t +probe_name(struct probe_trans *trans, dns_rdatatype_t type) { + isc_result_t result; + struct probe_ns *pns; + struct server *server; + + REQUIRE(trans->reqid == NULL); + REQUIRE(type == dns_rdatatype_a || type == dns_rdatatype_aaaa); + + for (pns = trans->current_ns; pns != NULL; + pns = ISC_LIST_NEXT(pns, link)) { + for (server = ISC_LIST_HEAD(pns->servers); server != NULL; + server = ISC_LIST_NEXT(server, link)) { + if ((type == dns_rdatatype_a && + server->result_a == none) || + (type == dns_rdatatype_aaaa && + server->result_aaaa == none)) { + pns->current_server = server; + goto found; + } + } + } + + found: + trans->current_ns = pns; + if (pns == NULL) + return (ISC_R_NOMORE); + + INSIST(pns->current_server != NULL); + dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER); + result = make_querymessage(trans->qmessage, trans->qname, type); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_client_startrequest(client, trans->qmessage, + trans->rmessage, + &pns->current_server->address, + 0, DNS_MESSAGEPARSE_BESTEFFORT, + NULL, 120, 0, 4, + probe_task, request_done, trans, + &trans->reqid); + + return (result); +} + +/* + * Get IP addresses of NSes + */ + +static void +resolve_nsaddress(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct probe_ns *pns = trans->current_ns; + isc_result_t result; + + REQUIRE(task == probe_task); + REQUIRE(trans->inuse == ISC_TRUE); + REQUIRE(pns != NULL); + INSIST(outstanding_probes > 0); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type != dns_rdatatype_a) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_in_a_t rdata_a; + struct server *server; + + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + if (result != ISC_R_SUCCESS) + continue; + + server = isc_mem_get(mctx, sizeof(*server)); + if (server == NULL) { + fprintf(stderr, "resolve_nsaddress: " + "mem_get failed"); + result = ISC_R_NOMEMORY; + goto cleanup; + } + isc_sockaddr_fromin(&server->address, + &rdata_a.in_addr, 53); + ISC_LINK_INIT(server, link); + server->result_a = none; + server->result_aaaa = none; + ISC_LIST_APPEND(pns->servers, server, link); + } + } + } + + cleanup: + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->resid); + isc_event_free(&event); + + next_ns: + trans->current_ns = ISC_LIST_NEXT(pns, link); + if (trans->current_ns == NULL) { + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + result = set_nextqname(trans); + if (result == ISC_R_SUCCESS) + result = probe_name(trans, dns_rdatatype_a); + } else { + result = fetch_nsaddress(trans); + if (result != ISC_R_SUCCESS) + goto next_ns; /* XXX: this is unlikely to succeed */ + } + + if (result != ISC_R_SUCCESS) + reset_probe(trans); +} + +static isc_result_t +fetch_nsaddress(struct probe_trans *trans) { + struct probe_ns *pns; + + pns = trans->current_ns; + REQUIRE(pns != NULL); + + return (dns_client_startresolve(client, pns->name, dns_rdataclass_in, + dns_rdatatype_a, 0, probe_task, + resolve_nsaddress, trans, + &trans->resid)); +} + +/* + * Get NS RRset for a given domain + */ + +static void +reset_probe(struct probe_trans *trans) { + struct probe_ns *pns; + struct server *server; + isc_result_t result; + + REQUIRE(trans->resid == NULL); + REQUIRE(trans->reqid == NULL); + + update_stat(trans); + + dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER); + dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE); + + trans->inuse = ISC_FALSE; + if (trans->domain != NULL) + isc_mem_free(mctx, trans->domain); + trans->domain = NULL; + if (trans->qname != NULL) + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + trans->qlabel = qlabels; + trans->qname_found = ISC_FALSE; + trans->current_ns = NULL; + + while ((pns = ISC_LIST_HEAD(trans->nslist)) != NULL) { + ISC_LIST_UNLINK(trans->nslist, pns, link); + while ((server = ISC_LIST_HEAD(pns->servers)) != NULL) { + ISC_LIST_UNLINK(pns->servers, server, link); + isc_mem_put(mctx, server, sizeof(*server)); + } + isc_mem_put(mctx, pns, sizeof(*pns)); + } + + outstanding_probes--; + + result = probe_domain(trans); + if (result == ISC_R_NOMORE && outstanding_probes == 0) + isc_app_ctxshutdown(actx); +} + +static void +resolve_ns(isc_task_t *task, isc_event_t *event) { + struct probe_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + isc_result_t result = ISC_R_SUCCESS; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct probe_ns *pns; + + REQUIRE(task == probe_task); + REQUIRE(trans->inuse == ISC_TRUE); + INSIST(outstanding_probes > 0); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)print_rdataset(rdataset, name); + + if (rdataset->type != dns_rdatatype_ns) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_ns_t ns; + + dns_rdataset_current(rdataset, &rdata); + /* + * Extract the name from the NS record. + */ + result = dns_rdata_tostruct(&rdata, &ns, NULL); + if (result != ISC_R_SUCCESS) + continue; + + pns = isc_mem_get(mctx, sizeof(*pns)); + if (pns == NULL) { + fprintf(stderr, + "resolve_ns: mem_get failed"); + result = ISC_R_NOMEMORY; + /* + * XXX: should we continue with the + * available servers anyway? + */ + goto cleanup; + } + + dns_fixedname_init(&pns->fixedname); + pns->name = + dns_fixedname_name(&pns->fixedname); + ISC_LINK_INIT(pns, link); + ISC_LIST_APPEND(trans->nslist, pns, link); + ISC_LIST_INIT(pns->servers); + + dns_name_copy(&ns.name, pns->name, NULL); + dns_rdata_reset(&rdata); + dns_rdata_freestruct(&ns); + } + } + } + + cleanup: + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->resid); + isc_event_free(&event); + + if (!ISC_LIST_EMPTY(trans->nslist)) { + /* Go get addresses of NSes */ + trans->current_ns = ISC_LIST_HEAD(trans->nslist); + result = fetch_nsaddress(trans); + } else + result = ISC_R_FAILURE; + + if (result == ISC_R_SUCCESS) + return; + + reset_probe(trans); +} + +static isc_result_t +probe_domain(struct probe_trans *trans) { + isc_result_t result; + size_t domainlen; + isc_buffer_t b; + char buf[4096]; /* XXX ad hoc constant, but should be enough */ + char *cp; + + REQUIRE(trans != NULL); + REQUIRE(trans->inuse == ISC_FALSE); + REQUIRE(outstanding_probes < MAX_PROBES); + + /* Construct domain */ + cp = fgets(buf, sizeof(buf), fp); + if (cp == NULL) + return (ISC_R_NOMORE); + if ((cp = strchr(buf, '\n')) != NULL) /* zap NL if any */ + *cp = '\0'; + trans->domain = isc_mem_strdup(mctx, buf); + if (trans->domain == NULL) { + fprintf(stderr, + "failed to allocate memory for domain: %s", cp); + return (ISC_R_NOMEMORY); + } + + /* Start getting NS for the domain */ + domainlen = strlen(buf); + isc_buffer_init(&b, buf, domainlen); + isc_buffer_add(&b, domainlen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_client_startresolve(client, trans->qname, + dns_rdataclass_in, dns_rdatatype_ns, + 0, probe_task, resolve_ns, trans, + &trans->resid); + if (result != ISC_R_SUCCESS) + goto cleanup; + + trans->inuse = ISC_TRUE; + outstanding_probes++; + + return (ISC_R_SUCCESS); + + cleanup: + isc_mem_free(mctx, trans->domain); + dns_fixedname_invalidate(&trans->fixedname); + + return (result); +} + +static void +usage() { + fprintf(stderr, "usage: nsprobe [-d] [-v [-v...]] [-c cache_address] " + "[input_file]\n"); + + exit(1); +} + +int +main(int argc, char *argv[]) { + int i, ch, error; + struct addrinfo hints, *res; + isc_result_t result; + isc_sockaddr_t sa; + isc_sockaddrlist_t servers; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + + while ((ch = getopt(argc, argv, "c:dhv")) != -1) { + switch (ch) { + case 'c': + cacheserver = optarg; + break; + case 'd': + debug_mode = ISC_TRUE; + break; + case 'h': + usage(); + break; + case 'v': + verbose_level++; + break; + default: + usage(); + break; + } + } + + argc -= optind; + argv += optind; + + /* Common set up */ + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, + &timermgr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "ctx create failed: %d\n", result); + exit(1); + } + + isc_app_ctxstart(actx); + + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, + timermgr, 0, &client); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_createx failed: %d\n", result); + exit(1); + } + + /* Set local cache server */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + error = getaddrinfo(cacheserver, "53", &hints, &res); + if (error != 0) { + fprintf(stderr, "failed to convert server name (%s): %s\n", + cacheserver, gai_strerror(error)); + exit(1); + } + + if (res->ai_addrlen > sizeof(sa.type)) { + fprintf(stderr, + "assumption failure: addrlen is too long: %d\n", + res->ai_addrlen); + exit(1); + } + memcpy(&sa.type.sa, res->ai_addr, res->ai_addrlen); + sa.length = res->ai_addrlen; + freeaddrinfo(res); + ISC_LINK_INIT(&sa, link); + ISC_LIST_INIT(servers); + ISC_LIST_APPEND(servers, &sa, link); + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to set server: %d\n", result); + exit(1); + } + + /* Create the main task */ + probe_task = NULL; + result = isc_task_create(taskmgr, 0, &probe_task); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create task: %d\n", result); + exit(1); + } + + /* Open input file */ + if (argc == 0) + fp = stdin; + else { + fp = fopen(argv[0], "r"); + if (fp == NULL) { + fprintf(stderr, "failed to open input file: %s\n", + argv[0]); + exit(1); + } + } + + /* Set up and start probe */ + for (i = 0; i < MAX_PROBES; i++) { + probes[i].inuse = ISC_FALSE; + probes[i].domain = NULL; + dns_fixedname_init(&probes[i].fixedname); + probes[i].qname = NULL; + probes[i].qlabel = qlabels; + probes[i].qname_found = ISC_FALSE; + probes[i].resid = NULL; + ISC_LIST_INIT(probes[i].nslist); + probes[i].reqid = NULL; + + probes[i].qmessage = NULL; + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, + &probes[i].qmessage); + if (result == ISC_R_SUCCESS) { + result = dns_message_create(mctx, + DNS_MESSAGE_INTENTPARSE, + &probes[i].rmessage); + } + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "initialization failure\n"); + exit(1); + } + } + for (i = 0; i < MAX_PROBES; i++) { + result = probe_domain(&probes[i]); + if (result == ISC_R_NOMORE) + break; + else if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to issue an initial probe\n"); + exit(1); + } + } + + /* Start event loop */ + isc_app_ctxrun(actx); + + /* Dump results */ + printf("Per domain results (out of %lu domains):\n", + number_of_domains); + printf(" valid: %lu\n" + " ignore: %lu\n" + " nxdomain: %lu\n" + " othererr: %lu\n" + " multiplesoa: %lu\n" + " multiplecname: %lu\n" + " brokenanswer: %lu\n" + " lame: %lu\n" + " unknown: %lu\n" + " multiple errors: %lu\n", + domain_stat.valid, domain_stat.ignore, domain_stat.nxdomain, + domain_stat.othererr, domain_stat.multiplesoa, + domain_stat.multiplecname, domain_stat.brokenanswer, + domain_stat.lame, domain_stat.unknown, multiple_error_domains); + printf("Per server results (out of %lu servers):\n", + number_of_servers); + printf(" valid: %lu\n" + " ignore: %lu\n" + " nxdomain: %lu\n" + " othererr: %lu\n" + " multiplesoa: %lu\n" + " multiplecname: %lu\n" + " brokenanswer: %lu\n" + " lame: %lu\n" + " unknown: %lu\n", + server_stat.valid, server_stat.ignore, server_stat.nxdomain, + server_stat.othererr, server_stat.multiplesoa, + server_stat.multiplecname, server_stat.brokenanswer, + server_stat.lame, server_stat.unknown); + + /* Cleanup */ + for (i = 0; i < MAX_PROBES; i++) { + dns_message_destroy(&probes[i].qmessage); + dns_message_destroy(&probes[i].rmessage); + } + isc_task_detach(&probe_task); + dns_client_destroy(&client); + dns_lib_shutdown(); + isc_app_ctxfinish(actx); + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + + exit(0); +} diff --git a/lib/export/samples/sample-async.c b/lib/export/samples/sample-async.c new file mode 100644 index 0000000000..d209f3a066 --- /dev/null +++ b/lib/export/samples/sample-async.c @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: sample-async.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SERVERS 10 +#define MAX_QUERIES 100 + +static dns_client_t *client = NULL; +static isc_task_t *query_task = NULL; +static isc_appctx_t *query_actx = NULL; +static unsigned int outstanding_queries = 0; +static const char *def_server = "127.0.0.1"; +static FILE *fp; + +struct query_trans { + int id; + isc_boolean_t inuse; + dns_rdatatype_t type; + dns_fixedname_t fixedname; + dns_name_t *qname; + dns_namelist_t answerlist; + dns_clientrestrans_t *xid; +}; + +static struct query_trans query_array[MAX_QUERIES]; + +static isc_result_t dispatch_query(struct query_trans *trans); + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (*taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (*timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (*socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (*actxp != NULL) + isc_appctx_destroy(actxp); + + if (*mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +static isc_result_t +printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + isc_buffer_init(&target, t, sizeof(t)); + + if (!dns_rdataset_isassociated(rdataset)) + return (ISC_R_SUCCESS); + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf(" %.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +static void +process_answer(isc_task_t *task, isc_event_t *event) { + struct query_trans *trans = event->ev_arg; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_name_t *name; + dns_rdataset_t *rdataset; + isc_result_t result; + + REQUIRE(task == query_task); + REQUIRE(trans->inuse == ISC_TRUE); + REQUIRE(outstanding_queries > 0); + + printf("answer[%2d]\n", trans->id); + + if (rev->result != ISC_R_SUCCESS) + printf(" failed: %d(%s)\n", rev->result, + dns_result_totext(rev->result)); + + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + (void)printdata(rdataset, name); + } + } + + dns_client_freeresanswer(client, &rev->answerlist); + dns_client_destroyrestrans(&trans->xid); + + isc_event_free(&event); + + trans->inuse = ISC_FALSE; + dns_fixedname_invalidate(&trans->fixedname); + trans->qname = NULL; + outstanding_queries--; + + result = dispatch_query(trans); +#if 0 /* for cancel test */ + if (result == ISC_R_SUCCESS) { + static int count = 0; + + if ((++count) % 10 == 0) + dns_client_cancelresolve(trans->xid); + } +#endif + if (result == ISC_R_NOMORE && outstanding_queries == 0) + isc_app_ctxshutdown(query_actx); +} + +static isc_result_t +dispatch_query(struct query_trans *trans) { + isc_result_t result; + size_t namelen; + isc_buffer_t b; + char buf[4096]; /* XXX ad hoc constant, but should be enough */ + char *cp; + + REQUIRE(trans != NULL); + REQUIRE(trans->inuse == ISC_FALSE); + REQUIRE(ISC_LIST_EMPTY(trans->answerlist)); + REQUIRE(outstanding_queries < MAX_QUERIES); + + /* Construct qname */ + cp = fgets(buf, sizeof(buf), fp); + if (cp == NULL) + return (ISC_R_NOMORE); + /* zap NL if any */ + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + namelen = strlen(buf); + isc_buffer_init(&b, buf, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&trans->fixedname); + trans->qname = dns_fixedname_name(&trans->fixedname); + result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Start resolution */ + result = dns_client_startresolve(client, trans->qname, + dns_rdataclass_in, trans->type, 0, + query_task, process_answer, trans, + &trans->xid); + if (result != ISC_R_SUCCESS) + goto cleanup; + + trans->inuse = ISC_TRUE; + outstanding_queries++; + + return (ISC_R_SUCCESS); + + cleanup: + dns_fixedname_invalidate(&trans->fixedname); + + return (result); +} + +static void +usage() { + fprintf(stderr, "usage: sample-async [-s server_address] [-t RR type] " + "input_file\n"); + + exit(1); +} + +int +main(int argc, char *argv[]) { + int ch; + isc_textregion_t tr; + isc_mem_t *mctx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + int nservers = 0; + const char *serveraddr[MAX_SERVERS]; + isc_sockaddr_t sa[MAX_SERVERS]; + isc_sockaddrlist_t servers; + dns_rdatatype_t type = dns_rdatatype_a; + struct in_addr inaddr; + isc_result_t result; + int i; + + while ((ch = getopt(argc, argv, "s:t:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + case 's': + if (nservers == MAX_SERVERS) { + fprintf(stderr, + "too many servers (up to %d)\n", + MAX_SERVERS); + exit(1); + } + serveraddr[nservers++] = (const char *)optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 1) + usage(); + + if (nservers == 0) { + nservers = 1; + serveraddr[0] = def_server; + } + + for (i = 0; i < MAX_QUERIES; i++) { + query_array[i].id = i; + query_array[i].inuse = ISC_FALSE; + query_array[i].type = type; + dns_fixedname_init(&query_array[i].fixedname); + query_array[i].qname = NULL; + ISC_LIST_INIT(query_array[i].answerlist); + query_array[i].xid = NULL; + } + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = ctxs_init(&mctx, &query_actx, &taskmgr, &socketmgr, + &timermgr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "ctx create failed: %d\n", result); + exit(1); + } + + isc_app_ctxstart(query_actx); + + result = dns_client_createx(mctx, query_actx, taskmgr, socketmgr, + timermgr, 0, &client); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_createx failed: %d\n", result); + exit(1); + } + + /* Set nameservers */ + ISC_LIST_INIT(servers); + for (i = 0; i < nservers; i++) { + if (inet_pton(AF_INET, serveraddr[i], &inaddr) != 1) { + fprintf(stderr, "failed to parse IPv4 address %s\n", + serveraddr[i]); + exit(1); + } + isc_sockaddr_fromin(&sa[i], &inaddr, 53); + ISC_LIST_APPEND(servers, &sa[i], link); + } + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } + + /* Create the main task */ + query_task = NULL; + result = isc_task_create(taskmgr, 0, &query_task); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create task: %d\n", result); + exit(1); + } + + /* Open input file */ + fp = fopen(argv[0], "r"); + if (fp == NULL) { + fprintf(stderr, "failed to open input file: %s\n", argv[1]); + exit(1); + } + + /* Dispatch initial queries */ + for (i = 0; i < MAX_QUERIES; i++) { + result = dispatch_query(&query_array[i]); + if (result == ISC_R_NOMORE) + break; + } + + /* Start event loop */ + isc_app_ctxrun(query_actx); + + /* Sanity check */ + for (i = 0; i < MAX_QUERIES; i++) + INSIST(query_array[i].inuse == ISC_FALSE); + + /* Cleanup */ + isc_task_detach(&query_task); + dns_client_destroy(&client); + dns_lib_shutdown(); + isc_app_ctxfinish(query_actx); + ctxs_destroy(&mctx, &query_actx, &taskmgr, &socketmgr, &timermgr); + + exit(0); +} diff --git a/lib/export/samples/sample-gai.c b/lib/export/samples/sample-gai.c new file mode 100644 index 0000000000..321004ef04 --- /dev/null +++ b/lib/export/samples/sample-gai.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: sample-gai.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include + +#include +#include +#include + +static void +do_gai(int family, char *hostname) { + struct addrinfo hints, *res, *res0; + int error; + char namebuf[1024], addrbuf[1024], servbuf[1024]; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(hostname, "http", &hints, &res0); + if (error) { + fprintf(stderr, "getaddrinfo failed for %s,family=%d: %s\n", + hostname, family, gai_strerror(error)); + return; + } + + for (res = res0; res; res = res->ai_next) { + error = getnameinfo(res->ai_addr, res->ai_addrlen, + addrbuf, sizeof(addrbuf), + NULL, 0, NI_NUMERICHOST); + if (error == 0) + error = getnameinfo(res->ai_addr, res->ai_addrlen, + namebuf, sizeof(namebuf), + servbuf, sizeof(servbuf), 0); + if (error != 0) { + fprintf(stderr, "getnameinfo failed: %s\n", + gai_strerror(error)); + } else { + printf("%s(%s/%s)=%s:%s\n", hostname, + res->ai_canonname, addrbuf, namebuf, servbuf); + } + } + + freeaddrinfo(res); +} + +int +main(int argc, char *argv[]) { + if (argc < 2) + exit(1); + + do_gai(AF_INET, argv[1]); + do_gai(AF_INET6, argv[1]); + do_gai(AF_UNSPEC, argv[1]); + + exit(0); +} diff --git a/lib/export/samples/sample-request.c b/lib/export/samples/sample-request.c new file mode 100644 index 0000000000..75242ee410 --- /dev/null +++ b/lib/export/samples/sample-request.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: sample-request.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static isc_mem_t *mctx; +static dns_fixedname_t fixedqname; + +static void +usage() { + fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n"); + + exit(1); +} + +static isc_result_t +make_querymessage(dns_message_t *message, const char *namestr, + dns_rdatatype_t rdtype) +{ + dns_name_t *qname = NULL, *qname0; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + isc_buffer_t b; + size_t namelen; + + /* Construct qname */ + namelen = strlen(namestr); + isc_buffer_init(&b, namestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fixedqname); + qname0 = dns_fixedname_name(&fixedqname); + result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to convert qname: %d\n", result); + return (result); + } + + /* Construct query message */ + message->opcode = dns_opcode_query; + message->rdclass = dns_rdataclass_in; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_name_init(qname, NULL); + dns_name_clone(qname0, qname); + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + if (message != NULL) + dns_message_destroy(&message); + return (result); +} + +static void +print_section(dns_message_t *message, int section, isc_buffer_t *buf) { + isc_result_t result; + isc_region_t r; + + result = dns_message_sectiontotext(message, section, + &dns_master_style_full, 0, buf); + if (result != ISC_R_SUCCESS) + goto fail; + + isc_buffer_usedregion(buf, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return; + + fail: + fprintf(stderr, "failed to convert a section\n"); +} + +int +main(int argc, char *argv[]) { + int ch, i, gai_error; + struct addrinfo hints, *res; + isc_textregion_t tr; + dns_client_t *client = NULL; + isc_result_t result; + isc_sockaddr_t sa; + dns_message_t *qmessage, *rmessage; + dns_rdatatype_t type = dns_rdatatype_a; + isc_buffer_t *outputbuf; + + while ((ch = getopt(argc, argv, "t:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + result = dns_client_create(&client, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Prepare message structures */ + mctx = NULL; + qmessage = NULL; + rmessage = NULL; + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a memory context\n"); + exit(1); + } + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); + if (result == ISC_R_SUCCESS) { + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, + &rmessage); + } + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create messages\n"); + exit(1); + } + + /* Initialize the nameserver address */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(argv[0], "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa.type)); + memcpy(&sa.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa.length = res->ai_addrlen; + ISC_LINK_INIT(&sa, link); + + /* Construct qname */ + result = make_querymessage(qmessage, argv[1], type); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a query\n"); + exit(1); + } + + /* Send request and wait for a response */ + result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, + NULL, 60, 0, 3); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to get a response: %s\n", + dns_result_totext(result)); + } + + /* Dump the response */ + outputbuf = NULL; + result = isc_buffer_allocate(mctx, &outputbuf, 65535); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to allocate a result buffer\n"); + exit(1); + } + for (i = 0; i < DNS_SECTION_MAX; i++) { + print_section(rmessage, i, outputbuf); + isc_buffer_clear(outputbuf); + } + isc_buffer_free(&outputbuf); + + /* Cleanup */ + dns_message_destroy(&qmessage); + dns_message_destroy(&rmessage); + isc_mem_destroy(&mctx); + dns_client_destroy(&client); + dns_lib_shutdown(); + + exit(0); +} diff --git a/lib/export/samples/sample-update.c b/lib/export/samples/sample-update.c new file mode 100644 index 0000000000..e186f536d6 --- /dev/null +++ b/lib/export/samples/sample-update.c @@ -0,0 +1,749 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: sample-update.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static dns_tsec_t *tsec = NULL; +static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in; +static isc_bufferlist_t usedbuffers; +static ISC_LIST(dns_rdatalist_t) usedrdatalists; + +static void setup_tsec(char *keyfile, isc_mem_t *mctx); +static void update_addordelete(isc_mem_t *mctx, char *cmdline, + isc_boolean_t isdelete, dns_name_t *name); +static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name); + +static void +usage() { + fprintf(stderr, "sample-update " + "[-a auth_server] " + "[-k keyfile] " + "[-p prerequisite] " + "[-r recursive_server] " + "[-z zonename] " + "(add|delete) \"name TTL RRtype RDATA\"\n"); + exit(1); +} + +int +main(int argc, char *argv[]) { + int ch; + struct addrinfo hints, *res; + int gai_error; + dns_client_t *client = NULL; + char *zonenamestr = NULL; + char *keyfilename = NULL; + char *prereqstr = NULL; + isc_sockaddrlist_t auth_servers; + char *auth_server = NULL; + char *recursive_server = NULL; + isc_sockaddr_t sa_auth, sa_recursive; + isc_sockaddrlist_t rec_servers; + isc_result_t result; + isc_boolean_t isdelete; + isc_buffer_t b, *buf; + dns_fixedname_t zname0, pname0, uname0; + size_t namelen; + dns_name_t *zname = NULL, *uname, *pname; + dns_rdataset_t *rdataset; + dns_rdatalist_t *rdatalist; + dns_rdata_t *rdata; + dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL; + isc_mem_t *umctx = NULL; + + while ((ch = getopt(argc, argv, "a:k:p:r:z:")) != -1) { + switch (ch) { + case 'k': + keyfilename = optarg; + break; + case 'a': + auth_server = optarg; + break; + case 'p': + prereqstr = optarg; + break; + case 'r': + recursive_server = optarg; + break; + case 'z': + zonenamestr = optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + /* command line argument validation */ + if (strcmp(argv[0], "delete") == 0) + isdelete = ISC_TRUE; + else if (strcmp(argv[0], "add") == 0) + isdelete = ISC_FALSE; + else { + fprintf(stderr, "invalid update command: %s\n", argv[0]); + exit(1); + } + + if (auth_server == NULL && recursive_server == NULL) { + fprintf(stderr, "authoritative or recursive server " + "must be specified\n"); + usage(); + } + + /* Initialization */ + ISC_LIST_INIT(usedbuffers); + ISC_LIST_INIT(usedrdatalists); + ISC_LIST_INIT(prereqlist); + ISC_LIST_INIT(auth_servers); + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + result = isc_mem_create(0, 0, &umctx); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to crate mctx\n"); + exit(1); + } + + result = dns_client_create(&client, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Set the authoritative server */ + if (auth_server != NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(auth_server, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa_auth.type)); + memcpy(&sa_auth.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa_auth.length = res->ai_addrlen; + ISC_LINK_INIT(&sa_auth, link); + + ISC_LIST_APPEND(auth_servers, &sa_auth, link); + } + + /* Set the recursive server */ + if (recursive_server != NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(recursive_server, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa_recursive.type)); + memcpy(&sa_recursive.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa_recursive.length = res->ai_addrlen; + ISC_LINK_INIT(&sa_recursive, link); + ISC_LIST_INIT(rec_servers); + ISC_LIST_APPEND(rec_servers, &sa_recursive, link); + result = dns_client_setservers(client, dns_rdataclass_in, + NULL, &rec_servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } + } + + /* Construct zone name */ + zname = NULL; + if (zonenamestr != NULL) { + namelen = strlen(zonenamestr); + isc_buffer_init(&b, zonenamestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&zname0); + zname = dns_fixedname_name(&zname0); + result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "failed to convert zone name: %d\n", + result); + } + + /* Construct prerequisite name (if given) */ + if (prereqstr != NULL) { + dns_fixedname_init(&pname0); + pname = dns_fixedname_name(&pname0); + evaluate_prereq(umctx, prereqstr, pname); + ISC_LIST_APPEND(prereqlist, pname, link); + prereqlistp = &prereqlist; + } + + /* Construct update name */ + ISC_LIST_INIT(updatelist); + dns_fixedname_init(&uname0); + uname = dns_fixedname_name(&uname0); + update_addordelete(umctx, argv[1], isdelete, uname); + ISC_LIST_APPEND(updatelist, uname, link); + + /* Set up TSIG/SIG(0) key (if given) */ + if (keyfilename != NULL) + setup_tsec(keyfilename, umctx); + + /* Perform update */ + result = dns_client_update(client, + default_rdataclass, /* XXX: fixed */ + zname, prereqlistp, &updatelist, + (auth_server == NULL) ? NULL : + &auth_servers, tsec, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "update failed: %s\n", dns_result_totext(result)); + } else + fprintf(stderr, "update succeeded\n"); + + /* Cleanup */ + while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) { + while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) { + ISC_LIST_UNLINK(pname->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + isc_mem_put(umctx, rdataset, sizeof(*rdataset)); + } + ISC_LIST_UNLINK(prereqlist, pname, link); + } + while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) { + while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) { + ISC_LIST_UNLINK(uname->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + isc_mem_put(umctx, rdataset, sizeof(*rdataset)); + } + ISC_LIST_UNLINK(updatelist, uname, link); + } + while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) { + while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) { + ISC_LIST_UNLINK(rdatalist->rdata, rdata, link); + isc_mem_put(umctx, rdata, sizeof(*rdata)); + } + ISC_LIST_UNLINK(usedrdatalists, rdatalist, link); + isc_mem_put(umctx, rdatalist, sizeof(*rdatalist)); + } + while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) { + ISC_LIST_UNLINK(usedbuffers, buf, link); + isc_buffer_free(&buf); + } + if (tsec != NULL) + dns_tsec_destroy(&tsec); + isc_mem_destroy(&umctx); + dns_client_destroy(&client); + dns_lib_shutdown(); + + exit(0); +} + +/* + * Subroutines borrowed from nsupdate.c + */ +#define MAXWIRE (64 * 1024) +#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ + +static char * +nsu_strsep(char **stringp, const char *delim) { + char *string = *stringp; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) + return (NULL); + + for (; *string != '\0'; string++) { + sc = *string; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) + break; + } + if (dc == 0) + break; + } + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return (string); + } + } + } + *stringp = NULL; + return (string); +} + +static void +fatal(const char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + +static inline void +check_result(isc_result_t result, const char *msg) { + if (result != ISC_R_SUCCESS) + fatal("%s: %s", msg, isc_result_totext(result)); +} + +static void +parse_name(char **cmdlinep, dns_name_t *name) { + isc_result_t result; + char *word; + isc_buffer_t source; + + word = nsu_strsep(cmdlinep, " \t\r\n"); + if (*word == 0) { + fprintf(stderr, "could not read owner name\n"); + exit(1); + } + + isc_buffer_init(&source, word, strlen(word)); + isc_buffer_add(&source, strlen(word)); + result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL); + check_result(result, "dns_name_fromtext"); + isc_buffer_invalidate(&source); +} + +static void +parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass, + dns_rdatatype_t rdatatype, dns_rdata_t *rdata) +{ + char *cmdline = *cmdlinep; + isc_buffer_t source, *buf = NULL, *newbuf = NULL; + isc_region_t r; + isc_lex_t *lex = NULL; + dns_rdatacallbacks_t callbacks; + isc_result_t result; + + while (cmdline != NULL && *cmdline != 0 && + isspace((unsigned char)*cmdline)) + cmdline++; + + if (cmdline != NULL && *cmdline != 0) { + dns_rdatacallbacks_init(&callbacks); + result = isc_lex_create(mctx, strlen(cmdline), &lex); + check_result(result, "isc_lex_create"); + isc_buffer_init(&source, cmdline, strlen(cmdline)); + isc_buffer_add(&source, strlen(cmdline)); + result = isc_lex_openbuffer(lex, &source); + check_result(result, "isc_lex_openbuffer"); + result = isc_buffer_allocate(mctx, &buf, MAXWIRE); + check_result(result, "isc_buffer_allocate"); + result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex, + dns_rootname, 0, mctx, buf, + &callbacks); + isc_lex_destroy(&lex); + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(buf, &r); + result = isc_buffer_allocate(mctx, &newbuf, r.length); + check_result(result, "isc_buffer_allocate"); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_reset(rdata); + dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); + isc_buffer_free(&buf); + ISC_LIST_APPEND(usedbuffers, newbuf, link); + } else { + fprintf(stderr, "invalid rdata format: %s\n", + isc_result_totext(result)); + isc_buffer_free(&buf); + exit(1); + } + } else { + rdata->flags = DNS_RDATA_UPDATE; + } + *cmdlinep = cmdline; +} + +static void +update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete, + dns_name_t *name) +{ + isc_result_t result; + isc_uint32_t ttl; + char *word; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t *rdataset = NULL; + isc_textregion_t region; + + /* + * Read the owner name. + */ + parse_name(&cmdline, name); + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + if (rdata == NULL) { + fprintf(stderr, "memory allocation for rdata failed\n"); + exit(1); + } + dns_rdata_init(rdata); + + /* + * If this is an add, read the TTL and verify that it's in range. + * If it's a delete, ignore a TTL if present (for compatibility). + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (!isdelete) { + fprintf(stderr, "could not read owner ttl\n"); + exit(1); + } + else { + ttl = 0; + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } + } + result = isc_parse_uint32(&ttl, word, 10); + if (result != ISC_R_SUCCESS) { + if (isdelete) { + ttl = 0; + goto parseclass; + } else { + fprintf(stderr, "ttl '%s': %s\n", word, + isc_result_totext(result)); + exit(1); + } + } + + if (isdelete) + ttl = 0; + else if (ttl > TTL_MAX) { + fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", + word, TTL_MAX); + exit(1); + } + + /* + * Read the class or type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + parseclass: + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read class or type\n"); + exit(1); + } + } + region.base = word; + region.length = strlen(word); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read type\n"); + exit(1); + } + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "'%s' is not a valid type: %s\n", + word, isc_result_totext(result)); + exit(1); + } + } else { + rdataclass = default_rdataclass; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "'%s' is not a valid class or type: " + "%s\n", word, isc_result_totext(result)); + exit(1); + } + } + + parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); + + if (isdelete) { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) + rdataclass = dns_rdataclass_any; + else + rdataclass = dns_rdataclass_none; + } else { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + fprintf(stderr, "could not read rdata\n"); + exit(1); + } + } + + doneparsing: + + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + if (rdatalist == NULL) { + fprintf(stderr, "memory allocation for rdatalist failed\n"); + exit(1); + } + dns_rdatalist_init(rdatalist); + rdatalist->type = rdatatype; + rdatalist->rdclass = rdataclass; + rdatalist->covers = rdatatype; + rdatalist->ttl = (dns_ttl_t)ttl; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(usedrdatalists, rdatalist, link); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) { + fprintf(stderr, "memory allocation for rdataset failed\n"); + exit(1); + } + dns_rdataset_init(rdataset); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +static void +make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive, + isc_boolean_t isrrset, dns_name_t *name) +{ + isc_result_t result; + char *word; + isc_textregion_t region; + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + + /* + * Read the owner name + */ + parse_name(&cmdline, name); + + /* + * If this is an rrset prereq, read the class or type. + */ + if (isrrset) { + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read class or type\n"); + exit(1); + } + region.base = word; + region.length = strlen(word); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read type\n"); + exit(1); + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + exit(1); + } + } else { + rdataclass = default_rdataclass; + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + exit(1); + } + } + } else + rdatatype = dns_rdatatype_any; + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + if (rdata == NULL) { + fprintf(stderr, "memory allocation for rdata failed\n"); + exit(1); + } + dns_rdata_init(rdata); + + if (isrrset && ispositive) + parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); + else + rdata->flags = DNS_RDATA_UPDATE; + + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + if (rdatalist == NULL) { + fprintf(stderr, "memory allocation for rdatalist failed\n"); + exit(1); + } + dns_rdatalist_init(rdatalist); + rdatalist->type = rdatatype; + if (ispositive) { + if (isrrset && rdata->data != NULL) + rdatalist->rdclass = rdataclass; + else + rdatalist->rdclass = dns_rdataclass_any; + } else + rdatalist->rdclass = dns_rdataclass_none; + rdatalist->covers = 0; + rdatalist->ttl = 0; + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatatype; + ISC_LIST_INIT(rdatalist->rdata); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(usedrdatalists, rdatalist, link); + + rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + if (rdataset == NULL) { + fprintf(stderr, "memory allocation for rdataset failed\n"); + exit(1); + } + dns_rdataset_init(rdataset); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +static void +evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) { + char *word; + isc_boolean_t ispositive, isrrset; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read operation code\n"); + exit(1); + } + if (strcasecmp(word, "nxdomain") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_FALSE; + } else if (strcasecmp(word, "yxdomain") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_FALSE; + } else if (strcasecmp(word, "nxrrset") == 0) { + ispositive = ISC_FALSE; + isrrset = ISC_TRUE; + } else if (strcasecmp(word, "yxrrset") == 0) { + ispositive = ISC_TRUE; + isrrset = ISC_TRUE; + } else { + fprintf(stderr, "incorrect operation code: %s\n", word); + exit(1); + } + + make_prereq(mctx, cmdline, ispositive, isrrset, name); +} + +static void +setup_tsec(char *keyfile, isc_mem_t *mctx) { + dst_key_t *dstkey = NULL; + isc_result_t result; + dns_tsectype_t tsectype; + + result = dst_key_fromnamedfile(keyfile, NULL, + DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not read key from %s: %s\n", + keyfile, isc_result_totext(result)); + exit(1); + } + + if (dst_key_alg(dstkey) == DST_ALG_HMACMD5) + tsectype = dns_tsectype_tsig; + else + tsectype = dns_tsectype_sig0; + + result = dns_tsec_create(mctx, tsectype, dstkey, &tsec); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create tsec: %s\n", + isc_result_totext(result)); + exit(1); + } +} diff --git a/lib/export/samples/sample.c b/lib/export/samples/sample.c new file mode 100644 index 0000000000..64797955c6 --- /dev/null +++ b/lib/export/samples/sample.c @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: sample.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static char *algname; + +static isc_result_t +printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + if (!dns_rdataset_isassociated(rdataset)) { + printf("[WARN: empty]\n"); + return (ISC_R_SUCCESS); + } + + isc_buffer_init(&target, t, sizeof(t)); + + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +static void +usage() { + fprintf(stderr, "sample [-t RRtype] " + "[[-a algorithm] [-e] -k keyname -K keystring] " + "[-s domain:serveraddr_for_domain ] " + "server_address hostname\n"); + + exit(1); +} + +static void +set_key(dns_client_t *client, char *keynamestr, char *keystr, + isc_boolean_t is_sep, isc_mem_t **mctxp) +{ + isc_result_t result; + dns_fixedname_t fkeyname; + size_t namelen; + dns_name_t *keyname; + dns_rdata_dnskey_t keystruct; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_buffer_t b; + isc_textregion_t tr; + isc_region_t r; + dns_secalg_t alg; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to crate mctx\n"); + exit(1); + } + + if (algname != NULL) { + tr.base = algname; + tr.length = strlen(algname); + result = dns_secalg_fromtext(&alg, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to identify the algorithm\n"); + exit(1); + } + } else + alg = DNS_KEYALG_RSASHA1; + + keystruct.common.rdclass = dns_rdataclass_in; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */ + if (is_sep) + keystruct.flags |= DNS_KEYFLAG_KSK; + keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */ + keystruct.algorithm = alg; + + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + result = isc_base64_decodestring(keystr, &keydatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "base64 decode failed\n"); + exit(1); + } + isc_buffer_usedregion(&keydatabuf, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to construct key rdata\n"); + exit(1); + } + namelen = strlen(keynamestr); + isc_buffer_init(&b, keynamestr, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fkeyname); + keyname = dns_fixedname_name(&fkeyname); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to construct key name\n"); + exit(1); + } + result = dns_client_addtrustedkey(client, dns_rdataclass_in, + keyname, &rrdatabuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to add key for %s\n", + keynamestr); + exit(1); + } +} + +static void +addserver(dns_client_t *client, const char *addrstr, const char *namespace) { + struct addrinfo hints, *res; + int gai_error; + isc_sockaddr_t sa; + isc_sockaddrlist_t servers; + isc_result_t result; + size_t namelen; + isc_buffer_t b; + dns_fixedname_t fname; + dns_name_t *name = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + gai_error = getaddrinfo(addrstr, "53", &hints, &res); + if (gai_error != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gai_error)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa.type)); + memcpy(&sa.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa.length = res->ai_addrlen; + ISC_LINK_INIT(&sa, link); + ISC_LIST_INIT(servers); + ISC_LIST_APPEND(servers, &sa, link); + + if (namespace != NULL) { + namelen = strlen(namespace); + isc_buffer_init(&b, namespace, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to convert qname: %d\n", + result); + exit(1); + } + } + + result = dns_client_setservers(client, dns_rdataclass_in, name, + &servers); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "set server failed: %d\n", result); + exit(1); + } +} + +int +main(int argc, char *argv[]) { + int ch; + isc_textregion_t tr; + char *altserver = NULL; + char *altserveraddr = NULL; + char *altservername = NULL; + dns_client_t *client = NULL; + char *keynamestr = NULL; + char *keystr = NULL; + isc_result_t result; + isc_buffer_t b; + dns_fixedname_t qname0; + size_t namelen; + dns_name_t *qname, *name; + dns_rdatatype_t type = dns_rdatatype_a; + dns_rdataset_t *rdataset; + dns_namelist_t namelist; + isc_mem_t *keymctx = NULL; + unsigned int clientopt, resopt; + isc_boolean_t is_sep = ISC_FALSE; + + while ((ch = getopt(argc, argv, "a:es:t:k:K:")) != -1) { + switch (ch) { + case 't': + tr.base = optarg; + tr.length = strlen(optarg); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", optarg); + exit(1); + } + break; + case 'a': + algname = optarg; + break; + case 'e': + is_sep = ISC_TRUE; + break; + case 's': + if (altserver != NULL) { + fprintf(stderr, "alternate server " + "already defined: %s\n", + altserver); + exit(1); + } + altserver = optarg; + break; + case 'k': + keynamestr = optarg; + break; + case 'K': + keystr = optarg; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc < 2) + usage(); + + if (altserver != NULL) { + char *cp; + + cp = strchr(altserver, ':'); + if (cp == NULL) { + fprintf(stderr, "invalid alternate server: %s\n", + altserver); + exit(1); + } + *cp = '\0'; + altservername = altserver; + altserveraddr = cp + 1; + } + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %d\n", result); + exit(1); + } + + clientopt = 0; + result = dns_client_create(&client, clientopt); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %d\n", result); + exit(1); + } + + /* Set the nameserver */ + addserver(client, argv[0], NULL); + + /* Set the alternate nameserver (when specified) */ + if (altserver != NULL) + addserver(client, altserveraddr, altservername); + + /* Install DNSSEC key (if given) */ + if (keynamestr != NULL) { + if (keystr == NULL) { + fprintf(stderr, + "key string is missing " + "while key name is provided\n"); + exit(1); + } + set_key(client, keynamestr, keystr, is_sep, &keymctx); + } + + /* Construct qname */ + namelen = strlen(argv[1]); + isc_buffer_init(&b, argv[1], namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&qname0); + qname = dns_fixedname_name(&qname0); + result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "failed to convert qname: %d\n", result); + + /* Perform resolution */ + resopt = 0; + if (keynamestr == NULL) + resopt |= DNS_CLIENTRESOPT_NODNSSEC; + ISC_LIST_INIT(namelist); + result = dns_client_resolve(client, qname, dns_rdataclass_in, type, + resopt, &namelist); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "resolution failed: %s\n", dns_result_totext(result)); + } + for (name = ISC_LIST_HEAD(namelist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (printdata(rdataset, name) != ISC_R_SUCCESS) + fprintf(stderr, "print data failed\n"); + } + } + + dns_client_freeresanswer(client, &namelist); + + /* Cleanup */ + dns_client_destroy(&client); + if (keynamestr != NULL) + isc_mem_destroy(&keymctx); + dns_lib_shutdown(); + + exit(0); +} diff --git a/lib/irs/Makefile.in b/lib/irs/Makefile.in new file mode 100644 index 0000000000..9504794db1 --- /dev/null +++ b/lib/irs/Makefile.in @@ -0,0 +1,80 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:27 jinmei Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@LIBIRS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -I./include -I${srcdir}/include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} + +CDEFINES = +CWARNINGS = + +# Alphabetically +OBJS = context.@O@ \ + dnsconf.@O@ \ + gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \ + resconf.@O@ + +# Alphabetically +SRCS = context.c \ + dnsconf.c \ + gai_sterror.c getaddrinfo.c getnameinfo.c \ + resconf.c + +LIBS = @LIBS@ + +SUBDIRS = include +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libirs.@SA@: ${OBJS} version.@O@ + ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ + ${RANLIB} $@ + +libirs.la: ${OBJS} version.@O@ + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} version.@O@ ${LIBS} + +timestamp: libirs.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ ${DESTDIR}${libdir} + +clean distclean:: + rm -f libirs.@A@ libirs.la timestamp diff --git a/lib/irs/api b/lib/irs/api new file mode 100644 index 0000000000..2240cdda3a --- /dev/null +++ b/lib/irs/api @@ -0,0 +1,3 @@ +LIBINTERFACE = 50 +LIBREVISION = 1 +LIBAGE = 0 diff --git a/lib/irs/context.c b/lib/irs/context.c new file mode 100644 index 0000000000..59ecd0e63b --- /dev/null +++ b/lib/irs/context.c @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: context.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c') +#define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC) + +#ifndef RESOLV_CONF +/*% location of resolve.conf */ +#define RESOLV_CONF "/etc/resolv.conf" +#endif + +#ifndef DNS_CONF +/*% location of dns.conf */ +#define DNS_CONF "/etc/dns.conf" +#endif + +#ifndef ISC_PLATFORM_USETHREADS +irs_context_t *irs_g_context = NULL; +#else +static isc_boolean_t thread_key_initialized = ISC_FALSE; +static isc_mutex_t thread_key_mutex; +static isc_thread_key_t irs_context_key; +static isc_once_t once = ISC_ONCE_INIT; +#endif + + +struct irs_context { + /* + * An IRS context is a thread-specific object, and does not need to + * be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_taskmgr_t *taskmgr; + isc_task_t *task; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; + dns_client_t *dnsclient; + irs_resconf_t *resconf; + irs_dnsconf_t *dnsconf; +}; + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (actxp != NULL) + isc_appctx_destroy(actxp); + + if (mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +#ifdef ISC_PLATFORM_USETHREADS +static void +free_specific_context(void *arg) { + irs_context_t *context = arg; + + irs_context_destroy(&context); + + isc_thread_key_setspecific(irs_context_key, NULL); +} + +static void +thread_key_mutex_init(void) { + RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS); +} + +static isc_result_t +thread_key_init() { + isc_result_t result; + + result = isc_once_do(&once, thread_key_mutex_init); + if (result != ISC_R_SUCCESS) + return (result); + + if (!thread_key_initialized) { + LOCK(&thread_key_mutex); + + if (!thread_key_initialized && + isc_thread_key_create(&irs_context_key, + free_specific_context) != 0) { + result = ISC_R_FAILURE; + } else + thread_key_initialized = ISC_TRUE; + + UNLOCK(&thread_key_mutex); + } + + return (result); +} +#endif /* ISC_PLATFORM_USETHREADS */ + +isc_result_t +irs_context_get(irs_context_t **contextp) { + irs_context_t *context; + isc_result_t result; + + REQUIRE(contextp != NULL && *contextp == NULL); + +#ifndef ISC_PLATFORM_USETHREADS + if (irs_g_context == NULL) { + result = irs_context_create(&irs_g_context); + if (result != ISC_R_SUCCESS) + return (result); + } + + context = irs_g_context; +#else + result = thread_key_init(); + if (result != ISC_R_SUCCESS) + return (result); + + context = isc_thread_key_getspecific(irs_context_key); + if (context == NULL) { + result = irs_context_create(&context); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_thread_key_setspecific(irs_context_key, context); + if (result != ISC_R_SUCCESS) { + irs_context_destroy(&context); + return (result); + } + } +#endif /* ISC_PLATFORM_USETHREADS */ + + *contextp = context; + + return (ISC_R_SUCCESS); +} + +isc_result_t +irs_context_create(irs_context_t **contextp) { + isc_result_t result; + irs_context_t *context; + isc_appctx_t *actx = NULL; + isc_mem_t *mctx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + dns_client_t *client = NULL; + isc_sockaddrlist_t *nameservers; + irs_dnsconf_dnskeylist_t *trustedkeys; + irs_dnsconf_dnskey_t *trustedkey; + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) + return (result); + + result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_app_ctxstart(actx); + if (result != ISC_R_SUCCESS) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (result); + } + + context = isc_mem_get(mctx, sizeof(*context)); + if (context == NULL) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (ISC_R_NOMEMORY); + } + + context->mctx = mctx; + context->actx = actx; + context->taskmgr = taskmgr; + context->socketmgr = socketmgr; + context->timermgr = timermgr; + context->resconf = NULL; + context->dnsconf = NULL; + context->task = NULL; + result = isc_task_create(taskmgr, 0, &context->task); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Create a DNS client object */ + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, + 0, &client); + if (result != ISC_R_SUCCESS) + goto fail; + context->dnsclient = client; + + /* Read resolver configuration file */ + result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf); + if (result != ISC_R_SUCCESS) + goto fail; + /* Set nameservers */ + nameservers = irs_resconf_getnameservers(context->resconf); + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + nameservers); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Read advanced DNS configuration (if any) */ + result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf); + if (result != ISC_R_SUCCESS) + goto fail; + trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf); + for (trustedkey = ISC_LIST_HEAD(*trustedkeys); + trustedkey != NULL; + trustedkey = ISC_LIST_NEXT(trustedkey, link)) { + result = dns_client_addtrustedkey(client, dns_rdataclass_in, + trustedkey->keyname, + trustedkey->keydatabuf); + if (result != ISC_R_SUCCESS) + goto fail; + } + + context->magic = IRS_CONTEXT_MAGIC; + *contextp = context; + + return (ISC_R_SUCCESS); + + fail: + if (context->task != NULL) + isc_task_detach(&context->task); + if (context->resconf != NULL) + irs_resconf_destroy(&context->resconf); + if (context->dnsconf != NULL) + irs_dnsconf_destroy(&context->dnsconf); + if (client != NULL) + dns_client_destroy(&client); + ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr); + isc_mem_putanddetach(&mctx, context, sizeof(*context)); + + return (result); +} + +void +irs_context_destroy(irs_context_t **contextp) { + irs_context_t *context; + + REQUIRE(contextp != NULL); + context = *contextp; + REQUIRE(IRS_CONTEXT_VALID(context)); + + isc_task_detach(&context->task); + irs_dnsconf_destroy(&context->dnsconf); + irs_resconf_destroy(&context->resconf); + dns_client_destroy(&context->dnsclient); + + ctxs_destroy(NULL, &context->actx, &context->taskmgr, + &context->socketmgr, &context->timermgr); + + context->magic = 0; + + isc_mem_putanddetach(&context->mctx, context, sizeof(*context)); + + *contextp = NULL; + +#ifndef ISC_PLATFORM_USETHREADS + irs_g_context = NULL; +#else + (void)isc_thread_key_setspecific(irs_context_key, NULL); +#endif +} + +isc_mem_t * +irs_context_getmctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->mctx); +} + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->actx); +} + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->taskmgr); +} + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->timermgr); +} + +isc_task_t * +irs_context_gettask(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->task); +} + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsclient); +} + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->resconf); +} + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsconf); +} diff --git a/lib/irs/dnsconf.c b/lib/irs/dnsconf.c new file mode 100644 index 0000000000..1aa339e103 --- /dev/null +++ b/lib/irs/dnsconf.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dnsconf.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +/*! \file */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g') +#define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC) + +/*! + * configuration data structure + */ + +struct irs_dnsconf { + unsigned int magic; + isc_mem_t *mctx; + irs_dnsconf_dnskeylist_t trusted_keylist; +}; + +static isc_result_t +configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, + dns_rdataclass_t rdclass) +{ + isc_mem_t *mctx = conf->mctx; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key, *keylist; + dns_fixedname_t fkeyname; + dns_name_t *keyname_base, *keyname; + const cfg_listelt_t *element, *element2; + isc_result_t result; + isc_uint32_t flags, proto, alg; + const char *keystr, *keynamestr; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf_base, *keydatabuf; + dns_rdata_dnskey_t keystruct; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + isc_buffer_t namebuf; + irs_dnsconf_dnskey_t *keyent; + + cfg_map_get(cfgobj, "trusted-keys", &keys); + if (keys == NULL) + return (ISC_R_SUCCESS); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) { + keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + keydatabuf = NULL; + keyname = NULL; + + key = cfg_listelt_value(element2); + + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); + proto = cfg_obj_asuint32(cfg_tuple_get(key, + "protocol")); + alg = cfg_obj_asuint32(cfg_tuple_get(key, + "algorithm")); + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, + "name")); + + keystruct.common.rdclass = rdclass; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.mctx = NULL; + ISC_LINK_INIT(&keystruct.common, link); + + if (flags > 0xffff) + return (ISC_R_RANGE); + if (proto > 0xff) + return (ISC_R_RANGE); + if (alg > 0xff) + return (ISC_R_RANGE); + keystruct.flags = (isc_uint16_t)flags; + keystruct.protocol = (isc_uint8_t)proto; + keystruct.algorithm = (isc_uint8_t)alg; + + isc_buffer_init(&keydatabuf_base, keydata, + sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + /* Configure key value */ + keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); + result = isc_base64_decodestring(keystr, + &keydatabuf_base); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&keydatabuf_base, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, + keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&rrdatabuf, &r); + result = isc_buffer_allocate(mctx, &keydatabuf, + r.length); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_copyregion(keydatabuf, &r); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Configure key name */ + dns_fixedname_init(&fkeyname); + keyname_base = dns_fixedname_name(&fkeyname); + isc_buffer_init(&namebuf, keynamestr, + strlen(keynamestr)); + isc_buffer_add(&namebuf, strlen(keynamestr)); + result = dns_name_fromtext(keyname_base, &namebuf, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + keyname = isc_mem_get(mctx, sizeof(*keyname)); + if (keyname == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + dns_name_init(keyname, NULL); + result = dns_name_dup(keyname_base, mctx, keyname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add the key data to the list */ + keyent = isc_mem_get(mctx, sizeof(*keyent)); + if (keyent == NULL) { + dns_name_free(keyname, mctx); + result = ISC_R_NOMEMORY; + goto cleanup; + } + keyent->keyname = keyname; + keyent->keydatabuf = keydatabuf; + + ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); + } + } + + return (ISC_R_SUCCESS); + + cleanup: + if (keydatabuf != NULL) + isc_buffer_free(&keydatabuf); + if (keyname != NULL) + isc_mem_put(mctx, keyname, sizeof(*keyname)); + + return (result); +} + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp) +{ + irs_dnsconf_t *conf; + cfg_parser_t *parser = NULL; + cfg_obj_t *cfgobj = NULL; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->trusted_keylist); + + /* + * If the specified file does not exist, we'll simply with an empty + * configuration. + */ + if (!isc_file_exists(filename)) + goto cleanup; + + result = cfg_parser_create(mctx, NULL, &parser); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(parser, filename, &cfg_type_dnsconf, + &cfgobj); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in); + + cleanup: + if (parser != NULL) { + if (cfgobj != NULL) + cfg_obj_destroy(parser, &cfgobj); + cfg_parser_destroy(&parser); + } + + conf->magic = IRS_DNSCONF_MAGIC; + + if (result == ISC_R_SUCCESS) + *confp = conf; + else + irs_dnsconf_destroy(&conf); + + return (result); +} + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp) { + irs_dnsconf_t *conf; + irs_dnsconf_dnskey_t *keyent; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_DNSCONF_VALID(conf)); + + while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) { + ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link); + + isc_buffer_free(&keyent->keydatabuf); + dns_name_free(keyent->keyname, conf->mctx); + isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t)); + isc_mem_put(conf->mctx, keyent, sizeof(*keyent)); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) { + REQUIRE(IRS_DNSCONF_VALID(conf)); + + return (&conf->trusted_keylist); +} diff --git a/lib/irs/gai_strerror.c b/lib/irs/gai_strerror.c new file mode 100644 index 0000000000..ce31df95c6 --- /dev/null +++ b/lib/irs/gai_strerror.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: gai_strerror.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +/*! \file gai_strerror.c + * gai_strerror() returns an error message corresponding to an + * error code returned by getaddrinfo() and getnameinfo(). The following error + * codes and their meaning are defined in + * \link netdb.h include/irs/netdb.h.\endlink + * This implementation is almost an exact copy of lwres/gai_sterror.c except + * that it catches up the latest API standard, RFC3493. + * + * \li #EAI_ADDRFAMILY address family for hostname not supported + * \li #EAI_AGAIN temporary failure in name resolution + * \li #EAI_BADFLAGS invalid value for ai_flags + * \li #EAI_FAIL non-recoverable failure in name resolution + * \li #EAI_FAMILY ai_family not supported + * \li #EAI_MEMORY memory allocation failure + * \li #EAI_NODATA no address associated with hostname (obsoleted in RFC3493) + * \li #EAI_NONAME hostname nor servname provided, or not known + * \li #EAI_SERVICE servname not supported for ai_socktype + * \li #EAI_SOCKTYPE ai_socktype not supported + * \li #EAI_SYSTEM system error returned in errno + * \li #EAI_BADHINTS Invalid value for hints (non-standard) + * \li #EAI_PROTOCOL Resolved protocol is unknown (non-standard) + * \li #EAI_OVERFLOW Argument buffer overflow + * \li #EAI_INSECUREDATA Insecure Data (experimental) + * + * The message invalid error code is returned if ecode is out of range. + * + * ai_flags, ai_family and ai_socktype are elements of the struct + * addrinfo used by lwres_getaddrinfo(). + * + * \section gai_strerror_see See Also + * + * strerror(), getaddrinfo(), getnameinfo(), RFC3493. + */ +#include + +/*% Text of error messages. */ +static const char *gai_messages[] = { + "no error", + "address family for hostname not supported", + "temporary failure in name resolution", + "invalid value for ai_flags", + "non-recoverable failure in name resolution", + "ai_family not supported", + "memory allocation failure", + "no address associated with hostname", + "hostname nor servname provided, or not known", + "servname not supported for ai_socktype", + "ai_socktype not supported", + "system error returned in errno", + "bad hints", + "bad protocol", + "argument buffer overflow", + "insecure data provided" +}; + +/*% + * Returns an error message corresponding to an error code returned by + * getaddrinfo() and getnameinfo() + */ +const char * +gai_strerror(int ecode) { + union { + const char *const_ptr; + char *deconst_ptr; + } ptr; + + if ((ecode < 0) || + (ecode >= (int)(sizeof(gai_messages)/sizeof(*gai_messages)))) + ptr.const_ptr = "invalid error code"; + else + ptr.const_ptr = gai_messages[ecode]; + return (ptr.deconst_ptr); +} diff --git a/lib/irs/getaddrinfo.c b/lib/irs/getaddrinfo.c new file mode 100644 index 0000000000..a86b82905a --- /dev/null +++ b/lib/irs/getaddrinfo.c @@ -0,0 +1,1299 @@ +/* + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: getaddrinfo.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +/*! \file */ + +/** + * getaddrinfo() is used to get a list of IP addresses and port + * numbers for host hostname and service servname as defined in RFC3493. + * hostname and servname are pointers to null-terminated strings + * or NULL. hostname is either a host name or a numeric host address + * string: a dotted decimal IPv4 address or an IPv6 address. servname is + * either a decimal port number or a service name as listed in + * /etc/services. + * + * If the operating system does not provide a struct addrinfo, the + * following structure is used: + * + * \code + * struct addrinfo { + * int ai_flags; // AI_PASSIVE, AI_CANONNAME + * int ai_family; // PF_xxx + * int ai_socktype; // SOCK_xxx + * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6 + * size_t ai_addrlen; // length of ai_addr + * char *ai_canonname; // canonical name for hostname + * struct sockaddr *ai_addr; // binary address + * struct addrinfo *ai_next; // next structure in linked list + * }; + * \endcode + * + * + * hints is an optional pointer to a struct addrinfo. This structure can + * be used to provide hints concerning the type of socket that the caller + * supports or wishes to use. The caller can supply the following + * structure elements in *hints: + * + *
    + *
  • ai_family: + * The protocol family that should be used. When ai_family is set + * to PF_UNSPEC, it means the caller will accept any protocol + * family supported by the operating system.
  • + * + *
  • ai_socktype: + * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or + * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller + * will accept any socket type.
  • + * + *
  • ai_protocol: + * indicates which transport protocol is wanted: IPPROTO_UDP or + * IPPROTO_TCP. If ai_protocol is zero the caller will accept any + * protocol.
  • + * + *
  • ai_flags: + * Flag bits. If the AI_CANONNAME bit is set, a successful call to + * getaddrinfo() will return a null-terminated string + * containing the canonical name of the specified hostname in + * ai_canonname of the first addrinfo structure returned. Setting + * the AI_PASSIVE bit indicates that the returned socket address + * structure is intended for used in a call to bind(2). In this + * case, if the hostname argument is a NULL pointer, then the IP + * address portion of the socket address structure will be set to + * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 + * address.

    + * + * When ai_flags does not set the AI_PASSIVE bit, the returned + * socket address structure will be ready for use in a call to + * connect(2) for a connection-oriented protocol or connect(2), + * sendto(2), or sendmsg(2) if a connectionless protocol was + * chosen. The IP address portion of the socket address structure + * will be set to the loopback address if hostname is a NULL + * pointer and AI_PASSIVE is not set in ai_flags.

    + * + * If ai_flags is set to AI_NUMERICHOST it indicates that hostname + * should be treated as a numeric string defining an IPv4 or IPv6 + * address and no name resolution should be attempted. + *
+ * + * All other elements of the struct addrinfo passed via hints must be + * zero. + * + * A hints of NULL is treated as if the caller provided a struct addrinfo + * initialized to zero with ai_familyset to PF_UNSPEC. + * + * After a successful call to getaddrinfo(), *res is a pointer to a + * linked list of one or more addrinfo structures. Each struct addrinfo + * in this list cn be processed by following the ai_next pointer, until a + * NULL pointer is encountered. The three members ai_family, ai_socktype, + * and ai_protocol in each returned addrinfo structure contain the + * corresponding arguments for a call to socket(2). For each addrinfo + * structure in the list, the ai_addr member points to a filled-in socket + * address structure of length ai_addrlen. + * + * All of the information returned by getaddrinfo() is dynamically + * allocated: the addrinfo structures, and the socket address structures + * and canonical host name strings pointed to by the addrinfostructures. + * Memory allocated for the dynamically allocated structures created by a + * successful call to getaddrinfo() is released by freeaddrinfo(). + * ai is a pointer to a struct addrinfo created by a call to getaddrinfo(). + * + * \section irsreturn RETURN VALUES + * + * getaddrinfo() returns zero on success or one of the error codes + * listed in gai_strerror() if an error occurs. If both hostname and + * servname are NULL getaddrinfo() returns #EAI_NONAME. + * + * \section irssee SEE ALSO + * + * getaddrinfo(), freeaddrinfo(), + * gai_strerror(), RFC3493, getservbyname(3), connect(2), + * sendto(2), sendmsg(2), socket(2). + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SA(addr) ((struct sockaddr *)(addr)) +#define SIN(addr) ((struct sockaddr_in *)(addr)) +#define SIN6(addr) ((struct sockaddr_in6 *)(addr)) +#define SLOCAL(addr) ((struct sockaddr_un *)(addr)) + +/*! \struct addrinfo + */ +static struct addrinfo + *ai_concat(struct addrinfo *ai1, struct addrinfo *ai2), + *ai_reverse(struct addrinfo *oai), + *ai_clone(struct addrinfo *oai, int family), + *ai_alloc(int family, int addrlen); +#ifdef AF_LOCAL +static int get_local(const char *name, int socktype, struct addrinfo **res); +#endif + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port); + +static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static void set_order(int, int (**)(const char *, int, struct addrinfo **, + int, int)); + +#define FOUND_IPV4 0x1 +#define FOUND_IPV6 0x2 +#define FOUND_MAX 2 + +#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) +/*% + * Get a list of IP addresses and port numbers for host hostname and + * service servname. + */ +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct servent *sp; + const char *proto; + int family, socktype, flags, protocol; + struct addrinfo *ai, *ai_list; + int err = 0; + int port, i; + int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **, + int, int); + + if (hostname == NULL && servname == NULL) + return (EAI_NONAME); + + proto = NULL; + if (hints != NULL) { + if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0) + return (EAI_BADFLAGS); + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) { + errno = EINVAL; + return (EAI_SYSTEM); + } + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + switch (family) { + case AF_UNSPEC: + switch (hints->ai_socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + break; + case AF_INET: + case AF_INET6: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_RAW: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#ifdef AF_LOCAL + case AF_LOCAL: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#endif + default: + return (EAI_FAMILY); + } + } else { + protocol = 0; + family = 0; + socktype = 0; + flags = 0; + } + +#ifdef AF_LOCAL + /*! + * First, deal with AF_LOCAL. If the family was not set, + * then assume AF_LOCAL if the first character of the + * hostname/servname is '/'. + */ + + if (hostname != NULL && + (family == AF_LOCAL || (family == 0 && *hostname == '/'))) + return (get_local(hostname, socktype, res)); + + if (servname != NULL && + (family == AF_LOCAL || (family == 0 && *servname == '/'))) + return (get_local(servname, socktype, res)); +#endif + + /* + * Ok, only AF_INET and AF_INET6 left. + */ + ai_list = NULL; + + /* + * First, look up the service name (port) if it was + * requested. If the socket type wasn't specified, then + * try and figure it out. + */ + if (servname != NULL) { + char *e; + + port = strtol(servname, &e, 10); + if (*e == '\0') { + if (socktype == 0) + return (EAI_SOCKTYPE); + if (port < 0 || port > 65535) + return (EAI_SERVICE); + port = htons((unsigned short) port); + } else { + sp = getservbyname(servname, proto); + if (sp == NULL) + return (EAI_SERVICE); + port = sp->s_port; + if (socktype == 0) { + if (strcmp(sp->s_proto, "tcp") == 0) + socktype = SOCK_STREAM; + else if (strcmp(sp->s_proto, "udp") == 0) + socktype = SOCK_DGRAM; + } + } + } else + port = 0; + + /* + * Next, deal with just a service name, and no hostname. + * (we verified that one of them was non-null up above). + */ + if (hostname == NULL && (flags & AI_PASSIVE) != 0) { + if (family == AF_INET || family == 0) { + ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); + if (ai == NULL) + return (EAI_MEMORY); + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN(ai->ai_addr)->sin_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + if (family == AF_INET6 || family == 0) { + ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); + if (ai == NULL) { + freeaddrinfo(ai_list); + return (EAI_MEMORY); + } + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN6(ai->ai_addr)->sin6_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + *res = ai_list; + return (0); + } + + /* + * If the family isn't specified or AI_NUMERICHOST specified, check + * first to see if it is a numeric address. + * Though the gethostbyname2() routine will recognize numeric addresses, + * it will only recognize the format that it is being called for. Thus, + * a numeric AF_INET address will be treated by the AF_INET6 call as + * a domain name, and vice versa. Checking for both numerics here + * avoids that. + */ + if (hostname != NULL && + (family == 0 || (flags & AI_NUMERICHOST) != 0)) { + char abuf[sizeof(struct in6_addr)]; + char nbuf[NI_MAXHOST]; + int addrsize, addroff; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + char *p, *ep; + char ntmp[NI_MAXHOST]; + isc_uint32_t scopeid; +#endif + +#ifdef IRS_HAVE_SIN6_SCOPE_ID + /* + * Scope identifier portion. + */ + ntmp[0] = '\0'; + if (strchr(hostname, '%') != NULL) { + strncpy(ntmp, hostname, sizeof(ntmp) - 1); + ntmp[sizeof(ntmp) - 1] = '\0'; + p = strchr(ntmp, '%'); + ep = NULL; + + /* + * Vendors may want to support non-numeric + * scopeid around here. + */ + + if (p != NULL) + scopeid = (isc_uint32_t)strtoul(p + 1, + &ep, 10); + if (p != NULL && ep != NULL && ep[0] == '\0') + *p = '\0'; + else { + ntmp[0] = '\0'; + scopeid = 0; + } + } else + scopeid = 0; +#endif + + if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf) + == 1) { + if (family == AF_INET6) { + /* + * Convert to a V4 mapped address. + */ + struct in6_addr *a6 = (struct in6_addr *)abuf; + memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4); + memset(&a6->s6_addr[10], 0xff, 2); + memset(&a6->s6_addr[0], 0, 10); + goto inet6_addr; + } + addrsize = sizeof(struct in_addr); + addroff = (char *)(&SIN(0)->sin_addr) - (char *)0; + family = AF_INET; + goto common; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + } else if (ntmp[0] != '\0' && + inet_pton(AF_INET6, ntmp, abuf) == 1) { + if (family && family != AF_INET6) + return (EAI_NONAME); + addrsize = sizeof(struct in6_addr); + addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; + family = AF_INET6; + goto common; +#endif + } else if (inet_pton(AF_INET6, hostname, abuf) == 1) { + if (family != 0 && family != AF_INET6) + return (EAI_NONAME); + inet6_addr: + addrsize = sizeof(struct in6_addr); + addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0; + family = AF_INET6; + + common: + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) + return (EAI_MEMORY); + ai_list = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy((char *)ai->ai_addr + addroff, abuf, addrsize); + if ((flags & AI_CANONNAME) != 0) { +#ifdef IRS_HAVE_SIN6_SCOPE_ID + if (ai->ai_family == AF_INET6) + SIN6(ai->ai_addr)->sin6_scope_id = + scopeid; +#endif + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, + nbuf, sizeof(nbuf), NULL, 0, + NI_NUMERICHOST) == 0) { + ai->ai_canonname = strdup(nbuf); + if (ai->ai_canonname == NULL) { + freeaddrinfo(ai); + return (EAI_MEMORY); + } + } else { + /* XXX raise error? */ + ai->ai_canonname = NULL; + } + } + goto done; + } else if ((flags & AI_NUMERICHOST) != 0) { + return (EAI_NONAME); + } + } + + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { + set_order(family, net_order); + for (i = 0; i < FOUND_MAX; i++) { + if (net_order[i] == NULL) + break; + err = (net_order[i])(hostname, flags, &ai_list, + socktype, port); + if (err != 0) { + if (ai_list != NULL) + freeaddrinfo(ai_list); + break; + } + } + } else + err = resolve_name(family, hostname, flags, &ai_list, + socktype, port); + + if (ai_list == NULL) { + if (err == 0) + err = EAI_NONAME; + return (err); + } + +done: + ai_list = ai_reverse(ai_list); + + *res = ai_list; + return (0); +} + +typedef struct gai_restrans { + dns_clientrestrans_t *xid; + isc_boolean_t is_inprogress; + int error; + struct addrinfo ai_sentinel; + struct gai_resstate *resstate; +} gai_restrans_t; + +typedef struct gai_resstate { + isc_mem_t *mctx; + struct gai_statehead *head; + dns_fixedname_t fixedname; + dns_name_t *qname; + gai_restrans_t *trans4; + gai_restrans_t *trans6; + ISC_LINK(struct gai_resstate) link; +} gai_resstate_t; + +typedef struct gai_statehead { + int ai_family; + int ai_flags; + int ai_socktype; + int ai_port; + isc_appctx_t *actx; + dns_client_t *dnsclient; + ISC_LIST(struct gai_resstate) resstates; + unsigned int activestates; +} gai_statehead_t; + +static isc_result_t +make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname, + const char *domain, gai_resstate_t **statep) +{ + isc_result_t result; + gai_resstate_t *state; + dns_fixedname_t fixeddomain; + dns_name_t *qdomain; + size_t namelen; + isc_buffer_t b; + isc_boolean_t need_v4 = ISC_FALSE; + isc_boolean_t need_v6 = ISC_FALSE; + + state = isc_mem_get(mctx, sizeof(*state)); + if (state == NULL) + return (ISC_R_NOMEMORY); + + /* Construct base domain name */ + namelen = strlen(domain); + isc_buffer_init(&b, domain, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&fixeddomain); + qdomain = dns_fixedname_name(&fixeddomain); + result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + /* Construct query name */ + namelen = strlen(hostname); + isc_buffer_init(&b, hostname, namelen); + isc_buffer_add(&b, namelen); + dns_fixedname_init(&state->fixedname); + state->qname = dns_fixedname_name(&state->fixedname); + result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET) + need_v4 = ISC_TRUE; + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6) + need_v6 = ISC_TRUE; + + state->trans6 = NULL; + state->trans4 = NULL; + if (need_v4) { + state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans4 == NULL) { + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans4->error = 0; + state->trans4->xid = NULL; + state->trans4->resstate = state; + state->trans4->is_inprogress = ISC_TRUE; + state->trans4->ai_sentinel.ai_next = NULL; + } + if (need_v6) { + state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans6 == NULL) { + if (state->trans4 != NULL) + isc_mem_put(mctx, state->trans4, + sizeof(*state->trans4)); + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans6->error = 0; + state->trans6->xid = NULL; + state->trans6->resstate = state; + state->trans6->is_inprogress = ISC_TRUE; + state->trans6->ai_sentinel.ai_next = NULL; + } + + state->mctx = mctx; + state->head = head; + ISC_LINK_INIT(state, link); + + *statep = state; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head, + irs_resconf_t *resconf) +{ + isc_result_t result; + irs_resconf_searchlist_t *searchlist; + irs_resconf_search_t *searchent; + gai_resstate_t *resstate, *resstate0; + + resstate0 = NULL; + result = make_resstate(mctx, head, hostname, ".", &resstate0); + if (result != ISC_R_SUCCESS) + return (result); + + searchlist = irs_resconf_getsearchlist(resconf); + for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL; + searchent = ISC_LIST_NEXT(searchent, link)) { + resstate = NULL; + result = make_resstate(mctx, head, hostname, + (const char *)searchent->domain, + &resstate); + if (result != ISC_R_SUCCESS) + break; + + ISC_LIST_APPEND(head->resstates, resstate, link); + head->activestates++; + } + + /* + * Insert the original hostname either at the head or the tail of the + * state list, depending on the number of labels contained in the + * original name and the 'ndots' configuration parameter. + */ + if (dns_name_countlabels(resstate0->qname) > + irs_resconf_getndots(resconf) + 1) { + ISC_LIST_PREPEND(head->resstates, resstate0, link); + } else + ISC_LIST_APPEND(head->resstates, resstate0, link); + head->activestates++; + + if (result != ISC_R_SUCCESS) { + while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) { + ISC_LIST_UNLINK(head->resstates, resstate, link); + if (resstate->trans4 != NULL) { + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + } + + return (result); +} + +static void +process_answer(isc_task_t *task, isc_event_t *event) { + int error = 0, family; + gai_restrans_t *trans = event->ev_arg; + gai_resstate_t *resstate; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_rdatatype_t qtype; + dns_name_t *name; + + REQUIRE(trans != NULL); + resstate = trans->resstate; + REQUIRE(resstate != NULL); + REQUIRE(task != NULL); + + if (trans == resstate->trans4) { + family = AF_INET; + qtype = dns_rdatatype_a; + } else { + INSIST(trans == resstate->trans6); + family = AF_INET6; + qtype = dns_rdatatype_aaaa; + } + + INSIST(trans->is_inprogress); + trans->is_inprogress = ISC_FALSE; + + switch (rev->result) { + case ISC_R_SUCCESS: + case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */ + case DNS_R_NCACHENXRRSET: + break; + default: + switch (rev->vresult) { + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + error = EAI_INSECUREDATA; + break; + default: + error = EAI_FAIL; + } + goto done; + } + + /* Parse the response and construct the addrinfo chain */ + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + isc_result_t result; + dns_rdataset_t *rdataset; + isc_buffer_t b; + isc_region_t r; + char t[1024]; + + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != qtype) + continue; + + if ((resstate->head->ai_flags & AI_CANONNAME) != 0) { + isc_buffer_init(&b, t, sizeof(t)); + result = dns_name_totext(name, ISC_TRUE, &b); + if (result != ISC_R_SUCCESS) { + error = EAI_FAIL; + goto done; + } + isc_buffer_putuint8(&b, '\0'); + isc_buffer_usedregion(&b, &r); + } + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + struct addrinfo *ai; + dns_rdata_t rdata; + dns_rdata_in_a_t rdata_a; + dns_rdata_in_aaaa_t rdata_aaaa; + + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) { + error = EAI_MEMORY; + goto done; + } + ai->ai_socktype = resstate->head->ai_socktype; + ai->ai_next = trans->ai_sentinel.ai_next; + trans->ai_sentinel.ai_next = ai; + + /* + * Set AF-specific parameters + * (IPv4/v6 address/port) + */ + dns_rdata_init(&rdata); + switch (family) { + case AF_INET: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_a, + NULL); + + SIN(ai->ai_addr)->sin_port = + resstate->head->ai_port; + memcpy(&SIN(ai->ai_addr)->sin_addr, + &rdata_a.in_addr, 4); + dns_rdata_freestruct(&rdata_a); + break; + case AF_INET6: + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_aaaa, + NULL); + SIN6(ai->ai_addr)->sin6_port = + resstate->head->ai_port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, + &rdata_aaaa.in6_addr, 16); + dns_rdata_freestruct(&rdata_aaaa); + break; + } + + if ((resstate->head->ai_flags & AI_CANONNAME) + != 0) { + ai->ai_canonname = + strdup((const char *)r.base); + if (ai->ai_canonname == NULL) { + error = EAI_MEMORY; + goto done; + } + } + } + } + } + + done: + dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist); + dns_client_destroyrestrans(&trans->xid); + + isc_event_free(&event); + + /* Make sure that error == 0 iff we have a non-empty list */ + if (error == 0) { + if (trans->ai_sentinel.ai_next == NULL) + error = EAI_NONAME; + } else { + if (trans->ai_sentinel.ai_next != NULL) { + freeaddrinfo(trans->ai_sentinel.ai_next); + trans->ai_sentinel.ai_next = NULL; + } + } + trans->error = error; + + /* Check whether we are done */ + if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) && + (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) { + /* + * We're done for this state. If there is no other outstanding + * state, we can exit. + */ + resstate->head->activestates--; + if (resstate->head->activestates == 0) { + isc_app_ctxsuspend(resstate->head->actx); + return; + } + + /* + * There are outstanding states, but if we are at the head + * of the state list (i.e., at the highest search priority) + * and have any answer, we can stop now by canceling the + * others. + */ + if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) { + if ((resstate->trans4 != NULL && + resstate->trans4->ai_sentinel.ai_next != NULL) || + (resstate->trans6 != NULL && + resstate->trans6->ai_sentinel.ai_next != NULL)) { + gai_resstate_t *rest; + + for (rest = ISC_LIST_NEXT(resstate, link); + rest != NULL; + rest = ISC_LIST_NEXT(rest, link)) { + if (rest->trans4 != NULL && + rest->trans4->xid != NULL) + dns_client_cancelresolve( + rest->trans4->xid); + if (rest->trans6 != NULL && + rest->trans6->xid != NULL) + dns_client_cancelresolve( + rest->trans6->xid); + } + } else { + /* + * This search fails, so we move to the tail + * of the list so that the next entry will + * have the highest priority. + */ + ISC_LIST_UNLINK(resstate->head->resstates, + resstate, link); + ISC_LIST_APPEND(resstate->head->resstates, + resstate, link); + } + } + } +} + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port) +{ + isc_result_t result; + irs_context_t *irsctx; + irs_resconf_t *conf; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_task_t *task; + int terror = 0; + int error = 0; + dns_client_t *client; + gai_resstate_t *resstate; + gai_statehead_t head; + isc_boolean_t all_fail = ISC_TRUE; + + /* get IRS context and the associated parameters */ + irsctx = NULL; + result = irs_context_get(&irsctx); + if (result != ISC_R_SUCCESS) + return (EAI_FAIL); + actx = irs_context_getappctx(irsctx); + + mctx = irs_context_getmctx(irsctx); + task = irs_context_gettask(irsctx); + conf = irs_context_getresconf(irsctx); + client = irs_context_getdnsclient(irsctx); + + /* construct resolution states */ + head.activestates = 0; + head.ai_family = family; + head.ai_socktype = socktype; + head.ai_flags = flags; + head.ai_port = port; + head.actx = actx; + head.dnsclient = client; + ISC_LIST_INIT(head.resstates); + result = make_resstates(mctx, hostname, &head, conf); + if (result != ISC_R_SUCCESS) + return (EAI_FAIL); + + for (resstate = ISC_LIST_HEAD(head.resstates); + resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) { + if (resstate->trans4 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_a, + 0, task, + process_answer, + resstate->trans4, + &resstate->trans4->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans4->is_inprogress = ISC_TRUE; + all_fail = ISC_FALSE; + } else + resstate->trans4->is_inprogress = ISC_FALSE; + } + if (resstate->trans6 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_aaaa, + 0, task, + process_answer, + resstate->trans6, + &resstate->trans6->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans6->is_inprogress = ISC_TRUE; + all_fail = ISC_FALSE; + } else + resstate->trans6->is_inprogress= ISC_FALSE; + } + } + if (!all_fail) { + /* Start all the events */ + isc_app_ctxrun(actx); + } else + error = EAI_FAIL; + + /* Cleanup */ + while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) { + int terror4 = 0, terror6 = 0; + + ISC_LIST_UNLINK(head.resstates, resstate, link); + + if (*aip == NULL) { + struct addrinfo *sentinel4 = NULL; + struct addrinfo *sentinel6 = NULL; + + if (resstate->trans4 != NULL) { + sentinel4 = + resstate->trans4->ai_sentinel.ai_next; + resstate->trans4->ai_sentinel.ai_next = NULL; + } + if (resstate->trans6 != NULL) { + sentinel6 = + resstate->trans6->ai_sentinel.ai_next; + resstate->trans6->ai_sentinel.ai_next = NULL; + } + *aip = ai_concat(sentinel4, sentinel6); + } + + if (resstate->trans4 != NULL) { + INSIST(resstate->trans4->xid == NULL); + terror4 = resstate->trans4->error; + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + INSIST(resstate->trans6->xid == NULL); + terror6 = resstate->trans6->error; + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + /* + * If the entire lookup fails, we need to choose an appropriate + * error code from individual codes. We'll try to provide as + * specific a code as possible. In general, we are going to + * find an error code other than EAI_NONAME (which is too + * generic and may actually not be problematic in some cases). + * EAI_NONAME will be set below if no better code is found. + */ + if (terror == 0 || terror == EAI_NONAME) { + if (terror4 != 0 && terror4 != EAI_NONAME) + terror = terror4; + else if (terror6 != 0 && terror6 != EAI_NONAME) + terror = terror6; + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + + if (*aip == NULL) { + error = terror; + if (error == 0) + error = EAI_NONAME; + } + +#if 1 /* XXX: enabled for finding leaks. should be cleaned up later. */ + isc_app_ctxfinish(actx); + irs_context_destroy(&irsctx); +#endif + + return (error); +} + +static char * +irs_strsep(char **stringp, const char *delim) { + char *string = *stringp; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) + return (NULL); + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return (string); + } + } + *stringp = NULL; + return (string); +} + +static void +set_order(int family, int (**net_order)(const char *, int, struct addrinfo **, + int, int)) +{ + char *order, *tok; + int found; + + if (family) { + switch (family) { + case AF_INET: + *net_order++ = add_ipv4; + break; + case AF_INET6: + *net_order++ = add_ipv6; + break; + } + } else { + order = getenv("NET_ORDER"); + found = 0; + while (order != NULL) { + /* + * We ignore any unknown names. + */ + tok = irs_strsep(&order, ":"); + if (strcasecmp(tok, "inet6") == 0) { + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + found |= FOUND_IPV6; + } else if (strcasecmp(tok, "inet") == 0 || + strcasecmp(tok, "inet4") == 0) { + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + found |= FOUND_IPV4; + } + } + + /* + * Add in anything that we didn't find. + */ + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + } + *net_order = NULL; + return; +} + +static char v4_loop[4] = { 127, 0, 0, 1 }; + +static int +add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */ + if (ai == NULL) { + freeaddrinfo(*aip); + return (EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); + + return (0); +} + +static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + +static int +add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */ + if (ai == NULL) { + freeaddrinfo(*aip); + return (EAI_MEMORY); + } + + *aip = ai; + ai->ai_socktype = socktype; + SIN6(ai->ai_addr)->sin6_port = port; + memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); + + return (0); +} + +/*% Free address info. */ +void +freeaddrinfo(struct addrinfo *ai) { + struct addrinfo *ai_next; + + while (ai != NULL) { + ai_next = ai->ai_next; + if (ai->ai_addr != NULL) + free(ai->ai_addr); + if (ai->ai_canonname) + free(ai->ai_canonname); + free(ai); + ai = ai_next; + } +} + +#ifdef AF_LOCAL +static int +get_local(const char *name, int socktype, struct addrinfo **res) { + struct addrinfo *ai; + struct sockaddr_un *slocal; + + if (socktype == 0) + return (EAI_SOCKTYPE); + + ai = ai_alloc(AF_LOCAL, sizeof(*slocal)); + if (ai == NULL) + return (EAI_MEMORY); + + slocal = SLOCAL(ai->ai_addr); + strncpy(slocal->sun_path, name, sizeof(slocal->sun_path)); + + ai->ai_socktype = socktype; + /* + * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, + * and ai->ai_next were initialized to zero. + */ + + *res = ai; + return (0); +} +#endif + +/*! + * Allocate an addrinfo structure, and a sockaddr structure + * of the specificed length. We initialize: + * ai_addrlen + * ai_family + * ai_addr + * ai_addr->sa_family + * ai_addr->sa_len (IRS_PLATFORM_HAVESALEN) + * and everything else is initialized to zero. + */ +static struct addrinfo * +ai_alloc(int family, int addrlen) { + struct addrinfo *ai; + + ai = (struct addrinfo *)calloc(1, sizeof(*ai)); + if (ai == NULL) + return (NULL); + + ai->ai_addr = SA(calloc(1, addrlen)); + if (ai->ai_addr == NULL) { + free(ai); + return (NULL); + } + ai->ai_addrlen = addrlen; + ai->ai_family = family; + ai->ai_addr->sa_family = family; +#ifdef IRS_PLATFORM_HAVESALEN + ai->ai_addr->sa_len = addrlen; +#endif + return (ai); +} + +static struct addrinfo * +ai_clone(struct addrinfo *oai, int family) { + struct addrinfo *ai; + + ai = ai_alloc(family, ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); + + if (ai == NULL) { + if (oai != NULL) + freeaddrinfo(oai); + return (NULL); + } + if (oai == NULL) + return (ai); + + ai->ai_flags = oai->ai_flags; + ai->ai_socktype = oai->ai_socktype; + ai->ai_protocol = oai->ai_protocol; + ai->ai_canonname = NULL; + ai->ai_next = oai; + return (ai); +} + +static struct addrinfo * +ai_reverse(struct addrinfo *oai) { + struct addrinfo *nai, *tai; + + nai = NULL; + + while (oai != NULL) { + /* + * Grab one off the old list. + */ + tai = oai; + oai = oai->ai_next; + /* + * Put it on the front of the new list. + */ + tai->ai_next = nai; + nai = tai; + } + return (nai); +} + + +static struct addrinfo * +ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) { + struct addrinfo *ai_tmp; + + if (ai1 == NULL) + return (ai2); + else if (ai2 == NULL) + return (ai1); + + for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL; + ai_tmp = ai_tmp->ai_next) + ; + + ai_tmp->ai_next = ai2; + + return (ai1); +} diff --git a/lib/irs/getnameinfo.c b/lib/irs/getnameinfo.c new file mode 100644 index 0000000000..b2f6ac3904 --- /dev/null +++ b/lib/irs/getnameinfo.c @@ -0,0 +1,410 @@ +/* + * Portions Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1999-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: getnameinfo.c,v 1.2 2009/09/01 00:22:27 jinmei Exp $ */ + +/*! \file */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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. + */ + +/** + * getnameinfo() returns the hostname for the struct sockaddr sa which is + * salen bytes long. The hostname is of length hostlen and is returned via + * *host. The maximum length of the hostname is 1025 bytes: #NI_MAXHOST. + * + * The name of the service associated with the port number in sa is + * returned in *serv. It is servlen bytes long. The maximum length of the + * service name is #NI_MAXSERV - 32 bytes. + * + * The flags argument sets the following bits: + * + * \li #NI_NOFQDN: + * A fully qualified domain name is not required for local hosts. + * The local part of the fully qualified domain name is returned + * instead. + * + * \li #NI_NUMERICHOST + * Return the address in numeric form, as if calling inet_ntop(), + * instead of a host name. + * + * \li #NI_NAMEREQD + * A name is required. If the hostname cannot be found in the DNS + * and this flag is set, a non-zero error code is returned. If the + * hostname is not found and the flag is not set, the address is + * returned in numeric form. + * + * \li #NI_NUMERICSERV + * The service name is returned as a digit string representing the + * port number. + * + * \li #NI_DGRAM + * Specifies that the service being looked up is a datagram + * service, and causes getservbyport() to be called with a second + * argument of "udp" instead of its default of "tcp". This is + * required for the few ports (512-514) that have different + * services for UDP and TCP. + * + * \section getnameinfo_return Return Values + * + * getnameinfo() returns 0 on success or a non-zero error code if + * an error occurs. + * + * \section getname_see See Also + * + * RFC3493, getservbyport(), + * getnamebyaddr(). inet_ntop(). + */ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SUCCESS 0 + +/*% afd structure definition */ +static struct afd { + int a_af; + size_t a_addrlen; + size_t a_socklen; +} afdl [] = { + /*! + * First entry is linked last... + */ + { AF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in) }, + { AF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6) }, + {0, 0, 0}, +}; + +/*! + * The test against 0 is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ +#define ERR(code) \ + do { result = (code); \ + if (result != 0) goto cleanup; \ + } while (0) + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, + IRS_GETNAMEINFO_BUFLEN_T hostlen, char *serv, + IRS_GETNAMEINFO_BUFLEN_T servlen, IRS_GETNAMEINFO_FLAGS_T flags) +{ + struct afd *afd; + struct servent *sp; + unsigned short port; +#ifdef IRS_PLATFORM_HAVESALEN + size_t len; +#endif + int family, i; + const void *addr; + char *p; +#if 0 + unsigned long v4a; + unsigned char pfx; +#endif + char numserv[sizeof("65000")]; + char numaddr[sizeof("abcd:abcd:abcd:abcd:abcd:abcd:255.255.255.255") + + 1 + sizeof("4294967295")]; + const char *proto; + int result = SUCCESS; + + if (sa == NULL) + ERR(EAI_FAIL); + +#ifdef IRS_PLATFORM_HAVESALEN + len = sa->sa_len; + if (len != salen) + ERR(EAI_FAIL); +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + ERR(EAI_FAMILY); + + found: + if (salen != afd->a_socklen) + ERR(EAI_FAIL); + + switch (family) { + case AF_INET: + port = ((const struct sockaddr_in *)sa)->sin_port; + addr = &((const struct sockaddr_in *)sa)->sin_addr.s_addr; + break; + + case AF_INET6: + port = ((const struct sockaddr_in6 *)sa)->sin6_port; + addr = ((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; + break; + + default: + port = 0; + addr = NULL; + INSIST(0); + } + proto = (flags & NI_DGRAM) ? "udp" : "tcp"; + + if (serv == NULL || servlen == 0U) { + /* + * Caller does not want service. + */ + } else if ((flags & NI_NUMERICSERV) != 0 || + (sp = getservbyport(port, proto)) == NULL) { + snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); + if ((strlen(numserv) + 1) > servlen) + ERR(EAI_OVERFLOW); + strcpy(serv, numserv); + } else { + if ((strlen(sp->s_name) + 1) > servlen) + ERR(EAI_OVERFLOW); + strcpy(serv, sp->s_name); + } + +#if 0 + switch (sa->sa_family) { + case AF_INET: + v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + flags |= NI_NUMERICHOST; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0 || v4a == IN_LOOPBACKNET) + flags |= NI_NUMERICHOST; + break; + + case AF_INET6: + pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; + } +#endif + + if (host == NULL || hostlen == 0U) { + /* + * do nothing in this case. + * in case you are wondering if "&&" is more correct than + * "||" here: RFC3493 says that host == NULL or hostlen == 0 + * means that the caller does not want the result. + */ + } else if ((flags & NI_NUMERICHOST) != 0) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + ERR(EAI_SYSTEM); +#if defined(IRS_HAVE_SIN6_SCOPE_ID) + if (afd->a_af == AF_INET6 && + ((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char *p = numaddr + strlen(numaddr); + const char *stringscope = NULL; +#ifdef VENDOR_SPECIFIC + /* + * Vendors may want to add support for + * non-numeric scope identifier. + */ + stringscope = foo; +#endif + if (stringscope == NULL) { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%u", + ((const struct sockaddr_in6 *)sa)->sin6_scope_id); + } else { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%s", stringscope); + } + } +#endif + if (strlen(numaddr) + 1 > hostlen) + ERR(EAI_OVERFLOW); + strcpy(host, numaddr); + } else { + isc_netaddr_t netaddr; + dns_fixedname_t ptrfname; + dns_name_t *ptrname; + irs_context_t *irsctx = NULL; + dns_client_t *client; + isc_boolean_t found = ISC_FALSE; + dns_namelist_t answerlist; + dns_rdataset_t *rdataset; + isc_region_t hostregion; + char hoststr[1024]; /* is this enough? */ + isc_result_t iresult; + + /* Get IRS context and the associated DNS client object */ + iresult = irs_context_get(&irsctx); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + client = irs_context_getdnsclient(irsctx); + + /* Make query name */ + isc_netaddr_fromsockaddr(&netaddr, (const isc_sockaddr_t *)sa); + dns_fixedname_init(&ptrfname); + ptrname = dns_fixedname_name(&ptrfname); + iresult = dns_byaddr_createptrname2(&netaddr, 0, ptrname); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + + /* Get the PTR RRset */ + ISC_LIST_INIT(answerlist); + iresult = dns_client_resolve(client, ptrname, + dns_rdataclass_in, + dns_rdatatype_ptr, + DNS_CLIENTRESOPT_ALLOWRUN, + &answerlist); + switch (iresult) { + case ISC_R_SUCCESS: + /* + * a 'non-existent' error is not necessarily fatal for + * getnameinfo(). + */ + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NCACHENXRRSET: + break; + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + ERR(EAI_INSECUREDATA); + default: + ERR(EAI_FAIL); + } + + /* Parse the answer for the hostname */ + for (ptrname = ISC_LIST_HEAD(answerlist); ptrname != NULL; + ptrname = ISC_LIST_NEXT(ptrname, link)) { + for (rdataset = ISC_LIST_HEAD(ptrname->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != dns_rdatatype_ptr) + continue; + + for (iresult = dns_rdataset_first(rdataset); + iresult == ISC_R_SUCCESS; + iresult = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata; + dns_rdata_ptr_t rdata_ptr; + isc_buffer_t b; + + dns_rdata_init(&rdata); + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_ptr, + NULL); + + isc_buffer_init(&b, hoststr, + sizeof(hoststr)); + iresult = + dns_name_totext(&rdata_ptr.ptr, + ISC_TRUE, &b); + dns_rdata_freestruct(&rdata_ptr); + if (iresult == ISC_R_SUCCESS) { + /* + * We ignore the rest of the + * answer. After all, + * getnameinfo() can return + * at most one hostname. + */ + found = ISC_TRUE; + isc_buffer_usedregion( + &b, &hostregion); + goto ptrfound; + } + + } + } + } + ptrfound: + dns_client_freeresanswer(client, &answerlist); + if (found) { + if ((flags & NI_NOFQDN) != 0) { + p = strchr(hoststr, '.'); + if (p) + *p = '\0'; + } + if (hostregion.length + 1 > hostlen) + ERR(EAI_OVERFLOW); + snprintf(host, hostlen, "%.*s", + (int)hostregion.length, + (char *)hostregion.base); + } else { + if ((flags & NI_NAMEREQD) != 0) + ERR(EAI_NONAME); + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + ERR(EAI_SYSTEM); + if ((strlen(numaddr) + 1) > hostlen) + ERR(EAI_OVERFLOW); + strcpy(host, numaddr); + } + } + result = SUCCESS; + + cleanup: + return (result); +} diff --git a/lib/irs/include/Makefile.in b/lib/irs/include/Makefile.in new file mode 100644 index 0000000000..3fba6e9dde --- /dev/null +++ b/lib/irs/include/Makefile.in @@ -0,0 +1,24 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:28 jinmei Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/irs/include/irs/Makefile.in b/lib/irs/include/irs/Makefile.in new file mode 100644 index 0000000000..e85a90de0c --- /dev/null +++ b/lib/irs/include/irs/Makefile.in @@ -0,0 +1,44 @@ +# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: Makefile.in,v 1.2 2009/09/01 00:22:28 jinmei Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/irs ; \ + done + ${INSTALL_DATA} netdb.h ${DESTDIR}${includedir}/irs + ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/irs + +distclean:: + rm -f netdb.h platform.h diff --git a/lib/irs/include/irs/context.h b/lib/irs/include/irs/context.h new file mode 100644 index 0000000000..a72d0e3b88 --- /dev/null +++ b/lib/irs/include/irs/context.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: context.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef IRS_CONTEXT_H +#define IRS_CONTEXT_H 1 + +/*! \file + * + * \brief + * The IRS context module provides an abstract interface to the DNS library + * with an application. An IRS context object initializes and holds various + * resources used in the DNS library. + */ + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_context_create(irs_context_t **contextp); +/*%< + * Create an IRS context. It internally initializes the ISC and DNS libraries + * (if not yet), creates a DNS client object and initializes the client using + * the configuration files parsed via the 'resconf' and 'dnsconf' IRS modules. + * Some of the internally initialized objects can be used by the application + * via irs_context_getxxx() functions (see below). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +isc_result_t +irs_context_get(irs_context_t **contextp); +/*%< + * Return an IRS context for the calling thread. If no IRS context is + * associated to the thread, this function creates a new one by calling + * irs_context_create(), and associates it with the thread as a thread specific + * data value. This function is provided for standard libraries that are + * expected to be thread-safe but do not accept an appropriate IRS context + * as a library parameter, e.g., getaddrinfo(). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +void +irs_context_destroy(irs_context_t **contextp); +/*%< + * Destroy an IRS context. + * + * Requires: + * + *\li '*contextp' is a valid IRS context. + * + * Ensures: + *\li '*contextp' == NULL. + */ + +isc_mem_t * +irs_context_getmctx(irs_context_t *context); +/*%< + * Return the memory context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context); +/*%< + * Return the application context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context); +/*%< + * Return the task manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context); +/*%< + * Return the timer manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_task_t * +irs_context_gettask(irs_context_t *context); +/*%< + * Return the task object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context); +/*%< + * Return the DNS client object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context); +/*%< + * Return the resolver configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context); +/*%< + * Return the advanced DNS configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_CONTEXT_H */ diff --git a/lib/irs/include/irs/dnsconf.h b/lib/irs/include/irs/dnsconf.h new file mode 100644 index 0000000000..7adb2cf723 --- /dev/null +++ b/lib/irs/include/irs/dnsconf.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dnsconf.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef IRS_DNSCONF_H +#define IRS_DNSCONF_H 1 + +/*! \file + * + * \brief + * The IRS dnsconf module parses an "advanced" configuration file related to + * the DNS library, such as trusted keys for DNSSEC validation, and creates + * the corresponding configuration objects for the DNS library modules. + * + * Notes: + * This module is very experimental and the configuration syntax or library + * interfaces may change in future versions. Currently, only the + * 'trusted-keys' statement is supported, whose syntax is the same as the + * same name of statement for named.conf. + */ + +#include + +/*% + * A compound structure storing DNS key information mainly for DNSSEC + * validation. A dns_key_t object will be created using the 'keyname' and + * 'keydatabuf' members with the dst_key_fromdns() function. + */ +typedef struct irs_dnsconf_dnskey { + dns_name_t *keyname; + isc_buffer_t *keydatabuf; + ISC_LINK(struct irs_dnsconf_dnskey) link; +} irs_dnsconf_dnskey_t; + +typedef ISC_LIST(irs_dnsconf_dnskey_t) irs_dnsconf_dnskeylist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp); +/*%< + * Load the "advanced" DNS configuration file 'filename' in the "dns.conf" + * format, and create a new irs_dnsconf_t object from the configuration. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp); +/*%< + * Destroy the dnsconf object. + * + * Requires: + * + *\li '*confp' is a valid dnsconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf); +/*%< + * Return a list of key information stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid dnsconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_DNSCONF_H */ diff --git a/lib/irs/include/irs/netdb.h.in b/lib/irs/include/irs/netdb.h.in new file mode 100644 index 0000000000..4f834dbaa2 --- /dev/null +++ b/lib/irs/include/irs/netdb.h.in @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: netdb.h.in,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file */ + +#ifndef IRS_NETDB_H +#define IRS_NETDB_H 1 + +#include /* Required on FreeBSD (and others?) for size_t. */ +#include /* Contractual provision. */ + +/* + * Define if does not declare struct addrinfo. + */ +@ISC_IRS_NEEDADDRINFO@ + +#ifdef ISC_IRS_NEEDADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* Length of ai_addr */ + char *ai_canonname; /* Canonical name for hostname */ + struct sockaddr *ai_addr; /* Binary address */ + struct addrinfo *ai_next; /* Next structure in linked list */ +}; +#endif + +/* + * Undefine all #defines we are interested in as may or may not have + * defined them. + */ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#undef NETDB_INTERNAL +#undef NETDB_SUCCESS +#undef HOST_NOT_FOUND +#undef TRY_AGAIN +#undef NO_RECOVERY +#undef NO_DATA +#undef NO_ADDRESS + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo(). EAI_INSECUREDATA is our own extension + * and it's very unlikely to be already defined, but undef it just in case; it + * at least doesn't do any harm. + */ + +#undef EAI_ADDRFAMILY +#undef EAI_AGAIN +#undef EAI_BADFLAGS +#undef EAI_FAIL +#undef EAI_FAMILY +#undef EAI_MEMORY +#undef EAI_NODATA +#undef EAI_NONAME +#undef EAI_SERVICE +#undef EAI_SOCKTYPE +#undef EAI_SYSTEM +#undef EAI_BADHINTS +#undef EAI_PROTOCOL +#undef EAI_OVERFLOW +#undef EAI_INSECUREDATA +#undef EAI_MAX + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 +#define EAI_INSECUREDATA 15 +#define EAI_MAX 16 + +/* + * Flag values for getaddrinfo() + */ +#undef AI_PASSIVE +#undef AI_CANONNAME +#undef AI_NUMERICHOST + +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 + +/* + * Flag values for getipnodebyname() + */ +#undef AI_V4MAPPED +#undef AI_ALL +#undef AI_ADDRCONFIG +#undef AI_DEFAULT + +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for lwres_getnameinfo() + */ +#undef NI_MAXHOST +#undef NI_MAXSERV + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for lwres_getnameinfo() + */ +#undef NI_NOFQDN +#undef NI_NUMERICHOST +#undef NI_NAMEREQD +#undef NI_NUMERICSERV +#undef NI_DGRAM +#undef NI_NUMERICSCOPE + +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 + +/* + * Tell Emacs to use C mode on this file. + * Local variables: + * mode: c + * End: + */ + +#endif /* IRS_NETDB_H */ diff --git a/lib/irs/include/irs/platform.h.in b/lib/irs/include/irs/platform.h.in new file mode 100644 index 0000000000..c498613911 --- /dev/null +++ b/lib/irs/include/irs/platform.h.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: platform.h.in,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file */ + +#ifndef IRS_PLATFORM_H +#define IRS_PLATFORM_H 1 + +/***** + ***** Platform-dependent defines. + *****/ + +#ifndef IRS_PLATFORM_USEDECLSPEC +#define LIBIRS_EXTERNAL_DATA +#else +#ifdef LIBIRS_EXPORTS +#define LIBIRS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBIRS_EXTERNAL_DATA __declspec(dllimport) +#endif +#endif + +/* + * Tell Emacs to use C mode on this file. + * Local Variables: + * mode: c + * End: + */ + +#endif /* IRS_PLATFORM_H */ diff --git a/lib/irs/include/irs/resconf.h b/lib/irs/include/irs/resconf.h new file mode 100644 index 0000000000..da31f0eab6 --- /dev/null +++ b/lib/irs/include/irs/resconf.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: resconf.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef IRS_RESCONF_H +#define IRS_RESCONF_H 1 + +/*! \file + * + * \brief + * The IRS resconf module parses the legacy "/etc/resolv.conf" file and + * creates the corresponding configuration objects for the DNS library + * modules. + */ + +#include + +/*% + * A DNS search list specified in the 'domain' or 'search' statements + * in the "resolv.conf" file. + */ +typedef struct irs_resconf_search { + char *domain; + ISC_LINK(struct irs_resconf_search) link; +} irs_resconf_search_t; + +typedef ISC_LIST(irs_resconf_search_t) irs_resconf_searchlist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp); +/*%< + * Load the resolver configuration file 'filename' in the "resolv.conf" format, + * and create a new irs_resconf_t object from the configuration. + * + * Notes: + * + *\li Currently, only the following options are supported: + * nameserver, domain, search, sortlist, ndots, and options. + * In addition, 'sortlist' is not actually effective; it's parsed, but + * the application cannot use the configuration. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_resconf_destroy(irs_resconf_t **confp); +/*%< + * Destroy the resconf object. + * + * Requires: + * + *\li '*confp' is a valid resconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf); +/*%< + * Return a list of name server addresses stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf); +/*%< + * Return the search list stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf); +/*%< + * Return the 'ndots' value stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_RESCONF_H */ diff --git a/lib/irs/include/irs/types.h b/lib/irs/include/irs/types.h new file mode 100644 index 0000000000..14b548d7b9 --- /dev/null +++ b/lib/irs/include/irs/types.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: types.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef IRS_TYPES_H +#define IRS_TYPES_H 1 + +/* Core Types. Alphabetized by defined type. */ + +/*%< per-thread IRS context */ +typedef struct irs_context irs_context_t; +/*%< resolv.conf configuration information */ +typedef struct irs_resconf irs_resconf_t; +/*%< advanced DNS-related configuration information */ +typedef struct irs_dnsconf irs_dnsconf_t; + +#endif /* IRS_TYPES_H */ diff --git a/lib/irs/include/irs/version.h b/lib/irs/include/irs/version.h new file mode 100644 index 0000000000..d9020b8289 --- /dev/null +++ b/lib/irs/include/irs/version.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: version.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file */ + +#include + +LIBIRS_EXTERNAL_DATA extern const char irs_version[]; + +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libinterface; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_librevision; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libage; diff --git a/lib/irs/resconf.c b/lib/irs/resconf.c new file mode 100644 index 0000000000..e51108e92f --- /dev/null +++ b/lib/irs/resconf.c @@ -0,0 +1,639 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * This code is derived from software contributed to ISC by + * Berkeley Software Design, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC. + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: resconf.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file resconf.c */ + +/** + * Module for parsing resolv.conf files (largely derived from lwconfig.c). + * + * irs_resconf_load() opens the file filename and parses it to initialize + * the configuration structure. + * + * \section lwconfig_return Return Values + * + * irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and + * parsed filename. It returns a non-0 error code if filename could not be + * opened or contained incorrect resolver statements. + * + * \section lwconfig_see See Also + * + * stdio(3), \link resolver resolver \endlink + * + * \section files Files + * + * /etc/resolv.conf + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define IRS_RESCONF_MAGIC ISC_MAGIC('R', 'E', 'S', 'c') +#define IRS_RESCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_RESCONF_MAGIC) + +/*! + * protocol constants + */ + +#if ! defined(NS_INADDRSZ) +#define NS_INADDRSZ 4 +#endif + +#if ! defined(NS_IN6ADDRSZ) +#define NS_IN6ADDRSZ 16 +#endif + +/*! + * resolv.conf parameters + */ + +#define RESCONFMAXNAMESERVERS 3 /*%< max 3 "nameserver" entries */ +#define RESCONFMAXSEARCH 8 /*%< max 8 domains in "search" entry */ +#define RESCONFMAXLINELEN 256 /*%< max size of a line */ +#define RESCONFMAXSORTLIST 10 /*%< max 10 */ + +/*! + * configuration data structure + */ + +struct irs_resconf { + /* + * The configuration data is a thread-specific object, and does not + * need to be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + + isc_sockaddrlist_t nameservers; + unsigned int numns; /*%< number of configured servers */ + + char *domainname; + char *search[RESCONFMAXSEARCH]; + isc_uint8_t searchnxt; /*%< index for next free slot */ + + irs_resconf_searchlist_t searchlist; + + struct { + isc_netaddr_t addr; + /*% mask has a non-zero 'family' if set */ + isc_netaddr_t mask; + } sortlist[RESCONFMAXSORTLIST]; + isc_uint8_t sortlistnxt; + + /*%< non-zero if 'options debug' set */ + isc_uint8_t resdebug; + /*%< set to n in 'options ndots:n' */ + isc_uint8_t ndots; +}; + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parseoption(irs_resconf_t *ctx, FILE *fp); + +/*! + * Eat characters from FP until EOL or EOF. Returns EOF or '\n' + */ +static int +eatline(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF) + ch = fgetc(fp); + + return (ch); +} + +/*! + * Eats white space up to next newline or non-whitespace character (of + * EOF). Returns the last character read. Comments are considered white + * space. + */ +static int +eatwhite(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF && isspace((unsigned char)ch)) + ch = fgetc(fp); + + if (ch == ';' || ch == '#') + ch = eatline(fp); + + return (ch); +} + +/*! + * Skip over any leading whitespace and then read in the next sequence of + * non-whitespace characters. In this context newline is not considered + * whitespace. Returns EOF on end-of-file, or the character + * that caused the reading to stop. + */ +static int +getword(FILE *fp, char *buffer, size_t size) { + int ch; + char *p = buffer; + + REQUIRE(buffer != NULL); + REQUIRE(size > 0U); + + *p = '\0'; + + ch = eatwhite(fp); + + if (ch == EOF) + return (EOF); + + do { + *p = '\0'; + + if (ch == EOF || isspace((unsigned char)ch)) + break; + else if ((size_t) (p - buffer) == size - 1) + return (EOF); /* Not enough space. */ + + *p++ = (char)ch; + ch = fgetc(fp); + } while (1); + + return (ch); +} + +static isc_result_t +add_server(isc_mem_t *mctx, const char *address_str, + isc_sockaddrlist_t *nameservers) +{ + int error; + isc_sockaddr_t *address = NULL; + struct addrinfo hints, *res; + isc_result_t result = ISC_R_SUCCESS; + + res = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(address_str, "53", &hints, &res); + if (error != 0) + return (ISC_R_BADADDRESSFORM); + + /* XXX: special case: treat all-0 IPv4 address as loopback */ + if (res->ai_family == AF_INET) { + struct in_addr *v4; + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + + v4 = &((struct sockaddr_in *)res->ai_addr)->sin_addr; + if (memcmp(v4, zeroaddress, 4) == 0) + memcpy(v4, loopaddress, 4); + } + + address = isc_mem_get(mctx, sizeof(*address)); + if (address == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + if (res->ai_addrlen > sizeof(address->type)) { + isc_mem_put(mctx, address, sizeof(*address)); + result = ISC_R_RANGE; + goto cleanup; + } + address->length = res->ai_addrlen; + memcpy(&address->type.sa, res->ai_addr, res->ai_addrlen); + ISC_LINK_INIT(address, link); + ISC_LIST_APPEND(*nameservers, address, link); + + cleanup: + freeaddrinfo(res); + + return (result); +} + +static isc_result_t +create_addr(const char *buffer, isc_netaddr_t *addr, int convert_zero) { + struct in_addr v4; + struct in6_addr v6; + + if (inet_aton(buffer, &v4) == 1) { + if (convert_zero) { + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + if (memcmp(&v4, zeroaddress, 4) == 0) + memcpy(&v4, loopaddress, 4); + } + addr->family = AF_INET; + memcpy(&addr->type.in, &v4, NS_INADDRSZ); + addr->zone = 0; + } else if (inet_pton(AF_INET6, buffer, &v6) == 1) { + addr->family = AF_INET6; + memcpy(&addr->type.in6, &v6, NS_IN6ADDRSZ); + addr->zone = 0; + } else + return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */ + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int cp; + isc_result_t result; + + if (conf->numns == RESCONFMAXNAMESERVERS) + return (ISC_R_SUCCESS); + + cp = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */ + else if (cp == ' ' || cp == '\t') + cp = eatwhite(fp); + + if (cp != EOF && cp != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + result = add_server(conf->mctx, word, &conf->nameservers); + if (result != ISC_R_SUCCESS) + return (result); + conf->numns++; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int res, i; + + res = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + else if (res == ' ' || res == '\t') + res = eatwhite(fp); + + if (res != EOF && res != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + /* + * Search and domain are mutually exclusive. + */ + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) { + isc_mem_free(conf->mctx, conf->search[i]); + conf->search[i] = NULL; + } + } + conf->searchnxt = 0; + + conf->domainname = isc_mem_strdup(conf->mctx, word); + if (conf->domainname == NULL) + return (ISC_R_NOMEMORY); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp) { + int idx, delim; + char word[RESCONFMAXLINELEN]; + + if (conf->domainname != NULL) { + /* + * Search and domain are mutually exclusive. + */ + isc_mem_free(conf->mctx, conf->domainname); + conf->domainname = NULL; + } + + /* + * Remove any previous search definitions. + */ + for (idx = 0; idx < RESCONFMAXSEARCH; idx++) { + if (conf->search[idx] != NULL) { + isc_mem_free(conf->mctx, conf->search[idx]); + conf->search[idx] = NULL; + } + } + conf->searchnxt = 0; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + + idx = 0; + while (strlen(word) > 0U) { + if (conf->searchnxt == RESCONFMAXSEARCH) + goto ignore; /* Too many domains. */ + + conf->search[idx] = isc_mem_strdup(conf->mctx, word); + if (conf->search[idx] == NULL) + return (ISC_R_NOMEMORY); + idx++; + conf->searchnxt++; + + ignore: + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) { + int delim, res, idx; + char word[RESCONFMAXLINELEN]; + char *p; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (conf->sortlistnxt == RESCONFMAXSORTLIST) + return (ISC_R_QUOTA); /* Too many values. */ + + p = strchr(word, '/'); + if (p != NULL) + *p++ = '\0'; + + idx = conf->sortlistnxt; + res = create_addr(word, &conf->sortlist[idx].addr, 1); + if (res != ISC_R_SUCCESS) + return (res); + + if (p != NULL) { + res = create_addr(p, &conf->sortlist[idx].mask, 0); + if (res != ISC_R_SUCCESS) + return (res); + } else { + /* + * Make up a mask. (XXX: is this correct?) + */ + conf->sortlist[idx].mask = conf->sortlist[idx].addr; + memset(&conf->sortlist[idx].mask.type, 0xff, + sizeof(conf->sortlist[idx].mask.type)); + } + + conf->sortlistnxt++; + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parseoption(irs_resconf_t *conf, FILE *fp) { + int delim; + long ndots; + char *p; + char word[RESCONFMAXLINELEN]; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (strcmp("debug", word) == 0) { + conf->resdebug = 1; + } else if (strncmp("ndots:", word, 6) == 0) { + ndots = strtol(word + 6, &p, 10); + if (*p != '\0') /* Bad string. */ + return (ISC_R_UNEXPECTEDTOKEN); + if (ndots < 0 || ndots > 0xff) /* Out of range. */ + return (ISC_R_RANGE); + conf->ndots = (isc_uint8_t)ndots; + } + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +add_search(irs_resconf_t *conf, char *domain) { + irs_resconf_search_t *entry; + + entry = isc_mem_get(conf->mctx, sizeof(*entry)); + if (entry == NULL) + return (ISC_R_NOMEMORY); + + entry->domain = domain; + ISC_LINK_INIT(entry, link); + ISC_LIST_APPEND(conf->searchlist, entry, link); + + return (ISC_R_SUCCESS); +} + +/*% parses a file and fills in the data structure. */ +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) +{ + FILE *fp = NULL; + char word[256]; + isc_result_t rval, ret; + irs_resconf_t *conf; + int i, stopchar; + + REQUIRE(mctx != NULL); + REQUIRE(filename != NULL); + REQUIRE(strlen(filename) > 0U); + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->nameservers); + conf->numns = 0; + conf->domainname = NULL; + conf->searchnxt = 0; + conf->resdebug = 0; + conf->ndots = 1; + for (i = 0; i < RESCONFMAXSEARCH; i++) + conf->search[i] = NULL; + + errno = 0; + if ((fp = fopen(filename, "r")) == NULL) { + isc_mem_put(mctx, conf, sizeof(*conf)); + return (ISC_R_INVALIDFILE); + } + + ret = ISC_R_SUCCESS; + do { + stopchar = getword(fp, word, sizeof(word)); + if (stopchar == EOF) { + rval = ISC_R_SUCCESS; + break; + } + + if (strlen(word) == 0U) + rval = ISC_R_SUCCESS; + else if (strcmp(word, "nameserver") == 0) + rval = resconf_parsenameserver(conf, fp); + else if (strcmp(word, "domain") == 0) + rval = resconf_parsedomain(conf, fp); + else if (strcmp(word, "search") == 0) + rval = resconf_parsesearch(conf, fp); + else if (strcmp(word, "sortlist") == 0) + rval = resconf_parsesortlist(conf, fp); + else if (strcmp(word, "options") == 0) + rval = resconf_parseoption(conf, fp); + else { + /* unrecognised word. Ignore entire line */ + rval = ISC_R_SUCCESS; + stopchar = eatline(fp); + if (stopchar == EOF) { + break; + } + } + if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) + ret = rval; + } while (1); + + fclose(fp); + + /* If we don't find a nameserver fall back to localhost */ + if (conf->numns == 0) { + INSIST(ISC_LIST_EMPTY(conf->nameservers)); + + /* XXX: should we catch errors? */ + (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers); + (void)add_server(conf->mctx, "::1", &conf->nameservers); + } + + /* + * Construct unified search list from domain or configured + * search list + */ + ISC_LIST_INIT(conf->searchlist); + if (conf->domainname != NULL) { + ret = add_search(conf, conf->domainname); + } else if (conf->searchnxt > 0) { + for (i = 0; i < conf->searchnxt; i++) { + ret = add_search(conf, conf->search[i]); + if (ret != ISC_R_SUCCESS) + break; + } + } + + conf->magic = IRS_RESCONF_MAGIC; + + if (ret != ISC_R_SUCCESS) + irs_resconf_destroy(&conf); + else + *confp = conf; + + return (ret); +} + +void +irs_resconf_destroy(irs_resconf_t **confp) { + irs_resconf_t *conf; + isc_sockaddr_t *address; + irs_resconf_search_t *searchentry; + int i; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_RESCONF_VALID(conf)); + + while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) { + ISC_LIST_UNLINK(conf->searchlist, searchentry, link); + isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry)); + } + + while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) { + ISC_LIST_UNLINK(conf->nameservers, address, link); + isc_mem_put(conf->mctx, address, sizeof(*address)); + } + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) + isc_mem_free(conf->mctx, conf->search[i]); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->nameservers); +} + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->searchlist); +} + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return ((unsigned int)conf->ndots); +} diff --git a/lib/irs/version.c b/lib/irs/version.c new file mode 100644 index 0000000000..1142a8496b --- /dev/null +++ b/lib/irs/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: version.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file */ + +#include + +const char irs_version[] = VERSION; + +const unsigned int irs_libinterface = LIBINTERFACE; +const unsigned int irs_librevision = LIBREVISION; +const unsigned int irs_libage = LIBAGE; diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 2eba940988..ced0e64729 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.100 2009/02/06 12:26:22 fdupont Exp $ +# $Id: Makefile.in,v 1.101 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -28,7 +28,7 @@ CINCLUDES = -I${srcdir}/unix/include \ -I${srcdir}/@ISC_ARCH_DIR@/include \ -I./include \ -I${srcdir}/include @ISC_OPENSSL_INC@ -CDEFINES = @USE_OPENSSL@ +CDEFINES = -DBIND9 @USE_OPENSSL@ CWARNINGS = # Alphabetically @@ -39,7 +39,6 @@ UNIXOBJS = @ISC_ISCIPV6_O@ \ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \ unix/stdtime.@O@ unix/strerror.@O@ unix/syslog.@O@ unix/time.@O@ - NLSOBJS = nls/msgcat.@O@ THREADOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ \ @@ -112,5 +111,8 @@ installdirs: install:: timestamp installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ ${DESTDIR}${libdir} +install:: @ISC_ARCH_DIR@/include/isc/atomic.h + ${INSTALL_DATA} @ISC_ARCH_DIR@/include/isc/atomic.h ${DESTDIR}${includedir}/isc + clean distclean:: rm -f libisc.@A@ libisc.la timestamp diff --git a/lib/isc/app_api.c b/lib/isc/app_api.c new file mode 100644 index 0000000000..8f44c5e84c --- /dev/null +++ b/lib/isc/app_api.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: app_api.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#include + +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_appctxcreatefunc_t appctx_createfunc = NULL; + +#define ISCAPI_APPMETHODS_VALID(m) ISC_MAGIC_VALID(m, ISCAPI_APPMETHODS_MAGIC) + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_app_register(isc_appctxcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (appctx_createfunc == NULL) + appctx_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(appctx_createfunc != NULL); + result = (*appctx_createfunc)(mctx, ctxp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_appctx_destroy(isc_appctx_t **ctxp) { + REQUIRE(ctxp != NULL && ISCAPI_APPCTX_VALID(*ctxp)); + + (*ctxp)->methods->ctxdestroy(ctxp); + + ENSURE(*ctxp == NULL); +} + +isc_result_t +isc_app_ctxstart(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxstart(ctx)); +} + +isc_result_t +isc_app_ctxrun(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxrun(ctx)); +} + +isc_result_t +isc_app_ctxsuspend(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxsuspend(ctx)); +} + +isc_result_t +isc_app_ctxshutdown(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxshutdown(ctx)); +} + +void +isc_app_ctxfinish(isc_appctx_t *ctx) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + + return (ctx->methods->ctxfinish(ctx)); +} + +void +isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(taskmgr != NULL); + + ctx->methods->settaskmgr(ctx, taskmgr); +} + +void +isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(socketmgr != NULL); + + ctx->methods->setsocketmgr(ctx, socketmgr); +} + +void +isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr) { + REQUIRE(ISCAPI_APPCTX_VALID(ctx)); + REQUIRE(timermgr != NULL); + + ctx->methods->settimermgr(ctx, timermgr); +} diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 2a1c112bf7..f1d68c7700 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: hash.c,v 1.15 2009/05/06 23:47:50 tbox Exp $ */ +/* $Id: hash.c,v 1.16 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file * Some portion of this code was derived from universal hash function @@ -194,8 +194,12 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, hctx->vectorlen = vlen; hctx->rndvector = rv; +#ifdef BIND9 if (entropy != NULL) isc_entropy_attach(entropy, &hctx->entropy); +#else + UNUSED(entropy); +#endif *hctxp = hctx; return (ISC_R_SUCCESS); @@ -236,18 +240,22 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) { void isc_hash_ctxinit(isc_hash_t *hctx) { - isc_result_t result; - LOCK(&hctx->lock); if (hctx->initialized == ISC_TRUE) goto out; if (hctx->entropy) { +#ifdef BIND9 + isc_result_t result; + result = isc_entropy_getdata(hctx->entropy, hctx->rndvector, hctx->vectorlen, NULL, 0); INSIST(result == ISC_R_SUCCESS); +#else + INSIST(0); +#endif } else { isc_uint32_t pr; unsigned int i, copylen; @@ -304,8 +312,10 @@ destroy(isc_hash_t **hctxp) { isc_refcount_destroy(&hctx->refcnt); mctx = hctx->mctx; +#ifdef BIND9 if (hctx->entropy != NULL) isc_entropy_detach(&hctx->entropy); +#endif if (hctx->rndvector != NULL) isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen); diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h index c4d54cbe44..f20f604639 100644 --- a/lib/isc/include/isc/app.h +++ b/lib/isc/include/isc/app.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: app.h,v 1.8 2007/06/19 23:47:18 tbox Exp $ */ +/* $Id: app.h,v 1.9 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_APP_H #define ISC_APP_H 1 @@ -54,12 +54,23 @@ * Use of this module is not required. In particular, isc_app_start() is * NOT an ISC library initialization routine. * + * This module also supports per-thread 'application contexts'. With this + * mode, a thread-based application will have a separate context, in which + * it uses other ISC library services such as tasks or timers. Signals are + * not caught in this mode, so that the application can handle the signals + * in its preferred way. + * * \li MP: * Clients must ensure that isc_app_start(), isc_app_run(), and * isc_app_finish() are called at most once. isc_app_shutdown() * is safe to use by any thread (provided isc_app_start() has been * called previously). * + * The same note applies to isc_app_ctxXXX() functions, but in this case + * it's a per-thread restriction. For example, a thread with an + * application context must ensure that isc_app_ctxstart() with the + * context is called at most once. + * * \li Reliability: * No anticipated impact. * @@ -75,16 +86,63 @@ #include #include +#include #include +/*** + *** Types + ***/ + typedef isc_event_t isc_appevent_t; #define ISC_APPEVENT_FIRSTEVENT (ISC_EVENTCLASS_APP + 0) #define ISC_APPEVENT_SHUTDOWN (ISC_EVENTCLASS_APP + 1) #define ISC_APPEVENT_LASTEVENT (ISC_EVENTCLASS_APP + 65535) +/*% + * app module methods. Only app driver implementations use this structure. + * Other clients should use the top-level interfaces (i.e., isc_app_xxx + * functions). magic must be ISCAPI_APPMETHODS_MAGIC. + */ +typedef struct isc_appmethods { + void (*ctxdestroy)(isc_appctx_t **ctxp); + isc_result_t (*ctxstart)(isc_appctx_t *ctx); + isc_result_t (*ctxrun)(isc_appctx_t *ctx); + isc_result_t (*ctxsuspend)(isc_appctx_t *ctx); + isc_result_t (*ctxshutdown)(isc_appctx_t *ctx); + void (*ctxfinish)(isc_appctx_t *ctx); + void (*settaskmgr)(isc_appctx_t *ctx, + isc_taskmgr_t *timermgr); + void (*setsocketmgr)(isc_appctx_t *ctx, + isc_socketmgr_t *timermgr); + void (*settimermgr)(isc_appctx_t *ctx, + isc_timermgr_t *timermgr); +} isc_appmethods_t; + +/*% + * This structure is actually just the common prefix of an application context + * implementation's version of an isc_appctx_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_APPCTX_MAGIC for any + * of the isc_app_ routines to work. app implementations must maintain + * all app socket invariants. + */ +struct isc_appctx { + unsigned int impmagic; + unsigned int magic; + isc_appmethods_t *methods; +}; + +#define ISCAPI_APPCTX_MAGIC ISC_MAGIC('A','a','p','c') +#define ISCAPI_APPCTX_VALID(c) ((c) != NULL && \ + (c)->magic == ISCAPI_APPCTX_MAGIC) + ISC_LANG_BEGINDECLS +isc_result_t +isc_app_ctxstart(isc_appctx_t *ctx); + isc_result_t isc_app_start(void); /*!< @@ -93,6 +151,9 @@ isc_app_start(void); * Notes: * This call should be made before any other ISC library call, and as * close to the beginning of the application as possible. + * + * Requires: + * 'ctx' is a valid application context (for app_ctxstart()). */ isc_result_t @@ -102,13 +163,16 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, * \brief Request delivery of an event when the application is run. * * Requires: - * isc_app_start() has been called. + *\li isc_app_start() has been called. * * Returns: * ISC_R_SUCCESS * ISC_R_NOMEMORY */ +isc_result_t +isc_app_ctxrun(isc_appctx_t *ctx); + isc_result_t isc_app_run(void); /*!< @@ -120,17 +184,21 @@ isc_app_run(void); * caller should start shutting down the application. * * Requires: - *\li isc_app_start() has been called. + *\li isc_app_[ctx]start() has been called. * * Ensures: *\li Any events requested via isc_app_onrun() will have been posted (in * FIFO order) before isc_app_run() blocks. + *\li 'ctx' is a valid application context (for app_ctxrun()). * * Returns: *\li ISC_R_SUCCESS Shutdown has been requested. *\li ISC_R_RELOAD Reload has been requested. */ +isc_result_t +isc_app_ctxshutdown(isc_appctx_t *ctx); + isc_result_t isc_app_shutdown(void); /*!< @@ -141,13 +209,20 @@ isc_app_shutdown(void); * only be triggered once. * * Requires: - *\li isc_app_run() has been called. + *\li isc_app_[ctx]run() has been called. + *\li 'ctx' is a valid application context (for app_ctxshutdown()). * * Returns: *\li ISC_R_SUCCESS *\li ISC_R_UNEXPECTED */ +isc_result_t +isc_app_ctxsuspend(isc_appctx_t *ctx); +/*!< + * \brief This has the same behavior as isc_app_ctxsuspend(). + */ + isc_result_t isc_app_reload(void); /*!< @@ -161,6 +236,9 @@ isc_app_reload(void); *\li ISC_R_UNEXPECTED */ +void +isc_app_ctxfinish(isc_appctx_t *ctx); + void isc_app_finish(void); /*!< @@ -171,6 +249,7 @@ isc_app_finish(void); * * Requires: *\li isc_app_start() has been called. + *\li 'ctx' is a valid application context (for app_ctxfinish()). * * Ensures: *\li Any resources allocated by isc_app_start() have been released. @@ -206,6 +285,90 @@ isc_app_unblock(void); * \li isc_app_block() has been called by the same thread. */ +isc_result_t +isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp); +/*!< + * \brief Create an application context. + * + * Requires: + *\li 'mctx' is a valid memory context. + *\li 'ctxp' != NULL && *ctxp == NULL. + */ + +void +isc_appctx_destroy(isc_appctx_t **ctxp); +/*!< + * \brief Destroy an application context. + * + * Requires: + *\li '*ctxp' is a valid application context. + * + * Ensures: + *\li *ctxp == NULL. + */ + +void +isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr); +/*!< + * \brief Associate a task manager with an application context. + * + * This must be done before running tasks within the application context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'taskmgr' is a valid task manager. + */ + +void +isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr); +/*!< + * \brief Associate a socket manager with an application context. + * + * This must be done before handling socket events within the application + * context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'socketmgr' is a valid socket manager. + */ + +void +isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr); +/*!< + * \brief Associate a socket timer with an application context. + * + * This must be done before handling timer events within the application + * context. + * + * Requires: + *\li 'ctx' is a valid application context. + *\li 'timermgr' is a valid timer manager. + */ + +#ifdef USE_APPIMPREGISTER +/*%< + * See isc_appctx_create() above. + */ +typedef isc_result_t +(*isc_appctxcreatefunc_t)(isc_mem_t *mctx, isc_appctx_t **ctxp); + +isc_result_t +isc_app_register(isc_appctxcreatefunc_t createfunc); +/*%< + * Register a new application implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__app_register(void); +/*%< + * A short cut function that specifies the application module in the ISC + * library for isc_app_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_APPIMPREGISTER */ ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/lib.h b/lib/isc/include/isc/lib.h index 765cdfaa19..af8b07b009 100644 --- a/lib/isc/include/isc/lib.h +++ b/lib/isc/include/isc/lib.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */ +/* $Id: lib.h,v 1.15 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_LIB_H #define ISC_LIB_H 1 @@ -36,6 +36,15 @@ isc_lib_initmsgcat(void); * has not already been initialized. */ +void +isc_lib_register(void); +/*!< + * \brief Register the ISC library implementations for some base services + * such as memory or event management and handling socket or timer events. + * An external application that wants to use the ISC library must call this + * function very early in main(). + */ + ISC_LANG_ENDDECLS #endif /* ISC_LIB_H */ diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h index a114d3eb6a..04a604f73f 100644 --- a/lib/isc/include/isc/mem.h +++ b/lib/isc/include/isc/mem.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mem.h,v 1.81 2009/02/11 03:04:18 jinmei Exp $ */ +/* $Id: mem.h,v 1.82 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_MEM_H #define ISC_MEM_H 1 @@ -187,6 +187,72 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging; * \endcode */ +/*% memory and memory pool methods */ +typedef struct isc_memmethods { + void (*attach)(isc_mem_t *source, isc_mem_t **targetp); + void (*detach)(isc_mem_t **mctxp); + void (*destroy)(isc_mem_t **mctxp); + void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG); + void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG); + void (*memputanddetach)(isc_mem_t **mctxp, void *ptr, + size_t size _ISC_MEM_FLARG); + void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG); + char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG); + void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG); + void (*setdestroycheck)(isc_mem_t *mctx, isc_boolean_t flag); + void (*setwater)(isc_mem_t *ctx, isc_mem_water_t water, + void *water_arg, size_t hiwater, size_t lowater); + void (*waterack)(isc_mem_t *ctx, int flag); + size_t (*inuse)(isc_mem_t *mctx); + isc_result_t (*mpcreate)(isc_mem_t *mctx, size_t size, + isc_mempool_t **mpctxp); +} isc_memmethods_t; + +typedef struct isc_mempoolmethods { + void (*destroy)(isc_mempool_t **mpctxp); + void *(*get)(isc_mempool_t *mpctx _ISC_MEM_FLARG); + void (*put)(isc_mempool_t *mpctx, void *mem _ISC_MEM_FLARG); + unsigned int (*getallocated)(isc_mempool_t *mpctx); + void (*setmaxalloc)(isc_mempool_t *mpctx, unsigned int limit); + void (*setfreemax)(isc_mempool_t *mpctx, unsigned int limit); + void (*setname)(isc_mempool_t *mpctx, const char *name); + void (*associatelock)(isc_mempool_t *mpctx, isc_mutex_t *lock); + void (*setfillcount)(isc_mempool_t *mpctx, unsigned int limit); +} isc_mempoolmethods_t; + +/*% + * This structure is actually just the common prefix of a memory context + * implementation's version of an isc_mem_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_MCTX_MAGIC for any of the + * isc_mem_ routines to work. mctx implementations must maintain all mctx + * invariants. + */ +struct isc_mem { + unsigned int impmagic; + unsigned int magic; + isc_memmethods_t *methods; +}; + +#define ISCAPI_MCTX_MAGIC ISC_MAGIC('A','m','c','x') +#define ISCAPI_MCTX_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_MCTX_MAGIC) + +/*% + * This is the common prefix of a memory pool context. The same note as + * that for the mem structure applies. + */ +struct isc_mempool { + unsigned int impmagic; + unsigned int magic; + isc_mempoolmethods_t *methods; +}; + +#define ISCAPI_MPOOL_MAGIC ISC_MAGIC('A','m','p','l') +#define ISCAPI_MPOOL_VALID(mp) ((mp) != NULL && \ + (mp)->magic == ISCAPI_MPOOL_MAGIC) + #if ISC_MEM_DEBUG #define isc_mem_put(c, p, s) \ do { \ @@ -607,8 +673,7 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit); void * isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG); void -isc__mem_putanddetach(isc_mem_t **, void *, - size_t _ISC_MEM_FLARG); +isc__mem_putanddetach(isc_mem_t **, void *, size_t _ISC_MEM_FLARG); void isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG); void * @@ -624,6 +689,33 @@ isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG); void isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG); +#ifdef USE_MEMIMPREGISTER + +/*%< + * See isc_mem_create2() above. + */ +typedef isc_result_t +(*isc_memcreatefunc_t)(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags); + +isc_result_t +isc_mem_register(isc_memcreatefunc_t createfunc); +/*%< + * Register a new memory management implementation and add it to the list of + * supported implementations. This function must be called when a different + * memory management library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__mem_register(void); +/*%< + * A short cut function that specifies the memory management module in the ISC + * library for isc_mem_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_MEMIMPREGISTER */ + ISC_LANG_ENDDECLS #endif /* ISC_MEM_H */ diff --git a/lib/isc/include/isc/namespace.h b/lib/isc/include/isc/namespace.h new file mode 100644 index 0000000000..9cc8d60a84 --- /dev/null +++ b/lib/isc/include/isc/namespace.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: namespace.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef ISCAPI_NAMESPACE_H +#define ISCAPI_NAMESPACE_H 1 + +/*% + * name space conversions + */ + +#ifdef BIND9 + +#define isc_app_start isc__app_start +#define isc_app_ctxstart isc__app_ctxstart +#define isc_app_onrun isc__app_onrun +#define isc_app_run isc__app_run +#define isc_app_ctxrun isc__app_ctxrun +#define isc_app_shutdown isc__app_shutdown +#define isc_app_ctxshutdown isc__app_ctxshutdown +#define isc_app_ctxsuspend isc__app_ctxsuspend +#define isc_app_reload isc__app_reload +#define isc_app_finish isc__app_finish +#define isc_app_block isc__app_block +#define isc_app_unblock isc__app_unblock +#define isc_appctx_create isc__appctx_create +#define isc_appctx_destroy isc__appctx_destroy +#define isc_appctx_settaskmgr isc__appctx_settaskmgr +#define isc_appctx_setsocketmgr isc__appctx_setsocketmgr +#define isc_appctx_settimermgr isc__appctx_settimermgr + +#define isc_mem_checkdestroyed isc__mem_checkdestroyed +#define isc_mem_createx isc__mem_createx +#define isc_mem_createx2 isc__mem_createx2 +#define isc_mem_create isc__mem_create +#define isc_mem_create2 isc__mem_create2 +#define isc_mem_attach isc__mem_attach +#define isc_mem_detach isc__mem_detach +#define isc__mem_putanddetach isc___mem_putanddetach +#define isc_mem_destroy isc__mem_destroy +#define isc_mem_ondestroy isc__mem_ondestroy +#define isc__mem_get isc___mem_get +#define isc__mem_put isc___mem_put +#define isc_mem_stats isc__mem_stats +#define isc__mem_allocate isc___mem_allocate +#define isc__mem_free isc___mem_free +#define isc__mem_strdup isc___mem_strdup +#define isc_mem_references isc__mem_references +#define isc_mem_setdestroycheck isc__mem_setdestroycheck +#define isc_mem_setquota isc__mem_setquota +#define isc_mem_getname isc__mem_getname +#define isc_mem_getquota isc__mem_getquota +#define isc_mem_gettag isc__mem_gettag +#define isc_mem_inuse isc__mem_inuse +#define isc_mem_setname isc__mem_setname +#define isc_mem_setwater isc__mem_setwater +#define isc_mem_printallactive isc__mem_printallactive +#define isc_mem_waterack isc__mem_waterack +#define isc_mempool_create isc__mempool_create +#define isc_mempool_setname isc__mempool_setname +#define isc_mempool_destroy isc__mempool_destroy +#define isc_mempool_associatelock isc__mempool_associatelock +#define isc__mempool_get isc___mempool_get +#define isc__mempool_put isc___mempool_put +#define isc_mempool_setfreemax isc__mempool_setfreemax +#define isc_mempool_getfreemax isc__mempool_getfreemax +#define isc_mempool_getfreecount isc__mempool_getfreecount +#define isc_mempool_setmaxalloc isc__mempool_setmaxalloc +#define isc_mempool_getmaxalloc isc__mempool_getmaxalloc +#define isc_mempool_getallocated isc__mempool_getallocated +#define isc_mempool_setfillcount isc__mempool_setfillcount +#define isc_mempool_getfillcount isc__mempool_getfillcount + +#define isc_socket_create isc__socket_create +#define isc_socket_attach isc__socket_attach +#define isc_socket_detach isc__socket_detach +#define isc_socketmgr_create isc__socketmgr_create +#define isc_socketmgr_create2 isc__socketmgr_create2 +#define isc_socketmgr_destroy isc__socketmgr_destroy +#define isc_socket_open isc__socket_open +#define isc_socket_close isc__socket_close +#define isc_socket_recvv isc__socket_recvv +#define isc_socket_recv isc__socket_recv +#define isc_socket_recv2 isc__socket_recv2 +#define isc_socket_send isc__socket_send +#define isc_socket_sendto isc__socket_sendto +#define isc_socket_sendv isc__socket_sendv +#define isc_socket_sendtov isc__socket_sendtov +#define isc_socket_sendto2 isc__socket_sendto2 +#define isc_socket_cleanunix isc__socket_cleanunix +#define isc_socket_permunix isc__socket_permunix +#define isc_socket_bind isc__socket_bind +#define isc_socket_filter isc__socket_filter +#define isc_socket_listen isc__socket_listen +#define isc_socket_accept isc__socket_accept +#define isc_socket_connect isc__socket_connect +#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate +#define isc_socket_getname isc__socket_getname +#define isc_socket_gettag isc__socket_gettag +#define isc_socket_getpeername isc__socket_getpeername +#define isc_socket_getsockname isc__socket_getsockname +#define isc_socket_cancel isc__socket_cancel +#define isc_socket_gettype isc__socket_gettype +#define isc_socket_isbound isc__socket_isbound +#define isc_socket_ipv6only isc__socket_ipv6only +#define isc_socket_setname isc__socket_setname +#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets +#define isc_socketmgr_setstats isc__socketmgr_setstats +#define isc_socketmgr_setreserved isc__socketmgr_setreserved +#define isc__socketmgr_maxudp isc___socketmgr_maxudp + +#define isc_task_create isc__task_create +#define isc_task_attach isc__task_attach +#define isc_task_detach isc__task_detach +#define isc_task_send isc__task_send +#define isc_task_sendanddetach isc__task_sendanddetach +#define isc_task_purgerange isc__task_purgerange +#define isc_task_purge isc__task_purge +#define isc_task_purgeevent isc__task_purgeevent +#define isc_task_unsendrange isc__task_unsendrange +#define isc_task_unsend isc__task_unsend +#define isc_task_onshutdown isc__task_onshutdown +#define isc_task_shutdown isc__task_shutdown +#define isc_task_destroy isc__task_destroy +#define isc_task_setname isc__task_setname +#define isc_task_getname isc__task_getname +#define isc_task_gettag isc__task_gettag +#define isc_task_getcurrenttime isc__task_getcurrenttime +#define isc_taskmgr_create isc__taskmgr_create +#define isc_taskmgr_destroy isc__taskmgr_destroy +#define isc_task_beginexclusive isc__task_beginexclusive +#define isc_task_endexclusive isc__task_endexclusive + +#define isc_timer_create isc__timer_create +#define isc_timer_reset isc__timer_reset +#define isc_timer_gettype isc__timer_gettype +#define isc_timer_touch isc__timer_touch +#define isc_timer_attach isc__timer_attach +#define isc_timer_detach isc__timer_detach +#define isc_timermgr_create isc__timermgr_create +#define isc_timermgr_poke isc__timermgr_poke +#define isc_timermgr_destroy isc__timermgr_destroy + +#endif /* BIND9 */ + +#endif /* ISCAPI_NAMESPACE_H */ diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h index 56b4ca6d69..b01b181fcf 100644 --- a/lib/isc/include/isc/result.h +++ b/lib/isc/include/isc/result.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.71 2008/09/25 04:02:39 tbox Exp $ */ +/* $Id: result.h,v 1.72 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 @@ -42,6 +42,7 @@ #define ISC_R_EOF 14 /*%< end of file */ #define ISC_R_BOUND 15 /*%< socket already bound */ #define ISC_R_RELOAD 16 /*%< reload */ +#define ISC_R_SUSPEND ISC_R_RELOAD /*%< alias of 'reload' */ #define ISC_R_LOCKBUSY 17 /*%< lock busy */ #define ISC_R_EXISTS 18 /*%< already exists */ #define ISC_R_NOSPACE 19 /*%< ran out of space */ diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h index b32426fee2..e0f64393b1 100644 --- a/lib/isc/include/isc/resultclass.h +++ b/lib/isc/include/isc/resultclass.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resultclass.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */ +/* $Id: resultclass.h,v 1.19 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_RESULTCLASS_H #define ISC_RESULTCLASS_H 1 @@ -45,6 +45,7 @@ #define ISC_RESULTCLASS_DNSRCODE ISC_RESULTCLASS_FROMNUM(3) #define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4) #define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5) +#define ISC_RESULTCLASS_DHCP ISC_RESULTCLASS_FROMNUM(6) #endif /* ISC_RESULTCLASS_H */ diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 4f654a2967..15ade4ea92 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.h,v 1.89 2009/03/05 03:13:55 marka Exp $ */ +/* $Id: socket.h,v 1.90 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_SOCKET_H #define ISC_SOCKET_H 1 @@ -260,6 +260,71 @@ typedef enum { #define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */ /*@}*/ +/*% Socket and socket manager methods */ +typedef struct isc_socketmgrmethods { + void (*destroy)(isc_socketmgr_t **managerp); + isc_result_t (*socketcreate)(isc_socketmgr_t *manager, int pf, + isc_sockettype_t type, + isc_socket_t **socketp); +} isc_socketmgrmethods_t; + +typedef struct isc_socketmethods { + void (*attach)(isc_socket_t *socket, + isc_socket_t **socketp); + void (*detach)(isc_socket_t **socketp); + isc_result_t (*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options); + isc_result_t (*sendto)(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, + const void *arg, isc_sockaddr_t *address, + struct in6_pktinfo *pktinfo); + isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, + const void *arg); + isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); + void (*cancel)(isc_socket_t *sock, isc_task_t *task, + unsigned int how); + isc_result_t (*getsockname)(isc_socket_t *sock, + isc_sockaddr_t *addressp); + isc_sockettype_t (*gettype)(isc_socket_t *sock); + void (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes); +} isc_socketmethods_t; + +/*% + * This structure is actually just the common prefix of a socket manager + * object implementation's version of an isc_socketmgr_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_SOCKETMGR_MAGIC for any + * of the isc_socket_ routines to work. socket implementations must maintain + * all socket invariants. + */ +struct isc_socketmgr { + unsigned int impmagic; + unsigned int magic; + isc_socketmgrmethods_t *methods; +}; + +#define ISCAPI_SOCKETMGR_MAGIC ISC_MAGIC('A','s','m','g') +#define ISCAPI_SOCKETMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_SOCKETMGR_MAGIC) + +/*% + * This is the common prefix of a socket object. The same note as + * that for the socketmgr structure applies. + */ +struct isc_socket { + unsigned int impmagic; + unsigned int magic; + isc_socketmethods_t *methods; +}; + +#define ISCAPI_SOCKET_MAGIC ISC_MAGIC('A','s','c','t') +#define ISCAPI_SOCKET_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_SOCKET_MAGIC) + /*** *** Socket and Socket Manager Functions *** @@ -820,6 +885,10 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, */ /*@}*/ +isc_result_t +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_socketmgr_t **managerp); + isc_result_t isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); @@ -831,6 +900,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, * maximum number of sockets that the created manager should handle. * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with * "maxsocks" being zero. + * isc_socketmgr_createinctx() also associates the new manager with the + * specified application context. * * Notes: * @@ -842,6 +913,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, * *\li 'managerp' points to a NULL isc_socketmgr_t. * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li '*managerp' is a valid isc_socketmgr_t. @@ -987,7 +1060,7 @@ void *isc_socket_gettag(isc_socket_t *socket); */ void -isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t); +isc_socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t); /*%< * Temporary. For use by named only. */ @@ -1008,6 +1081,31 @@ isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer); #endif /* HAVE_LIBXML2 */ +#ifdef USE_SOCKETIMPREGISTER +/*%< + * See isc_socketmgr_create() above. + */ +typedef isc_result_t +(*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp); + +isc_result_t +isc_socket_register(isc_socketmgrcreatefunc_t createfunc); +/*%< + * Register a new socket I/O implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__socket_register(void); +/*%< + * A short cut function that specifies the socket I/O module in the ISC + * library for isc_socket_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_SOCKETIMPREGISTER */ + ISC_LANG_ENDDECLS #endif /* ISC_SOCKET_H */ diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h index bf90281e78..2fd838f45e 100644 --- a/lib/isc/include/isc/task.h +++ b/lib/isc/include/isc/task.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task.h,v 1.63 2009/01/18 23:48:14 tbox Exp $ */ +/* $Id: task.h,v 1.64 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_TASK_H #define ISC_TASK_H 1 @@ -96,6 +96,70 @@ ISC_LANG_BEGINDECLS +/*** + *** Types + ***/ + +/*% Task and task manager methods */ +typedef struct isc_taskmgrmethods { + void (*destroy)(isc_taskmgr_t **managerp); + isc_result_t (*taskcreate)(isc_taskmgr_t *manager, + unsigned int quantum, + isc_task_t **taskp); +} isc_taskmgrmethods_t; + +typedef struct isc_taskmethods { + void (*attach)(isc_task_t *source, isc_task_t **targetp); + void (*detach)(isc_task_t **taskp); + void (*destroy)(isc_task_t **taskp); + void (*send)(isc_task_t *task, isc_event_t **eventp); + void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp); + unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events); + isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action, + const void *arg); + void (*shutdown)(isc_task_t *task); + void (*setname)(isc_task_t *task, const char *name, void *tag); + unsigned int (*purgeevents)(isc_task_t *task, void *sender, + isc_eventtype_t type, void *tag); + unsigned int (*purgerange)(isc_task_t *task, void *sender, + isc_eventtype_t first, isc_eventtype_t last, + void *tag); +} isc_taskmethods_t; + +/*% + * This structure is actually just the common prefix of a task manager + * object implementation's version of an isc_taskmgr_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_TASKMGR_MAGIC for any + * of the isc_task_ routines to work. task implementations must maintain + * all task invariants. + */ +struct isc_taskmgr { + unsigned int impmagic; + unsigned int magic; + isc_taskmgrmethods_t *methods; +}; + +#define ISCAPI_TASKMGR_MAGIC ISC_MAGIC('A','t','m','g') +#define ISCAPI_TASKMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_TASKMGR_MAGIC) + +/*% + * This is the common prefix of a task object. The same note as + * that for the taskmgr structure applies. + */ +struct isc_task { + unsigned int impmagic; + unsigned int magic; + isc_taskmethods_t *methods; +}; + +#define ISCAPI_TASK_MAGIC ISC_MAGIC('A','t','s','t') +#define ISCAPI_TASK_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_TASK_MAGIC) + isc_result_t isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, isc_task_t **taskp); @@ -540,10 +604,15 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t); *****/ isc_result_t +isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + unsigned int workers, unsigned int default_quantum, + isc_taskmgr_t **managerp); +isc_result_t isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp); /*%< - * Create a new task manager. + * Create a new task manager. isc_taskmgr_createinctx() also associates + * the new manager with the specified application context. * * Notes: * @@ -565,6 +634,8 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, * *\li managerp != NULL && *managerp == NULL * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li On success, '*managerp' will be attached to the newly created task @@ -619,6 +690,31 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer); #endif +/*%< + * See isc_taskmgr_create() above. + */ +typedef isc_result_t +(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, + isc_taskmgr_t **managerp); + +isc_result_t +isc_task_register(isc_taskmgrcreatefunc_t createfunc); +/*%< + * Register a new task management implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc__task_register(void); +/*%< + * A short cut function that specifies the task management module in the ISC + * library for isc_task_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ + ISC_LANG_ENDDECLS #endif /* ISC_TASK_H */ diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index a4b2df7a54..583dd9624e 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer.h,v 1.40 2008/06/23 23:47:11 tbox Exp $ */ +/* $Id: timer.h,v 1.41 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_TIMER_H #define ISC_TIMER_H 1 @@ -103,6 +103,61 @@ typedef struct isc_timerevent { #define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) #define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) +/*% Timer and timer manager methods */ +typedef struct { + void (*destroy)(isc_timermgr_t **managerp); + isc_result_t (*timercreate)(isc_timermgr_t *manager, + isc_timertype_t type, + isc_time_t *expires, + isc_interval_t *interval, + isc_task_t *task, + isc_taskaction_t action, + const void *arg, + isc_timer_t **timerp); +} isc_timermgrmethods_t; + +typedef struct { + void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); + void (*detach)(isc_timer_t **timerp); + isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge); + isc_result_t (*touch)(isc_timer_t *timer); +} isc_timermethods_t; + +/*% + * This structure is actually just the common prefix of a timer manager + * object implementation's version of an isc_timermgr_t. + * \brief + * Direct use of this structure by clients is forbidden. mctx implementations + * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any + * of the isc_timer_ routines to work. timer implementations must maintain + * all timer invariants. + */ +struct isc_timermgr { + unsigned int impmagic; + unsigned int magic; + isc_timermgrmethods_t *methods; +}; + +#define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') +#define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ + (m)->magic == ISCAPI_TIMERMGR_MAGIC) + +/*% + * This is the common prefix of a timer object. The same note as + * that for the timermgr structure applies. + */ +struct isc_timer { + unsigned int impmagic; + unsigned int magic; + isc_timermethods_t *methods; +}; + +#define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') +#define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ + (s)->magic == ISCAPI_TIMER_MAGIC) + /*** *** Timer and Timer Manager Functions *** @@ -288,10 +343,15 @@ isc_timer_gettype(isc_timer_t *timer); *\li 'timer' to be a valid timer. */ +isc_result_t +isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_timermgr_t **managerp); + isc_result_t isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); /*%< - * Create a timer manager. + * Create a timer manager. isc_timermgr_createinctx() also associates + * the new manager with the specified application context. * * Notes: * @@ -303,6 +363,8 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); * *\li 'managerp' points to a NULL isc_timermgr_t. * + *\li 'actx' is a valid application context (for createinctx()). + * * Ensures: * *\li '*managerp' is a valid isc_timermgr_t. @@ -339,6 +401,31 @@ isc_timermgr_destroy(isc_timermgr_t **managerp); void isc_timermgr_poke(isc_timermgr_t *m); +#ifdef USE_TIMERIMPREGISTER +/*%< + * See isc_timermgr_create() above. + */ +typedef isc_result_t +(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); + +isc_result_t +isc__timer_register(void); +/*%< + * Register a new timer management implementation and add it to the list of + * supported implementations. This function must be called when a different + * event library is used than the one contained in the ISC library. + */ + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc); +/*%< + * A short cut function that specifies the timer management module in the ISC + * library for isc_timer_register(). An application that uses the ISC library + * usually do not have to care about this function: it would call + * isc_lib_register(), which internally calls this function. + */ +#endif /* USE_TIMERIMPREGISTER */ + ISC_LANG_ENDDECLS #endif /* ISC_TIMER_H */ diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index 469e7d62f4..dd60d76a20 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -15,11 +15,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.48 2009/01/27 23:47:54 tbox Exp $ */ +/* $Id: types.h,v 1.49 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_TYPES_H #define ISC_TYPES_H 1 +#include + /*! \file isc/types.h * \brief * OS-specific types, from the OS-specific include directories. @@ -40,6 +42,7 @@ /* Core Types. Alphabetized by defined type. */ +typedef struct isc_appctx isc_appctx_t; /*%< Application context */ typedef struct isc_bitstring isc_bitstring_t; /*%< Bitstring */ typedef struct isc_buffer isc_buffer_t; /*%< Buffer */ typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ diff --git a/lib/isc/lib.c b/lib/isc/lib.c index f3a2c2dc79..8d431f13e0 100644 --- a/lib/isc/lib.c +++ b/lib/isc/lib.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lib.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: lib.c,v 1.15 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file */ @@ -24,9 +24,15 @@ #include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include /*** *** Globals @@ -41,7 +47,6 @@ LIBISC_EXTERNAL_DATA isc_msgcat_t * isc_msgcat = NULL; static isc_once_t msgcat_once = ISC_ONCE_INIT; - /*** *** Functions ***/ @@ -77,3 +82,22 @@ isc_lib_initmsgcat(void) { abort(); } } + +#ifndef BIND9 +static isc_once_t register_once = ISC_ONCE_INIT; + +static void +do_register(void) { + RUNTIME_CHECK(isc__mem_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__app_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__task_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__socket_register() == ISC_R_SUCCESS); + RUNTIME_CHECK(isc__timer_register() == ISC_R_SUCCESS); +} + +void +isc_lib_register() { + RUNTIME_CHECK(isc_once_do(®ister_once, do_register) + == ISC_R_SUCCESS); +} +#endif diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 2ee8c89ea8..6895a873e9 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mem.c,v 1.149 2009/02/16 03:16:10 marka Exp $ */ +/* $Id: mem.c,v 1.150 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file */ @@ -60,6 +60,9 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING; /* * Types. */ +typedef struct isc__mem isc__mem_t; +typedef struct isc__mempool isc__mempool_t; + #if ISC_MEM_TRACKLINES typedef struct debuglink debuglink_t; struct debuglink { @@ -89,7 +92,7 @@ typedef struct { */ union { size_t size; - isc_mem_t *ctx; + isc__mem_t *ctx; char bytes[ALIGNMENT_SIZE]; } u; } size_info; @@ -110,7 +113,7 @@ typedef ISC_LIST(debuglink_t) debuglist_t; /* List of all active memory contexts. */ -static ISC_LIST(isc_mem_t) contexts; +static ISC_LIST(isc__mem_t) contexts; static isc_once_t once = ISC_ONCE_INIT; static isc_mutex_t lock; @@ -120,8 +123,8 @@ static isc_mutex_t lock; */ static isc_uint64_t totallost; -struct isc_mem { - unsigned int magic; +struct isc__mem { + isc_mem_t common; isc_ondestroy_t ondestroy; unsigned int flags; isc_mutex_t lock; @@ -143,7 +146,7 @@ struct isc_mem { isc_boolean_t hi_called; isc_mem_water_t water; void * water_arg; - ISC_LIST(isc_mempool_t) pools; + ISC_LIST(isc__mempool_t) pools; unsigned int poolcnt; /* ISC_MEMFLAG_INTERNAL */ @@ -162,19 +165,19 @@ struct isc_mem { #endif unsigned int memalloc_failures; - ISC_LINK(isc_mem_t) link; + ISC_LINK(isc__mem_t) link; }; #define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p') #define VALID_MEMPOOL(c) ISC_MAGIC_VALID(c, MEMPOOL_MAGIC) -struct isc_mempool { +struct isc__mempool { /* always unlocked */ - unsigned int magic; /*%< magic number */ + isc_mempool_t common; /*%< common header of mempool's */ isc_mutex_t *lock; /*%< optional lock */ - isc_mem_t *mctx; /*%< our memory context */ + isc__mem_t *mctx; /*%< our memory context */ /*%< locked via the memory context's lock */ - ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */ + ISC_LINK(isc__mempool_t) link; /*%< next pool in this mem context */ /*%< optionally locked from here down */ element *items; /*%< low water item list */ size_t size; /*%< size of each item on this pool */ @@ -209,13 +212,170 @@ struct isc_mempool { #define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e) static void -print_active(isc_mem_t *ctx, FILE *out); +print_active(isc__mem_t *ctx, FILE *out); + +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_MEMFUNC_SCOPE +#else +#define ISC_MEMFUNC_SCOPE static +#endif + +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx2(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp, unsigned int flags); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create2(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags); +ISC_MEMFUNC_SCOPE void +isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp); +ISC_MEMFUNC_SCOPE void +isc__mem_detach(isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE void +isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_destroy(isc_mem_t **ctxp); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event); +ISC_MEMFUNC_SCOPE void * +isc___mem_get(isc_mem_t *ctx, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_stats(isc_mem_t *ctx, FILE *out); +ISC_MEMFUNC_SCOPE void * +isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG); +ISC_MEMFUNC_SCOPE void +isc___mem_free(isc_mem_t *ctx, void *ptr FLARG); +ISC_MEMFUNC_SCOPE char * +isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG); +ISC_MEMFUNC_SCOPE void +isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag); +ISC_MEMFUNC_SCOPE void +isc__mem_setquota(isc_mem_t *ctx, size_t quota); +ISC_MEMFUNC_SCOPE size_t +isc__mem_getquota(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE size_t +isc__mem_inuse(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE void +isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, + size_t hiwater, size_t lowater); +ISC_MEMFUNC_SCOPE void +isc__mem_waterack(isc_mem_t *ctx0, int flag); +ISC_MEMFUNC_SCOPE void +isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag); +ISC_MEMFUNC_SCOPE const char * +isc__mem_getname(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE void * +isc__mem_gettag(isc_mem_t *ctx); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp); +ISC_MEMFUNC_SCOPE void +isc__mempool_setname(isc_mempool_t *mpctx, const char *name); +ISC_MEMFUNC_SCOPE void +isc__mempool_destroy(isc_mempool_t **mpctxp); +ISC_MEMFUNC_SCOPE void +isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock); +ISC_MEMFUNC_SCOPE void * +isc___mempool_get(isc_mempool_t *mpctx FLARG); +ISC_MEMFUNC_SCOPE void +isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG); +ISC_MEMFUNC_SCOPE void +isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreemax(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreecount(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE void +isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getmaxalloc(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getallocated(isc_mempool_t *mpctx); +ISC_MEMFUNC_SCOPE void +isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit); +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfillcount(isc_mempool_t *mpctx); +#ifdef BIND9 +ISC_MEMFUNC_SCOPE void +isc__mem_printactive(isc_mem_t *ctx0, FILE *file); +ISC_MEMFUNC_SCOPE void +isc__mem_printallactive(FILE *file); +ISC_MEMFUNC_SCOPE void +isc__mem_checkdestroyed(FILE *file); +ISC_MEMFUNC_SCOPE unsigned int +isc__mem_references(isc_mem_t *ctx0); +#endif + +static struct isc__memmethods { + isc_memmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *createx, *create, *create2, *ondestroy, *stats, + *setquota, *getquota, *setname, *getname, *gettag; +} memmethods = { + { + isc__mem_attach, + isc__mem_detach, + isc__mem_destroy, + isc___mem_get, + isc___mem_put, + isc___mem_putanddetach, + isc___mem_allocate, + isc___mem_strdup, + isc___mem_free, + isc__mem_setdestroycheck, + isc__mem_setwater, + isc__mem_waterack, + isc__mem_inuse, + isc__mempool_create + }, + isc__mem_createx, isc__mem_create, isc__mem_create2, + isc__mem_ondestroy, isc__mem_stats, + isc__mem_setquota, isc__mem_getquota, isc__mem_setname, + isc__mem_getname, isc__mem_gettag +}; + +static struct isc__mempoolmethods { + isc_mempoolmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount; +} mempoolmethods = { + { + isc__mempool_destroy, + isc___mempool_get, + isc___mempool_put, + isc__mempool_getallocated, + isc__mempool_setmaxalloc, + isc__mempool_setfreemax, + isc__mempool_setname, + isc__mempool_associatelock, + isc__mempool_setfillcount + }, + isc__mempool_getfreemax, isc__mempool_getfreecount, + isc__mempool_getmaxalloc, isc__mempool_getfillcount +}; /*! * mctx must be locked. */ static inline void -add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size +add_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size FLARG) { debuglink_t *dl; @@ -274,7 +434,7 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size } static inline void -delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size, +delete_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size, const char *file, unsigned int line) { debuglink_t *dl; @@ -345,7 +505,7 @@ quantize(size_t size) { } static inline isc_boolean_t -more_basic_blocks(isc_mem_t *ctx) { +more_basic_blocks(isc__mem_t *ctx) { void *new; unsigned char *curr, *next; unsigned char *first, *last; @@ -415,7 +575,7 @@ more_basic_blocks(isc_mem_t *ctx) { } static inline isc_boolean_t -more_frags(isc_mem_t *ctx, size_t new_size) { +more_frags(isc__mem_t *ctx, size_t new_size) { int i, frags; size_t total_size; void *new; @@ -477,7 +637,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) { } static inline void * -mem_getunlocked(isc_mem_t *ctx, size_t size) { +mem_getunlocked(isc__mem_t *ctx, size_t size) { size_t new_size = quantize(size); void *ret; @@ -558,7 +718,7 @@ check_overrun(void *mem, size_t size, size_t new_size) { #endif static inline void -mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { +mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) { size_t new_size = quantize(size); if (size == ctx->max_size || new_size >= ctx->max_size) { @@ -606,7 +766,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { * Perform a malloc, doing memory filling and overrun detection as necessary. */ static inline void * -mem_get(isc_mem_t *ctx, size_t size) { +mem_get(isc__mem_t *ctx, size_t size) { char *ret; #if ISC_MEM_CHECKOVERRUN @@ -634,7 +794,7 @@ mem_get(isc_mem_t *ctx, size_t size) { * Perform a free, doing memory filling and overrun detection as necessary. */ static inline void -mem_put(isc_mem_t *ctx, void *mem, size_t size) { +mem_put(isc__mem_t *ctx, void *mem, size_t size) { #if ISC_MEM_CHECKOVERRUN INSIST(((unsigned char *)mem)[size] == 0xbe); #endif @@ -650,7 +810,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) { * Update internal counters after a memory get. */ static inline void -mem_getstats(isc_mem_t *ctx, size_t size) { +mem_getstats(isc__mem_t *ctx, size_t size) { ctx->total += size; ctx->inuse += size; @@ -667,7 +827,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) { * Update internal counters after a memory put. */ static inline void -mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) { +mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) { UNUSED(ptr); INSIST(ctx->inuse >= size); @@ -711,22 +871,22 @@ initialize_action(void) { * Public. */ -isc_result_t -isc_mem_createx(size_t init_max_size, size_t target_size, - isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, - isc_mem_t **ctxp) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp) { - return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree, - arg, ctxp, ISC_MEMFLAG_DEFAULT)); + return (isc__mem_createx2(init_max_size, target_size, memalloc, memfree, + arg, ctxp, ISC_MEMFLAG_DEFAULT)); } -isc_result_t -isc_mem_createx2(size_t init_max_size, size_t target_size, - isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, - isc_mem_t **ctxp, unsigned int flags) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_createx2(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp, unsigned int flags) { - isc_mem_t *ctx; + isc__mem_t *ctx; isc_result_t result; REQUIRE(ctxp != NULL && *ctxp == NULL); @@ -766,7 +926,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, ctx->hi_called = ISC_FALSE; ctx->water = NULL; ctx->water_arg = NULL; - ctx->magic = MEM_MAGIC; + ctx->common.impmagic = MEM_MAGIC; + ctx->common.magic = ISCAPI_MCTX_MAGIC; + ctx->common.methods = (isc_memmethods_t *)&memmethods; isc_ondestroy_init(&ctx->ondestroy); ctx->memalloc = memalloc; ctx->memfree = memfree; @@ -831,7 +993,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, ISC_LIST_INITANDAPPEND(contexts, ctx, link); UNLOCK(&lock); - *ctxp = ctx; + *ctxp = (isc_mem_t *)ctx; return (ISC_R_SUCCESS); error: @@ -852,30 +1014,29 @@ isc_mem_createx2(size_t init_max_size, size_t target_size, return (result); } -isc_result_t -isc_mem_create(size_t init_max_size, size_t target_size, - isc_mem_t **ctxp) -{ - return (isc_mem_createx2(init_max_size, target_size, - default_memalloc, default_memfree, NULL, - ctxp, ISC_MEMFLAG_DEFAULT)); +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp) { + return (isc__mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, ISC_MEMFLAG_DEFAULT)); } -isc_result_t -isc_mem_create2(size_t init_max_size, size_t target_size, - isc_mem_t **ctxp, unsigned int flags) +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_create2(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags) { - return (isc_mem_createx2(init_max_size, target_size, - default_memalloc, default_memfree, NULL, - ctxp, flags)); + return (isc__mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, flags)); } static void -destroy(isc_mem_t *ctx) { +destroy(isc__mem_t *ctx) { unsigned int i; isc_ondestroy_t ondest; - ctx->magic = 0; + ctx->common.impmagic = 0; + ctx->common.magic = 0; LOCK(&lock); ISC_LIST_UNLINK(contexts, ctx, link); @@ -938,8 +1099,10 @@ destroy(isc_mem_t *ctx) { isc_ondestroy_notify(&ondest, ctx); } -void -isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { +ISC_MEMFUNC_SCOPE void +isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) { + isc__mem_t *source = (isc__mem_t *)source0; + REQUIRE(VALID_CONTEXT(source)); REQUIRE(targetp != NULL && *targetp == NULL); @@ -947,16 +1110,16 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { source->references++; MCTXUNLOCK(source, &source->lock); - *targetp = source; + *targetp = (isc_mem_t *)source; } -void -isc_mem_detach(isc_mem_t **ctxp) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc__mem_detach(isc_mem_t **ctxp) { + isc__mem_t *ctx; isc_boolean_t want_destroy = ISC_FALSE; REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -982,15 +1145,15 @@ isc_mem_detach(isc_mem_t **ctxp) { * isc_mem_detach(&mctx); */ -void -isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { + isc__mem_t *ctx; isc_boolean_t want_destroy = ISC_FALSE; size_info *si; size_t oldsize; REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); @@ -1008,7 +1171,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { oldsize -= ALIGNMENT_SIZE; INSIST(oldsize == size); } - isc__mem_free(ctx, ptr FLARG_PASS); + isc_mem_free((isc_mem_t *)ctx, ptr); MCTXLOCK(ctx, &ctx->lock); ctx->references--; @@ -1042,9 +1205,9 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { destroy(ctx); } -void -isc_mem_destroy(isc_mem_t **ctxp) { - isc_mem_t *ctx; +ISC_MEMFUNC_SCOPE void +isc__mem_destroy(isc_mem_t **ctxp) { + isc__mem_t *ctx; /* * This routine provides legacy support for callers who use mctxs @@ -1052,7 +1215,7 @@ isc_mem_destroy(isc_mem_t **ctxp) { */ REQUIRE(ctxp != NULL); - ctx = *ctxp; + ctx = (isc__mem_t *)*ctxp; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1069,8 +1232,9 @@ isc_mem_destroy(isc_mem_t **ctxp) { *ctxp = NULL; } -isc_result_t -isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) { +ISC_MEMFUNC_SCOPE isc_result_t +isc__mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_result_t res; MCTXLOCK(ctx, &ctx->lock); @@ -1080,16 +1244,16 @@ isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) { return (res); } - -void * -isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; void *ptr; isc_boolean_t call_water = ISC_FALSE; REQUIRE(VALID_CONTEXT(ctx)); if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) - return (isc__mem_allocate(ctx, size FLARG_PASS)); + return (isc_mem_allocate((isc_mem_t *)ctx, size)); if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { MCTXLOCK(ctx, &ctx->lock); @@ -1121,9 +1285,9 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { return (ptr); } -void -isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) -{ +ISC_MEMFUNC_SCOPE void +isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_boolean_t call_water = ISC_FALSE; size_info *si; size_t oldsize; @@ -1139,7 +1303,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) oldsize -= ALIGNMENT_SIZE; INSIST(oldsize == size); } - isc__mem_free(ctx, ptr FLARG_PASS); + isc_mem_free((isc_mem_t *)ctx, ptr); return; } @@ -1170,8 +1334,10 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER); } -void -isc_mem_waterack(isc_mem_t *ctx, int flag) { +ISC_MEMFUNC_SCOPE void +isc__mem_waterack(isc_mem_t *ctx0, int flag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1184,7 +1350,7 @@ isc_mem_waterack(isc_mem_t *ctx, int flag) { #if ISC_MEM_TRACKLINES static void -print_active(isc_mem_t *mctx, FILE *out) { +print_active(isc__mem_t *mctx, FILE *out) { if (mctx->debuglist != NULL) { debuglink_t *dl; unsigned int i, j; @@ -1226,11 +1392,12 @@ print_active(isc_mem_t *mctx, FILE *out) { /* * Print the stats[] on the stream "out" with suitable formatting. */ -void -isc_mem_stats(isc_mem_t *ctx, FILE *out) { +ISC_MEMFUNC_SCOPE void +isc__mem_stats(isc_mem_t *ctx0, FILE *out) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t i; const struct stats *s; - const isc_mempool_t *pool; + const isc__mempool_t *pool; REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1303,7 +1470,8 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { */ static void * -isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { +isc__mem_allocateunlocked(isc_mem_t *ctx0, size_t size) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; size += ALIGNMENT_SIZE; @@ -1325,8 +1493,9 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { return (&si[1]); } -void * -isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; isc_boolean_t call_water = ISC_FALSE; @@ -1334,9 +1503,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { MCTXLOCK(ctx, &ctx->lock); - si = isc__mem_allocateunlocked(ctx, size); + si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size); } else { - si = isc__mem_allocateunlocked(ctx, size); + si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size); MCTXLOCK(ctx, &ctx->lock); if (si != NULL) mem_getstats(ctx, si[-1].u.size); @@ -1399,8 +1568,9 @@ isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) { return (new_ptr); } -void -isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) { +ISC_MEMFUNC_SCOPE void +isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_info *si; size_t size; isc_boolean_t call_water= ISC_FALSE; @@ -1451,8 +1621,9 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) { * Other useful things. */ -char * -isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { +ISC_MEMFUNC_SCOPE char * +isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) { + isc__mem_t *mctx = (isc__mem_t *)mctx0; size_t len; char *ns; @@ -1461,7 +1632,7 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { len = strlen(s); - ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS); + ns = isc___mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS); if (ns != NULL) strncpy(ns, s, len + 1); @@ -1469,8 +1640,10 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { return (ns); } -void -isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { +ISC_MEMFUNC_SCOPE void +isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1483,8 +1656,10 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { * Quotas */ -void -isc_mem_setquota(isc_mem_t *ctx, size_t quota) { +ISC_MEMFUNC_SCOPE void +isc__mem_setquota(isc_mem_t *ctx0, size_t quota) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -1493,8 +1668,9 @@ isc_mem_setquota(isc_mem_t *ctx, size_t quota) { MCTXUNLOCK(ctx, &ctx->lock); } -size_t -isc_mem_getquota(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE size_t +isc__mem_getquota(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t quota; REQUIRE(VALID_CONTEXT(ctx)); @@ -1507,8 +1683,9 @@ isc_mem_getquota(isc_mem_t *ctx) { return (quota); } -size_t -isc_mem_inuse(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE size_t +isc__mem_inuse(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; size_t inuse; REQUIRE(VALID_CONTEXT(ctx)); @@ -1521,10 +1698,11 @@ isc_mem_inuse(isc_mem_t *ctx) { return (inuse); } -void -isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, +ISC_MEMFUNC_SCOPE void +isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg, size_t hiwater, size_t lowater) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; isc_boolean_t callwater = ISC_FALSE; isc_mem_water_t oldwater; void *oldwater_arg; @@ -1559,8 +1737,10 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, (oldwater)(oldwater_arg, ISC_MEM_LOWATER); } -void -isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) { +ISC_MEMFUNC_SCOPE void +isc__mem_setname(isc_mem_t *ctx0, const char *name, void *tag) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); LOCK(&ctx->lock); @@ -1570,15 +1750,19 @@ isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) { UNLOCK(&ctx->lock); } -const char * -isc_mem_getname(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE const char * +isc__mem_getname(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); return (ctx->name); } -void * -isc_mem_gettag(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE void * +isc__mem_gettag(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; + REQUIRE(VALID_CONTEXT(ctx)); return (ctx->tag); @@ -1588,9 +1772,10 @@ isc_mem_gettag(isc_mem_t *ctx) { * Memory pool stuff */ -isc_result_t -isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { - isc_mempool_t *mpctx; +ISC_MEMFUNC_SCOPE isc_result_t +isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) { + isc__mem_t *mctx = (isc__mem_t *)mctx0; + isc__mempool_t *mpctx; REQUIRE(VALID_CONTEXT(mctx)); REQUIRE(size > 0U); @@ -1600,11 +1785,13 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { * Allocate space for this pool, initialize values, and if all works * well, attach to the memory context. */ - mpctx = isc_mem_get(mctx, sizeof(isc_mempool_t)); + mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t)); if (mpctx == NULL) return (ISC_R_NOMEMORY); - mpctx->magic = MEMPOOL_MAGIC; + mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods; + mpctx->common.impmagic = MEMPOOL_MAGIC; + mpctx->common.magic = ISCAPI_MPOOL_MAGIC; mpctx->lock = NULL; mpctx->mctx = mctx; mpctx->size = size; @@ -1619,7 +1806,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { #endif mpctx->items = NULL; - *mpctxp = mpctx; + *mpctxp = (isc_mempool_t *)mpctx; MCTXLOCK(mctx, &mctx->lock); ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link); @@ -1629,9 +1816,12 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { return (ISC_R_SUCCESS); } -void -isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(name != NULL); + REQUIRE(VALID_MEMPOOL(mpctx)); #if ISC_MEMPOOL_NAMES if (mpctx->lock != NULL) @@ -1648,20 +1838,20 @@ isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { #endif } -void -isc_mempool_destroy(isc_mempool_t **mpctxp) { - isc_mempool_t *mpctx; - isc_mem_t *mctx; +ISC_MEMFUNC_SCOPE void +isc__mempool_destroy(isc_mempool_t **mpctxp) { + isc__mempool_t *mpctx; + isc__mem_t *mctx; isc_mutex_t *lock; element *item; REQUIRE(mpctxp != NULL); - mpctx = *mpctxp; + mpctx = (isc__mempool_t *)*mpctxp; REQUIRE(VALID_MEMPOOL(mpctx)); #if ISC_MEMPOOL_NAMES if (mpctx->allocated > 0) UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mempool_destroy(): mempool %s " + "isc__mempool_destroy(): mempool %s " "leaked memory", mpctx->name); #endif @@ -1701,9 +1891,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { mctx->poolcnt--; MCTXUNLOCK(mctx, &mctx->lock); - mpctx->magic = 0; + mpctx->common.impmagic = 0; + mpctx->common.magic = 0; - isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t)); + isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t)); if (lock != NULL) UNLOCK(lock); @@ -1711,8 +1902,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { *mpctxp = NULL; } -void -isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { +ISC_MEMFUNC_SCOPE void +isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(VALID_MEMPOOL(mpctx)); REQUIRE(mpctx->lock == NULL); REQUIRE(lock != NULL); @@ -1720,10 +1913,11 @@ isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { mpctx->lock = lock; } -void * -isc__mempool_get(isc_mempool_t *mpctx FLARG) { +ISC_MEMFUNC_SCOPE void * +isc___mempool_get(isc_mempool_t *mpctx0 FLARG) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; element *item; - isc_mem_t *mctx; + isc__mem_t *mctx; unsigned int i; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1802,9 +1996,10 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) { return (item); } -void -isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { - isc_mem_t *mctx; +ISC_MEMFUNC_SCOPE void +isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + isc__mem_t *mctx; element *item; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1859,8 +2054,10 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { * Quotas */ -void -isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(VALID_MEMPOOL(mpctx)); if (mpctx->lock != NULL) @@ -1872,8 +2069,9 @@ isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getfreemax(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreemax(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int freemax; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1889,8 +2087,9 @@ isc_mempool_getfreemax(isc_mempool_t *mpctx) { return (freemax); } -unsigned int -isc_mempool_getfreecount(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfreecount(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int freecount; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1906,8 +2105,10 @@ isc_mempool_getfreecount(isc_mempool_t *mpctx) { return (freecount); } -void -isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(limit > 0); REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1921,8 +2122,9 @@ isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getmaxalloc(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getmaxalloc(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int maxalloc; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1938,8 +2140,9 @@ isc_mempool_getmaxalloc(isc_mempool_t *mpctx) { return (maxalloc); } -unsigned int -isc_mempool_getallocated(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getallocated(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; unsigned int allocated; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1955,8 +2158,10 @@ isc_mempool_getallocated(isc_mempool_t *mpctx) { return (allocated); } -void -isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { +ISC_MEMFUNC_SCOPE void +isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + REQUIRE(limit > 0); REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1969,8 +2174,10 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { UNLOCK(mpctx->lock); } -unsigned int -isc_mempool_getfillcount(isc_mempool_t *mpctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc__mempool_getfillcount(isc_mempool_t *mpctx0) { + isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0; + unsigned int fillcount; REQUIRE(VALID_MEMPOOL(mpctx)); @@ -1986,8 +2193,17 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) { return (fillcount); } -void -isc_mem_printactive(isc_mem_t *ctx, FILE *file) { +#ifdef USE_MEMIMPREGISTER +isc_result_t +isc__mem_register() { + return (isc_mem_register(isc__mem_create2)); +} +#endif + +#ifdef BIND9 +ISC_MEMFUNC_SCOPE void +isc__mem_printactive(isc_mem_t *ctx0, FILE *file) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(file != NULL); @@ -2000,12 +2216,12 @@ isc_mem_printactive(isc_mem_t *ctx, FILE *file) { #endif } -void -isc_mem_printallactive(FILE *file) { +ISC_MEMFUNC_SCOPE void +isc__mem_printallactive(FILE *file) { #if !ISC_MEM_TRACKLINES UNUSED(file); #else - isc_mem_t *ctx; + isc__mem_t *ctx; RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); @@ -2020,15 +2236,15 @@ isc_mem_printallactive(FILE *file) { #endif } -void -isc_mem_checkdestroyed(FILE *file) { +ISC_MEMFUNC_SCOPE void +isc__mem_checkdestroyed(FILE *file) { RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); LOCK(&lock); if (!ISC_LIST_EMPTY(contexts)) { #if ISC_MEM_TRACKLINES - isc_mem_t *ctx; + isc__mem_t *ctx; for (ctx = ISC_LIST_HEAD(contexts); ctx != NULL; @@ -2043,9 +2259,11 @@ isc_mem_checkdestroyed(FILE *file) { UNLOCK(&lock); } -unsigned int -isc_mem_references(isc_mem_t *ctx) { +ISC_MEMFUNC_SCOPE unsigned int +isc_mem_references(isc_mem_t *ctx0) { + isc__mem_t *ctx = (isc__mem_t *)ctx0; unsigned int references; + REQUIRE(VALID_CONTEXT(ctx)); MCTXLOCK(ctx, &ctx->lock); @@ -2065,7 +2283,7 @@ typedef struct summarystat { } summarystat_t; static void -renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { +renderctx(isc__mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { REQUIRE(VALID_CONTEXT(ctx)); xmlTextWriterStartElement(writer, ISC_XMLCHAR "context"); @@ -2151,7 +2369,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) { void isc_mem_renderxml(xmlTextWriterPtr writer) { - isc_mem_t *ctx; + isc__mem_t *ctx; summarystat_t summary; isc_uint64_t lost; @@ -2203,3 +2421,4 @@ isc_mem_renderxml(xmlTextWriterPtr writer) { } #endif /* HAVE_LIBXML2 */ +#endif /* BIND9 */ diff --git a/lib/isc/mem_api.c b/lib/isc/mem_api.c new file mode 100644 index 0000000000..432cd67b66 --- /dev/null +++ b/lib/isc/mem_api.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: mem_api.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#include +#include +#include +#include + +#if ISC_MEM_TRACKLINES +#define FLARG_PASS , file, line +#define FLARG , const char *file, int line +#else +#define FLARG_PASS +#define FLARG +#endif + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_memcreatefunc_t mem_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_mem_register(isc_memcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (mem_createfunc == NULL) + mem_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(mem_createfunc != NULL); + result = (*mem_createfunc)(init_max_size, target_size, mctxp, + ISC_MEMFLAG_DEFAULT); + + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp, + unsigned int flags) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(mem_createfunc != NULL); + result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { + REQUIRE(ISCAPI_MCTX_VALID(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + source->methods->attach(source, targetp); + + ENSURE(*targetp == source); +} + +void +isc_mem_detach(isc_mem_t **mctxp) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->detach(mctxp); + + ENSURE(*mctxp == NULL); +} + +void +isc_mem_destroy(isc_mem_t **mctxp) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->destroy(mctxp); + + ENSURE(*mctxp == NULL); +} + +void * +isc__mem_get(isc_mem_t *mctx, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memget(mctx, size FLARG_PASS)); +} + +void +isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->memput(mctx, ptr, size FLARG_PASS); +} + +void +isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) { + REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp)); + + (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS); + + /* + * XXX: We cannot always ensure *mctxp == NULL here + * (see lib/isc/mem.c). + */ +} + +void * +isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memallocate(mctx, size FLARG_PASS)); +} + +char * +isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->memstrdup(mctx, s FLARG_PASS)); +} + +void +isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->memfree(mctx, ptr FLARG_PASS); +} + +void +isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + mctx->methods->setdestroycheck(mctx, flag); +} + +void +isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, + size_t hiwater, size_t lowater) +{ + REQUIRE(ISCAPI_MCTX_VALID(ctx)); + + ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater); +} + +void +isc_mem_waterack(isc_mem_t *ctx, int flag) { + REQUIRE(ISCAPI_MCTX_VALID(ctx)); + + ctx->methods->waterack(ctx, flag); +} + +size_t +isc_mem_inuse(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->inuse(mctx)); +} + +void +isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + UNUSED(name); + UNUSED(tag); + + return; +} + +const char * +isc_mem_getname(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (""); +} + +void * +isc_mem_gettag(isc_mem_t *mctx) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (NULL); +} + +isc_result_t +isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { + REQUIRE(ISCAPI_MCTX_VALID(mctx)); + + return (mctx->methods->mpcreate(mctx, size, mpctxp)); +} + +void +isc_mempool_destroy(isc_mempool_t **mpctxp) { + REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp)); + + (*mpctxp)->methods->destroy(mpctxp); + + ENSURE(*mpctxp == NULL); +} + +void * +isc__mempool_get(isc_mempool_t *mpctx FLARG) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + return (mpctx->methods->get(mpctx FLARG_PASS)); +} + +void +isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->put(mpctx, mem FLARG_PASS); +} + +unsigned int +isc_mempool_getallocated(isc_mempool_t *mpctx) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + return (mpctx->methods->getallocated(mpctx)); +} + +void +isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setmaxalloc(mpctx, limit); +} + +void +isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setfreemax(mpctx, limit); +} + +void +isc_mempool_setname(isc_mempool_t *mpctx, const char *name) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setname(mpctx, name); +} + +void +isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->associatelock(mpctx, lock); +} + +void +isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) { + REQUIRE(ISCAPI_MPOOL_VALID(mpctx)); + + mpctx->methods->setfillcount(mpctx, limit); +} diff --git a/lib/isc/nls/Makefile.in b/lib/isc/nls/Makefile.in index 695c31327a..29baa21fcc 100644 --- a/lib/isc/nls/Makefile.in +++ b/lib/isc/nls/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.14 2007/06/19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.15 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ CINCLUDES = -I../unix/include \ -I../include \ -I${srcdir}/../include -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = OBJS = msgcat.@O@ diff --git a/lib/isc/nothreads/Makefile.in b/lib/isc/nothreads/Makefile.in index 75a2cb5e3b..2e6a41bebd 100644 --- a/lib/isc/nothreads/Makefile.in +++ b/lib/isc/nothreads/Makefile.in @@ -13,11 +13,11 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.7 2007/06/19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.8 2009/09/01 00:22:28 jinmei Exp $ -srcdir = @srcdir@ -VPATH = @srcdir@ top_srcdir = @top_srcdir@ +srcdir = @top_srcdir@/lib/isc/nothreads +VPATH = @top_srcdir@/lib/isc/nothreads CINCLUDES = -I${srcdir}/include \ -I${srcdir}/../unix/include \ @@ -25,7 +25,7 @@ CINCLUDES = -I${srcdir}/include \ -I${srcdir}/../include \ -I${srcdir}/.. -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = OBJS = condition.@O@ mutex.@O@ thread.@O@ diff --git a/lib/isc/pthreads/Makefile.in b/lib/isc/pthreads/Makefile.in index a287457805..c83eaa610a 100644 --- a/lib/isc/pthreads/Makefile.in +++ b/lib/isc/pthreads/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.19 2007/06/19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.20 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ CINCLUDES = -I${srcdir}/include \ -I${srcdir}/../include \ -I${srcdir}/.. -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = OBJS = condition.@O@ mutex.@O@ thread.@O@ diff --git a/lib/isc/socket_api.c b/lib/isc/socket_api.c new file mode 100644 index 0000000000..66541299bd --- /dev/null +++ b/lib/isc/socket_api.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: socket_api.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_socket_register(isc_socketmgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (socketmgr_createfunc == NULL) + socketmgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_socketmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(socketmgr_createfunc != NULL); + result = (*socketmgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_setsocketmgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(socketmgr_createfunc != NULL); + result = (*socketmgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_socketmgr_destroy(isc_socketmgr_t **managerp) { + REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp) +{ + REQUIRE(ISCAPI_SOCKETMGR_VALID(manager)); + + return (manager->methods->socketcreate(manager, pf, type, socketp)); +} + +void +isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + sock->methods->attach(sock, socketp); + + ENSURE(*socketp == sock); +} + +void +isc_socket_detach(isc_socket_t **socketp) { + REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp)); + + (*socketp)->methods->detach(socketp); + + ENSURE(*socketp == NULL); +} + +isc_result_t +isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->bind(sock, sockaddr, options)); +} + +isc_result_t +isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task, + isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->sendto(sock, region, task, action, arg, address, + pktinfo)); +} + +isc_result_t +isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task, + isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->connect(sock, addr, task, action, arg)); +} + +isc_result_t +isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, + isc_task_t *task, isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->recv(sock, region, minimum, task, action, arg)); +} + +void +isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + sock->methods->cancel(sock, task, how); +} + +isc_result_t +isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->getsockname(sock, addressp)); +} + +void +isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + sock->methods->ipv6only(sock, yes); +} + +isc_sockettype_t +isc_socket_gettype(isc_socket_t *sock) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->gettype(sock)); +} + +void +isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { + REQUIRE(ISCAPI_SOCKET_VALID(socket)); + + UNUSED(socket); /* in case REQUIRE() is empty */ + UNUSED(name); + UNUSED(tag); +} diff --git a/lib/isc/task.c b/lib/isc/task.c index a630173d94..27b1a508f9 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task.c,v 1.107 2008/03/27 23:46:57 tbox Exp $ */ +/* $Id: task.c,v 1.108 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file * \author Principal Author: Bob Halley @@ -40,9 +40,29 @@ #include #include -#ifndef ISC_PLATFORM_USETHREADS +/*% + * For BIND9 internal applications: + * when built with threads we use multiple worker threads shared by the whole + * application. + * when built without threads we share a single global task manager and use + * an integrated event loop for socket, timer, and other generic task events. + * For generic library: + * we don't use either of them: an application can have multiple task managers + * whether or not it's threaded, and if the application is threaded each thread + * is expected to have a separate manager; no "worker threads" are shared by + * the application threads. + */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_WORKER_THREADS +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_WORKER_THREADS #include "task_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ #ifdef ISC_TASK_TRACE #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \ @@ -66,7 +86,7 @@ typedef enum { task_state_done } task_state_t; -#ifdef HAVE_LIBXML2 +#if defined(HAVE_LIBXML2) && defined(BIND9) static const char *statenames[] = { "idle", "ready", "running", "done", }; @@ -75,10 +95,13 @@ static const char *statenames[] = { #define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K') #define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC) -struct isc_task { +typedef struct isc__task isc__task_t; +typedef struct isc__taskmgr isc__taskmgr_t; + +struct isc__task { /* Not locked. */ - unsigned int magic; - isc_taskmgr_t * manager; + isc_task_t common; + isc__taskmgr_t * manager; isc_mutex_t lock; /* Locked by task lock. */ task_state_t state; @@ -91,8 +114,8 @@ struct isc_task { char name[16]; void * tag; /* Locked by task manager lock. */ - LINK(isc_task_t) link; - LINK(isc_task_t) ready_link; + LINK(isc__task_t) link; + LINK(isc__task_t) ready_link; }; #define TASK_F_SHUTTINGDOWN 0x01 @@ -103,9 +126,11 @@ struct isc_task { #define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC) -struct isc_taskmgr { +typedef ISC_LIST(isc__task_t) isc__tasklist_t; + +struct isc__taskmgr { /* Not locked. */ - unsigned int magic; + isc_taskmgr_t common; isc_mem_t * mctx; isc_mutex_t lock; #ifdef ISC_PLATFORM_USETHREADS @@ -114,8 +139,8 @@ struct isc_taskmgr { #endif /* ISC_PLATFORM_USETHREADS */ /* Locked by task manager lock. */ unsigned int default_quantum; - LIST(isc_task_t) tasks; - isc_tasklist_t ready_tasks; + LIST(isc__task_t) tasks; + isc__tasklist_t ready_tasks; #ifdef ISC_PLATFORM_USETHREADS isc_condition_t work_available; isc_condition_t exclusive_granted; @@ -123,7 +148,7 @@ struct isc_taskmgr { unsigned int tasks_running; isc_boolean_t exclusive_requested; isc_boolean_t exiting; -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER unsigned int refs; #endif /* ISC_PLATFORM_USETHREADS */ }; @@ -132,17 +157,112 @@ struct isc_taskmgr { #define DEFAULT_DEFAULT_QUANTUM 5 #define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks)) -#ifndef ISC_PLATFORM_USETHREADS -static isc_taskmgr_t *taskmgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +#ifdef USE_SHARED_MANAGER +static isc__taskmgr_t *taskmgr = NULL; +#endif /* USE_SHARED_MANAGER */ + +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_TASKFUNC_SCOPE +#else +#define ISC_TASKFUNC_SCOPE static +#endif + +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum, + isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_attach(isc_task_t *source0, isc_task_t **targetp); +ISC_TASKFUNC_SCOPE void +isc__task_detach(isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_send(isc_task_t *task0, isc_event_t **eventp); +ISC_TASKFUNC_SCOPE void +isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag); +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_purgeevent(isc_task_t *task0, isc_event_t *event); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag, + isc_eventlist_t *events); +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events); +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action, + const void *arg); +ISC_TASKFUNC_SCOPE void +isc__task_shutdown(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__task_destroy(isc_task_t **taskp); +ISC_TASKFUNC_SCOPE void +isc__task_setname(isc_task_t *task0, const char *name, void *tag); +ISC_TASKFUNC_SCOPE const char * +isc__task_getname(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void * +isc__task_gettag(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t); +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp); +ISC_TASKFUNC_SCOPE void +isc__taskmgr_destroy(isc_taskmgr_t **managerp); +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_beginexclusive(isc_task_t *task); +ISC_TASKFUNC_SCOPE void +isc__task_endexclusive(isc_task_t *task0); + +static struct isc__taskmethods { + isc_taskmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *purgeevent, *unsendrange, + *getname, *gettag, *getcurrenttime, *beginexclusive, + *endexclusive; +} taskmethods = { + { + isc__task_attach, + isc__task_detach, + isc__task_destroy, + isc__task_send, + isc__task_sendanddetach, + isc__task_unsend, + isc__task_onshutdown, + isc__task_shutdown, + isc__task_setname, + isc__task_purge, + isc__task_purgerange + }, + isc__task_purgeevent, isc__task_unsendrange, + isc__task_getname, isc__task_gettag, + isc__task_getcurrenttime, isc__task_beginexclusive, + isc__task_endexclusive +}; + +static isc_taskmgrmethods_t taskmgrmethods = { + isc__taskmgr_destroy, + isc__task_create +}; /*** *** Tasks. ***/ static void -task_finished(isc_task_t *task) { - isc_taskmgr_t *manager = task->manager; +task_finished(isc__task_t *task) { + isc__taskmgr_t *manager = task->manager; REQUIRE(EMPTY(task->events)); REQUIRE(EMPTY(task->on_shutdown)); @@ -153,7 +273,7 @@ task_finished(isc_task_t *task) { LOCK(&manager->lock); UNLINK(manager->tasks, task, link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS if (FINISHED(manager)) { /* * All tasks have completed and the @@ -163,19 +283,21 @@ task_finished(isc_task_t *task) { */ BROADCAST(&manager->work_available); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); DESTROYLOCK(&task->lock); - task->magic = 0; + task->common.impmagic = 0; + task->common.magic = 0; isc_mem_put(manager->mctx, task, sizeof(*task)); } -isc_result_t -isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, - isc_task_t **taskp) +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum, + isc_task_t **taskp) { - isc_task_t *task; + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + isc__task_t *task; isc_boolean_t exiting; isc_result_t result; @@ -220,14 +342,17 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, return (ISC_R_SHUTTINGDOWN); } - task->magic = TASK_MAGIC; - *taskp = task; + task->common.methods = (isc_taskmethods_t *)&taskmethods; + task->common.magic = ISCAPI_TASK_MAGIC; + task->common.impmagic = TASK_MAGIC; + *taskp = (isc_task_t *)task; return (ISC_R_SUCCESS); } -void -isc_task_attach(isc_task_t *source, isc_task_t **targetp) { +ISC_TASKFUNC_SCOPE void +isc__task_attach(isc_task_t *source0, isc_task_t **targetp) { + isc__task_t *source = (isc__task_t *)source0; /* * Attach *targetp to source. @@ -242,11 +367,11 @@ isc_task_attach(isc_task_t *source, isc_task_t **targetp) { source->references++; UNLOCK(&source->lock); - *targetp = source; + *targetp = (isc_task_t *)source; } static inline isc_boolean_t -task_shutdown(isc_task_t *task) { +task_shutdown(isc__task_t *task) { isc_boolean_t was_idle = ISC_FALSE; isc_event_t *event, *prev; @@ -283,8 +408,8 @@ task_shutdown(isc_task_t *task) { } static inline void -task_ready(isc_task_t *task) { - isc_taskmgr_t *manager = task->manager; +task_ready(isc__task_t *task) { + isc__taskmgr_t *manager = task->manager; REQUIRE(VALID_MANAGER(manager)); REQUIRE(task->state == task_state_ready); @@ -294,15 +419,15 @@ task_ready(isc_task_t *task) { LOCK(&manager->lock); ENQUEUE(manager->ready_tasks, task, ready_link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS SIGNAL(&manager->work_available); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); } static inline isc_boolean_t -task_detach(isc_task_t *task) { +task_detach(isc__task_t *task) { /* * Caller must be holding the task lock. @@ -330,9 +455,9 @@ task_detach(isc_task_t *task) { return (ISC_FALSE); } -void -isc_task_detach(isc_task_t **taskp) { - isc_task_t *task; +ISC_TASKFUNC_SCOPE void +isc__task_detach(isc_task_t **taskp) { + isc__task_t *task; isc_boolean_t was_idle; /* @@ -340,7 +465,7 @@ isc_task_detach(isc_task_t **taskp) { */ REQUIRE(taskp != NULL); - task = *taskp; + task = (isc__task_t *)*taskp; REQUIRE(VALID_TASK(task)); XTRACE("isc_task_detach"); @@ -356,7 +481,7 @@ isc_task_detach(isc_task_t **taskp) { } static inline isc_boolean_t -task_send(isc_task_t *task, isc_event_t **eventp) { +task_send(isc__task_t *task, isc_event_t **eventp) { isc_boolean_t was_idle = ISC_FALSE; isc_event_t *event; @@ -385,8 +510,9 @@ task_send(isc_task_t *task, isc_event_t **eventp) { return (was_idle); } -void -isc_task_send(isc_task_t *task, isc_event_t **eventp) { +ISC_TASKFUNC_SCOPE void +isc__task_send(isc_task_t *task0, isc_event_t **eventp) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t was_idle; /* @@ -426,10 +552,10 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp) { } } -void -isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { +ISC_TASKFUNC_SCOPE void +isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { isc_boolean_t idle1, idle2; - isc_task_t *task; + isc__task_t *task; /* * Send '*event' to '*taskp' and then detach '*taskp' from its @@ -437,7 +563,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { */ REQUIRE(taskp != NULL); - task = *taskp; + task = (isc__task_t *)*taskp; REQUIRE(VALID_TASK(task)); XTRACE("isc_task_sendanddetach"); @@ -463,7 +589,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { #define PURGE_OK(event) (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0) static unsigned int -dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first, +dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first, isc_eventtype_t last, void *tag, isc_eventlist_t *events, isc_boolean_t purging) { @@ -502,10 +628,11 @@ dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first, return (count); } -unsigned int -isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, - isc_eventtype_t last, void *tag) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag) { + isc__task_t *task = (isc__task_t *)task0; unsigned int count; isc_eventlist_t events; isc_event_t *event, *next_event; @@ -533,9 +660,9 @@ isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, return (count); } -unsigned int -isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, - void *tag) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag) { /* * Purge events from a task's event queue. @@ -543,11 +670,12 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, XTRACE("isc_task_purge"); - return (isc_task_purgerange(task, sender, type, type, tag)); + return (isc__task_purgerange(task, sender, type, type, tag)); } -isc_boolean_t -isc_task_purgeevent(isc_task_t *task, isc_event_t *event) { +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) { + isc__task_t *task = (isc__task_t *)task0; isc_event_t *curr_event, *next_event; /* @@ -588,10 +716,10 @@ isc_task_purgeevent(isc_task_t *task, isc_event_t *event) { return (ISC_TRUE); } -unsigned int -isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, - isc_eventtype_t last, void *tag, - isc_eventlist_t *events) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag, + isc_eventlist_t *events) { /* * Remove events from a task's event queue. @@ -599,13 +727,13 @@ isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, XTRACE("isc_task_unsendrange"); - return (dequeue_events(task, sender, first, last, tag, events, - ISC_FALSE)); + return (dequeue_events((isc__task_t *)task, sender, first, + last, tag, events, ISC_FALSE)); } -unsigned int -isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, - void *tag, isc_eventlist_t *events) +ISC_TASKFUNC_SCOPE unsigned int +isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events) { /* * Remove events from a task's event queue. @@ -613,13 +741,15 @@ isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, XTRACE("isc_task_unsend"); - return (dequeue_events(task, sender, type, type, tag, events, - ISC_FALSE)); + return (dequeue_events((isc__task_t *)task, sender, type, + type, tag, events, ISC_FALSE)); } -isc_result_t -isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action, + const void *arg) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t disallowed = ISC_FALSE; isc_result_t result = ISC_R_SUCCESS; isc_event_t *event; @@ -655,8 +785,9 @@ isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) return (result); } -void -isc_task_shutdown(isc_task_t *task) { +ISC_TASKFUNC_SCOPE void +isc__task_shutdown(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; isc_boolean_t was_idle; /* @@ -673,8 +804,8 @@ isc_task_shutdown(isc_task_t *task) { task_ready(task); } -void -isc_task_destroy(isc_task_t **taskp) { +ISC_TASKFUNC_SCOPE void +isc__task_destroy(isc_task_t **taskp) { /* * Destroy '*taskp'. @@ -686,8 +817,9 @@ isc_task_destroy(isc_task_t **taskp) { isc_task_detach(taskp); } -void -isc_task_setname(isc_task_t *task, const char *name, void *tag) { +ISC_TASKFUNC_SCOPE void +isc__task_setname(isc_task_t *task0, const char *name, void *tag) { + isc__task_t *task = (isc__task_t *)task0; /* * Name 'task'. @@ -702,18 +834,28 @@ isc_task_setname(isc_task_t *task, const char *name, void *tag) { UNLOCK(&task->lock); } -const char * -isc_task_getname(isc_task_t *task) { +ISC_TASKFUNC_SCOPE const char * +isc__task_getname(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; + + REQUIRE(VALID_TASK(task)); + return (task->name); } -void * -isc_task_gettag(isc_task_t *task) { +ISC_TASKFUNC_SCOPE void * +isc__task_gettag(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; + + REQUIRE(VALID_TASK(task)); + return (task->tag); } -void -isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) { +ISC_TASKFUNC_SCOPE void +isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) { + isc__task_t *task = (isc__task_t *)task0; + REQUIRE(VALID_TASK(task)); REQUIRE(t != NULL); @@ -728,12 +870,12 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) { *** Task Manager. ***/ static void -dispatch(isc_taskmgr_t *manager) { - isc_task_t *task; -#ifndef ISC_PLATFORM_USETHREADS +dispatch(isc__taskmgr_t *manager) { + isc__task_t *task; +#ifndef USE_WORKER_THREADS unsigned int total_dispatch_count = 0; - isc_tasklist_t ready_tasks; -#endif /* ISC_PLATFORM_USETHREADS */ + isc__tasklist_t ready_tasks; +#endif /* USE_WORKER_THREADS */ REQUIRE(VALID_MANAGER(manager)); @@ -787,12 +929,12 @@ dispatch(isc_taskmgr_t *manager) { * unlocks. The while expression is always protected by the lock. */ -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS ISC_LIST_INIT(ready_tasks); #endif LOCK(&manager->lock); while (!FINISHED(manager)) { -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS /* * For reasons similar to those given in the comment in * isc_task_send() above, it is safe for us to dequeue @@ -812,11 +954,11 @@ dispatch(isc_taskmgr_t *manager) { ISC_MSGSET_TASK, ISC_MSG_AWAKE, "awake")); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WORKER_THREADS */ if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM || EMPTY(manager->ready_tasks)) break; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK, ISC_MSG_WORKING, "working")); @@ -859,13 +1001,15 @@ dispatch(isc_taskmgr_t *manager) { "execute action")); if (event->ev_action != NULL) { UNLOCK(&task->lock); - (event->ev_action)(task,event); + (event->ev_action)( + (isc_task_t *)task, + event); LOCK(&task->lock); } dispatch_count++; -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS total_dispatch_count++; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ } if (task->references == 0 && @@ -950,12 +1094,12 @@ dispatch(isc_taskmgr_t *manager) { LOCK(&manager->lock); manager->tasks_running--; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS if (manager->exclusive_requested && manager->tasks_running == 1) { SIGNAL(&manager->exclusive_granted); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ if (requeue) { /* * We know we're awake, so we don't have @@ -976,7 +1120,7 @@ dispatch(isc_taskmgr_t *manager) { * were usually nonempty, the 'optimization' * might even hurt rather than help. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS ENQUEUE(manager->ready_tasks, task, ready_link); #else @@ -985,19 +1129,19 @@ dispatch(isc_taskmgr_t *manager) { } } } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link); #endif UNLOCK(&manager->lock); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS static isc_threadresult_t #ifdef _WIN32 WINAPI #endif run(void *uap) { - isc_taskmgr_t *manager = uap; + isc__taskmgr_t *manager = uap; XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_STARTING, "starting")); @@ -1009,31 +1153,36 @@ run(void *uap) { return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ static void -manager_free(isc_taskmgr_t *manager) { +manager_free(isc__taskmgr_t *manager) { isc_mem_t *mctx; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS (void)isc_condition_destroy(&manager->exclusive_granted); (void)isc_condition_destroy(&manager->work_available); isc_mem_free(manager->mctx, manager->threads); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ DESTROYLOCK(&manager->lock); - manager->magic = 0; + manager->common.impmagic = 0; + manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); + +#ifdef USE_SHARED_MANAGER + taskmgr = NULL; +#endif /* USE_SHARED_MANAGER */ } -isc_result_t -isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, - unsigned int default_quantum, isc_taskmgr_t **managerp) +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp) { isc_result_t result; unsigned int i, started = 0; - isc_taskmgr_t *manager; + isc__taskmgr_t *manager; /* * Create a new task manager. @@ -1042,28 +1191,31 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, REQUIRE(workers > 0); REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS UNUSED(i); UNUSED(started); - UNUSED(workers); +#endif +#ifdef USE_SHARED_MANAGER if (taskmgr != NULL) { taskmgr->refs++; - *managerp = taskmgr; + *managerp = (isc_taskmgr_t *)taskmgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); - manager->magic = TASK_MANAGER_MAGIC; + manager->common.methods = &taskmgrmethods; + manager->common.impmagic = TASK_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TASKMGR_MAGIC; manager->mctx = NULL; result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) goto cleanup_mgr; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, workers * sizeof(isc_thread_t)); @@ -1087,7 +1239,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, result = ISC_R_UNEXPECTED; goto cleanup_workavailable; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ if (default_quantum == 0) default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; @@ -1099,7 +1251,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, isc_mem_attach(mctx, &manager->mctx); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS LOCK(&manager->lock); /* * Start workers. @@ -1119,16 +1271,17 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (ISC_R_NOTHREADS); } isc_thread_setconcurrency(workers); -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ +#ifdef USE_SHARED_MANAGER manager->refs = 1; taskmgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ - *managerp = manager; + *managerp = (isc_taskmgr_t *)manager; return (ISC_R_SUCCESS); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS cleanup_workavailable: (void)isc_condition_destroy(&manager->work_available); cleanup_threads: @@ -1141,10 +1294,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (result); } -void -isc_taskmgr_destroy(isc_taskmgr_t **managerp) { - isc_taskmgr_t *manager; - isc_task_t *task; +ISC_TASKFUNC_SCOPE void +isc__taskmgr_destroy(isc_taskmgr_t **managerp) { + isc__taskmgr_t *manager; + isc__task_t *task; unsigned int i; /* @@ -1152,18 +1305,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__taskmgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS UNUSED(i); +#endif /* USE_WORKER_THREADS */ +#ifdef USE_SHARED_MANAGER if (manager->refs > 1) { manager->refs--; *managerp = NULL; return; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif XTHREADTRACE("isc_taskmgr_destroy"); /* @@ -1203,7 +1358,7 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { ENQUEUE(manager->ready_tasks, task, ready_link); UNLOCK(&task->lock); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WORKER_THREADS /* * Wake up any sleeping workers. This ensures we get work done if * there's work left to do, and if there are already no tasks left @@ -1217,36 +1372,48 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { */ for (i = 0; i < manager->workers; i++) (void)isc_thread_join(manager->threads[i], NULL); -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WORKER_THREADS */ /* * Dispatch the shutdown events. */ UNLOCK(&manager->lock); - while (isc__taskmgr_ready()) - (void)isc__taskmgr_dispatch(); + while (isc__taskmgr_ready((isc_taskmgr_t *)manager)) + (void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager); +#ifdef BIND9 if (!ISC_LIST_EMPTY(manager->tasks)) isc_mem_printallactive(stderr); +#endif INSIST(ISC_LIST_EMPTY(manager->tasks)); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ manager_free(manager); *managerp = NULL; } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WORKER_THREADS isc_boolean_t -isc__taskmgr_ready(void) { - if (taskmgr == NULL) +isc__taskmgr_ready(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = taskmgr; +#endif + if (manager == NULL) return (ISC_FALSE); - return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks))); + return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks))); } isc_result_t -isc__taskmgr_dispatch(void) { - isc_taskmgr_t *manager = taskmgr; +isc__taskmgr_dispatch(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; - if (taskmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = taskmgr; +#endif + if (manager == NULL) return (ISC_R_NOTFOUND); dispatch(manager); @@ -1254,12 +1421,13 @@ isc__taskmgr_dispatch(void) { return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WORKER_THREADS */ -isc_result_t -isc_task_beginexclusive(isc_task_t *task) { -#ifdef ISC_PLATFORM_USETHREADS - isc_taskmgr_t *manager = task->manager; +ISC_TASKFUNC_SCOPE isc_result_t +isc__task_beginexclusive(isc_task_t *task0) { +#ifdef USE_WORKER_THREADS + isc__task_t *task = (isc__task_t *)task0; + isc__taskmgr_t *manager = task->manager; REQUIRE(task->state == task_state_running); LOCK(&manager->lock); if (manager->exclusive_requested) { @@ -1272,15 +1440,17 @@ isc_task_beginexclusive(isc_task_t *task) { } UNLOCK(&manager->lock); #else - UNUSED(task); + UNUSED(task0); #endif return (ISC_R_SUCCESS); } -void -isc_task_endexclusive(isc_task_t *task) { -#ifdef ISC_PLATFORM_USETHREADS - isc_taskmgr_t *manager = task->manager; +ISC_TASKFUNC_SCOPE void +isc__task_endexclusive(isc_task_t *task0) { +#ifdef USE_WORKER_THREADS + isc__task_t *task = (isc__task_t *)task0; + isc__taskmgr_t *manager = task->manager; + REQUIRE(task->state == task_state_running); LOCK(&manager->lock); REQUIRE(manager->exclusive_requested); @@ -1288,16 +1458,22 @@ isc_task_endexclusive(isc_task_t *task) { BROADCAST(&manager->work_available); UNLOCK(&manager->lock); #else - UNUSED(task); + UNUSED(task0); #endif } -#ifdef HAVE_LIBXML2 +#ifdef USE_SOCKETIMPREGISTER +isc_result_t +isc__task_register() { + return (isc_task_register(isc__taskmgr_create)); +} +#endif +#if defined(HAVE_LIBXML2) && defined(BIND9) void -isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer) -{ - isc_task_t *task; +isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) { + isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0; + isc__task_t *task; LOCK(&mgr->lock); @@ -1373,4 +1549,4 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer) UNLOCK(&mgr->lock); } -#endif /* HAVE_LIBXML2 */ +#endif /* HAVE_LIBXML2 && BIND9 */ diff --git a/lib/isc/task_api.c b/lib/isc/task_api.c new file mode 100644 index 0000000000..ff5c5c5cd6 --- /dev/null +++ b/lib/isc/task_api.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: task_api.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_task_register(isc_taskmgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (taskmgr_createfunc == NULL) + taskmgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + unsigned int workers, unsigned int default_quantum, + isc_taskmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(taskmgr_createfunc != NULL); + result = (*taskmgr_createfunc)(mctx, workers, default_quantum, + managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_settaskmgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, + unsigned int default_quantum, isc_taskmgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(taskmgr_createfunc != NULL); + result = (*taskmgr_createfunc)(mctx, workers, default_quantum, + managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_taskmgr_destroy(isc_taskmgr_t **managerp) { + REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +}; + +isc_result_t +isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, + isc_task_t **taskp) +{ + REQUIRE(ISCAPI_TASKMGR_VALID(manager)); + REQUIRE(taskp != NULL && *taskp == NULL); + + return (manager->methods->taskcreate(manager, quantum, taskp)); +} + +void +isc_task_attach(isc_task_t *source, isc_task_t **targetp) { + REQUIRE(ISCAPI_TASK_VALID(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + source->methods->attach(source, targetp); + + ENSURE(*targetp == source); +} + +void +isc_task_detach(isc_task_t **taskp) { + REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); + + (*taskp)->methods->detach(taskp); + + ENSURE(*taskp == NULL); +} + +void +isc_task_send(isc_task_t *task, isc_event_t **eventp) { + REQUIRE(ISCAPI_TASK_VALID(task)); + REQUIRE(eventp != NULL && *eventp != NULL); + + task->methods->send(task, eventp); + + ENSURE(*eventp == NULL); +} + +void +isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { + REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); + REQUIRE(eventp != NULL && *eventp != NULL); + + (*taskp)->methods->sendanddetach(taskp, eventp); + + ENSURE(*taskp == NULL && *eventp == NULL); +} + +unsigned int +isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, + void *tag, isc_eventlist_t *events) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->unsend(task, sender, type, tag, events)); +} + +isc_result_t +isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->onshutdown(task, action, arg)); +} + +void +isc_task_shutdown(isc_task_t *task) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->shutdown(task); +} + +void +isc_task_setname(isc_task_t *task, const char *name, void *tag) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->setname(task, name, tag); +} + +unsigned int +isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->purgeevents(task, sender, type, tag)); +} + +/*% + * This is necessary for libisc's internal timer implementation. Other + * implementation might skip implementing this. + */ +unsigned int +isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, + isc_eventtype_t last, void *tag) +{ + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->purgerange(task, sender, first, last, tag)); +} diff --git a/lib/isc/task_p.h b/lib/isc/task_p.h index c888103908..75cba60a0f 100644 --- a/lib/isc/task_p.h +++ b/lib/isc/task_p.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task_p.h,v 1.11 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: task_p.h,v 1.12 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_TASK_P_H #define ISC_TASK_P_H @@ -23,9 +23,9 @@ /*! \file */ isc_boolean_t -isc__taskmgr_ready(void); +isc__taskmgr_ready(isc_taskmgr_t *taskmgr); isc_result_t -isc__taskmgr_dispatch(void); +isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr); #endif /* ISC_TASK_P_H */ diff --git a/lib/isc/timer.c b/lib/isc/timer.c index b40f404c8b..4a715e1638 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer.c,v 1.89 2009/01/23 23:47:54 tbox Exp $ */ +/* $Id: timer.c,v 1.90 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file */ @@ -34,9 +34,18 @@ #include #include -#ifndef ISC_PLATFORM_USETHREADS +/* See task.c about the following definition: */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_TIMER_THREAD +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_TIMER_THREAD #include "timer_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ #ifdef ISC_TIMER_TRACE #define XTRACE(s) fprintf(stderr, "%s\n", (s)) @@ -58,10 +67,13 @@ #define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R') #define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC) -struct isc_timer { +typedef struct isc__timer isc__timer_t; +typedef struct isc__timermgr isc__timermgr_t; + +struct isc__timer { /*! Not locked. */ - unsigned int magic; - isc_timermgr_t * manager; + isc_timer_t common; + isc__timermgr_t * manager; isc_mutex_t lock; /*! Locked by timer lock. */ unsigned int references; @@ -75,45 +87,109 @@ struct isc_timer { void * arg; unsigned int index; isc_time_t due; - LINK(isc_timer_t) link; + LINK(isc__timer_t) link; }; #define TIMER_MANAGER_MAGIC ISC_MAGIC('T', 'I', 'M', 'M') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC) -struct isc_timermgr { +struct isc__timermgr { /* Not locked. */ - unsigned int magic; + isc_timermgr_t common; isc_mem_t * mctx; isc_mutex_t lock; /* Locked by manager lock. */ isc_boolean_t done; - LIST(isc_timer_t) timers; + LIST(isc__timer_t) timers; unsigned int nscheduled; isc_time_t due; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_condition_t wakeup; isc_thread_t thread; -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ +#ifdef USE_SHARED_MANAGER unsigned int refs; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ isc_heap_t * heap; }; -#ifndef ISC_PLATFORM_USETHREADS -/*! - * If threads are not in use, there can be only one. +/*% + * The followings can be either static or public, depending on build + * environment. */ -static isc_timermgr_t *timermgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ + +#ifdef BIND9 +#define ISC_TIMERFUNC_SCOPE +#else +#define ISC_TIMERFUNC_SCOPE static +#endif + +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_reset(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_gettype(isc_timer_t *timer); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_touch(isc_timer_t *timer); +ISC_TIMERFUNC_SCOPE void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE void +isc__timer_detach(isc_timer_t **timerp); +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); +ISC_TIMERFUNC_SCOPE void +isc__timermgr_poke(isc_timermgr_t *manager0); +ISC_TIMERFUNC_SCOPE void +isc__timermgr_destroy(isc_timermgr_t **managerp); + +static struct isc__timermethods { + isc_timermethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *gettype; +} timermethods = { + { + isc__timer_attach, + isc__timer_detach, + isc__timer_reset, + isc__timer_touch + }, + isc__timer_gettype +}; + +static struct isc__timermgrmethods { + isc_timermgrmethods_t methods; + void *poke; /* see above */ +} timermgrmethods = { + { + isc__timermgr_destroy, + isc__timer_create + }, + isc__timermgr_poke +}; + +#ifdef USE_SHARED_MANAGER +/*! + * If the manager is supposed to be shared, there can be only one. + */ +static isc__timermgr_t *timermgr = NULL; +#endif /* USE_SHARED_MANAGER */ static inline isc_result_t -schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { +schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { isc_result_t result; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_time_t due; int cmp; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_boolean_t timedwait; #endif @@ -123,13 +199,13 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { REQUIRE(timer->type != isc_timertype_inactive); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD UNUSED(signal_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ manager = timer->manager; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /*! * If the manager was timed wait, we may need to signal the * manager to force a wakeup. @@ -199,7 +275,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { * the current "next" timer. We do this either by waking up the * run thread, or explicitly setting the value in the manager. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * This is a temporary (probably) hack to fix a bug on tru64 5.1 @@ -232,19 +308,19 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { "signal (schedule)")); SIGNAL(&manager->wakeup); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_TIMER_THREAD */ if (timer->index == 1 && isc_time_compare(&timer->due, &manager->due) < 0) manager->due = timer->due; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ return (ISC_R_SUCCESS); } static inline void -deschedule(isc_timer_t *timer) { +deschedule(isc__timer_t *timer) { isc_boolean_t need_wakeup = ISC_FALSE; - isc_timermgr_t *manager; + isc__timermgr_t *manager; /* * The caller must ensure locking. @@ -258,20 +334,20 @@ deschedule(isc_timer_t *timer) { timer->index = 0; INSIST(manager->nscheduled > 0); manager->nscheduled--; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (need_wakeup) { XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESCHED, "signal (deschedule)")); SIGNAL(&manager->wakeup); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ } } static void -destroy(isc_timer_t *timer) { - isc_timermgr_t *manager = timer->manager; +destroy(isc__timer_t *timer) { + isc__timermgr_t *manager = timer->manager; /* * The caller must ensure it is safe to destroy the timer. @@ -291,17 +367,19 @@ destroy(isc_timer_t *timer) { isc_task_detach(&timer->task); DESTROYLOCK(&timer->lock); - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; isc_mem_put(manager->mctx, timer, sizeof(*timer)); } -isc_result_t -isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_timer_t **timerp) +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp) { - isc_timer_t *timer; + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + isc__timer_t *timer; isc_result_t result; isc_time_t now; @@ -382,7 +460,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, return (result); } ISC_LINK_INIT(timer, link); - timer->magic = TIMER_MAGIC; + timer->common.impmagic = TIMER_MAGIC; + timer->common.magic = ISCAPI_TIMER_MAGIC; + timer->common.methods = (isc_timermethods_t *)&timermethods; LOCK(&manager->lock); @@ -401,25 +481,27 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; DESTROYLOCK(&timer->lock); isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } - *timerp = timer; + *timerp = (isc_timer_t *)timer; return (ISC_R_SUCCESS); } -isc_result_t -isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_boolean_t purge) +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_time_t now; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_result_t result; /* @@ -489,8 +571,9 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, return (result); } -isc_timertype_t -isc_timer_gettype(isc_timer_t *timer) { +ISC_TIMERFUNC_SCOPE isc_timertype_t +isc__timer_gettype(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_timertype_t t; REQUIRE(VALID_TIMER(timer)); @@ -502,8 +585,9 @@ isc_timer_gettype(isc_timer_t *timer) { return (t); } -isc_result_t -isc_timer_touch(isc_timer_t *timer) { +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timer_touch(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_result_t result; isc_time_t now; @@ -532,8 +616,10 @@ isc_timer_touch(isc_timer_t *timer) { return (result); } -void -isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { +ISC_TIMERFUNC_SCOPE void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) { + isc__timer_t *timer = (isc__timer_t *)timer0; + /* * Attach *timerp to timer. */ @@ -545,12 +631,12 @@ isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { timer->references++; UNLOCK(&timer->lock); - *timerp = timer; + *timerp = (isc_timer_t *)timer; } -void -isc_timer_detach(isc_timer_t **timerp) { - isc_timer_t *timer; +ISC_TIMERFUNC_SCOPE void +isc__timer_detach(isc_timer_t **timerp) { + isc__timer_t *timer; isc_boolean_t free_timer = ISC_FALSE; /* @@ -558,7 +644,7 @@ isc_timer_detach(isc_timer_t **timerp) { */ REQUIRE(timerp != NULL); - timer = *timerp; + timer = (isc__timer_t *)*timerp; REQUIRE(VALID_TIMER(timer)); LOCK(&timer->lock); @@ -575,11 +661,11 @@ isc_timer_detach(isc_timer_t **timerp) { } static void -dispatch(isc_timermgr_t *manager, isc_time_t *now) { +dispatch(isc__timermgr_t *manager, isc_time_t *now) { isc_boolean_t done = ISC_FALSE, post_event, need_schedule; isc_timerevent_t *event; isc_eventtype_t type = 0; - isc_timer_t *timer; + isc__timer_t *timer; isc_result_t result; isc_boolean_t idle; @@ -693,13 +779,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD static isc_threadresult_t #ifdef _WIN32 /* XXXDCL */ WINAPI #endif run(void *uap) { - isc_timermgr_t *manager = uap; + isc__timermgr_t *manager = uap; isc_time_t now; isc_result_t result; @@ -734,11 +820,11 @@ run(void *uap) { return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ static isc_boolean_t sooner(void *v1, void *v2) { - isc_timer_t *t1, *t2; + isc__timer_t *t1, *t2; t1 = v1; t2 = v2; @@ -752,7 +838,7 @@ sooner(void *v1, void *v2) { static void set_index(void *what, unsigned int index) { - isc_timer_t *timer; + isc__timer_t *timer; timer = what; REQUIRE(VALID_TIMER(timer)); @@ -760,9 +846,9 @@ set_index(void *what, unsigned int index) { timer->index = index; } -isc_result_t -isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +ISC_TIMERFUNC_SCOPE isc_result_t +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_result_t result; /* @@ -771,19 +857,21 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (timermgr != NULL) { timermgr->refs++; - *managerp = timermgr; + *managerp = (isc_timermgr_t *)timermgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); - manager->magic = TIMER_MANAGER_MAGIC; + manager->common.impmagic = TIMER_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TIMERMGR_MAGIC; + manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods; manager->mctx = NULL; manager->done = ISC_FALSE; INIT_LIST(manager->timers); @@ -803,7 +891,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { return (result); } isc_mem_attach(mctx, &manager->mctx); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) { isc_mem_detach(&manager->mctx); DESTROYLOCK(&manager->lock); @@ -828,30 +916,33 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { ISC_MSG_FAILED, "failed")); return (ISC_R_UNEXPECTED); } -#else /* ISC_PLATFORM_USETHREADS */ +#endif +#ifdef USE_SHARED_MANAGER manager->refs = 1; timermgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ - *managerp = manager; + *managerp = (isc_timermgr_t *)manager; return (ISC_R_SUCCESS); } -void -isc_timermgr_poke(isc_timermgr_t *manager) { -#ifdef ISC_PLATFORM_USETHREADS +ISC_TIMERFUNC_SCOPE void +isc__timermgr_poke(isc_timermgr_t *manager0) { +#ifdef USE_TIMER_THREAD + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); SIGNAL(&manager->wakeup); #else - UNUSED(manager); + UNUSED(manager0); #endif } -void -isc_timermgr_destroy(isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +ISC_TIMERFUNC_SCOPE void +isc__timermgr_destroy(isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_mem_t *mctx; /* @@ -859,34 +950,36 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__timermgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (manager->refs > 1) { manager->refs--; UNLOCK(&manager->lock); *managerp = NULL; return; } +#endif /* USE_SHARED_MANAGER */ - isc__timermgr_dispatch(); -#endif /* ISC_PLATFORM_USETHREADS */ +#ifndef USE_TIMER_THREAD + isc__timermgr_dispatch((isc_timermgr_t *)manager); +#endif REQUIRE(EMPTY(manager->timers)); manager->done = ISC_TRUE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESTROY, "signal (destroy)")); SIGNAL(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ UNLOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * Wait for thread to exit. */ @@ -895,39 +988,63 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ /* * Clean up. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD (void)isc_condition_destroy(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); - manager->magic = 0; + manager->common.impmagic = 0; + manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; + +#ifdef USE_SHARED_MANAGER + timermgr = NULL; +#endif } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD isc_result_t -isc__timermgr_nextevent(isc_time_t *when) { - if (timermgr == NULL || timermgr->nscheduled == 0) +isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL || manager->nscheduled == 0) return (ISC_R_NOTFOUND); - *when = timermgr->due; + *when = manager->due; return (ISC_R_SUCCESS); } void -isc__timermgr_dispatch(void) { +isc__timermgr_dispatch(isc_timermgr_t *manager0) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; isc_time_t now; - if (timermgr == NULL) + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL) return; TIME_NOW(&now); - dispatch(timermgr, &now); + dispatch(manager, &now); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ + +#ifdef USE_TIMERIMPREGISTER +isc_result_t +isc__timer_register() { + return (isc_timer_register(isc__timermgr_create)); +} +#endif diff --git a/lib/isc/timer_api.c b/lib/isc/timer_api.c new file mode 100644 index 0000000000..07c3448d8d --- /dev/null +++ b/lib/isc/timer_api.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: timer_api.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#include + +#include +#include +#include +#include +#include +#include + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_timermgrcreatefunc_t timermgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (timermgr_createfunc == NULL) + timermgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_timermgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_settimermgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_timermgr_destroy(isc_timermgr_t **managerp) { + REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp)); + + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_timer_t **timerp) +{ + REQUIRE(ISCAPI_TIMERMGR_VALID(manager)); + + return (manager->methods->timercreate(manager, type, expires, + interval, task, action, arg, + timerp)); +} + +void +isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + REQUIRE(timerp != NULL && *timerp == NULL); + + timer->methods->attach(timer, timerp); + + ENSURE(*timerp == timer); +} + +void +isc_timer_detach(isc_timer_t **timerp) { + REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp)); + + (*timerp)->methods->detach(timerp); + + ENSURE(*timerp == NULL); +} + +isc_result_t +isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, + isc_time_t *expires, isc_interval_t *interval, + isc_boolean_t purge) +{ + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (timer->methods->reset(timer, type, expires, interval, purge)); +} + +isc_result_t +isc_timer_touch(isc_timer_t *timer) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (timer->methods->touch(timer)); +} diff --git a/lib/isc/timer_p.h b/lib/isc/timer_p.h index ec8e2e0b78..5e66bbe4bb 100644 --- a/lib/isc/timer_p.h +++ b/lib/isc/timer_p.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: timer_p.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */ +/* $Id: timer_p.h,v 1.11 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_TIMER_P_H #define ISC_TIMER_P_H @@ -23,9 +23,9 @@ /*! \file */ isc_result_t -isc__timermgr_nextevent(isc_time_t *when); +isc__timermgr_nextevent(isc_timermgr_t *timermgr, isc_time_t *when); void -isc__timermgr_dispatch(void); +isc__timermgr_dispatch(isc_timermgr_t *timermgr); #endif /* ISC_TIMER_P_H */ diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in index 7d19b5c042..861048dd93 100644 --- a/lib/isc/unix/Makefile.in +++ b/lib/isc/unix/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.41 2007/06/19 23:47:18 tbox Exp $ +# $Id: Makefile.in,v 1.42 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,7 +25,7 @@ CINCLUDES = -I${srcdir}/include \ -I${srcdir}/../include \ -I${srcdir}/.. -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = # Alphabetically diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c index 660b438678..10b99f05f9 100644 --- a/lib/isc/unix/app.c +++ b/lib/isc/unix/app.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: app.c,v 1.60 2008/10/15 03:41:17 marka Exp $ */ +/* $Id: app.c,v 1.61 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file */ @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -47,18 +48,26 @@ #include #include +/*% + * For BIND9 internal applications built with threads, we use a single app + * context and let multiple worker, I/O, timer threads do actual jobs. + * For other cases (including BIND9 built without threads) an app context acts + * as an event loop dispatching various events. + */ +#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9) +#define USE_THREADS_SINGLECTX +#endif + #ifdef ISC_PLATFORM_USETHREADS #include -#else /* ISC_PLATFORM_USETHREADS */ +#endif + +#ifndef USE_THREADS_SINGLECTX #include "../timer_p.h" #include "../task_p.h" #include "socket_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_THREADS_SINGLECTX */ -static isc_eventlist_t on_run; -static isc_mutex_t lock; -static isc_boolean_t shutdown_requested = ISC_FALSE; -static isc_boolean_t running = ISC_FALSE; /*! * We assume that 'want_shutdown' can be read and written atomically. */ @@ -68,11 +77,104 @@ static volatile isc_boolean_t want_shutdown = ISC_FALSE; */ static volatile isc_boolean_t want_reload = ISC_FALSE; -static isc_boolean_t blocked = ISC_FALSE; #ifdef ISC_PLATFORM_USETHREADS static pthread_t blockedthread; #endif /* ISC_PLATFORM_USETHREADS */ +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_APPFUNC_SCOPE +#else +#define ISC_APPFUNC_SCOPE static +#endif + +ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx, + isc_task_t *task, + isc_taskaction_t action, + void *arg); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void); +ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx); +ISC_APPFUNC_SCOPE void isc__app_finish(void); +ISC_APPFUNC_SCOPE void isc__app_block(void); +ISC_APPFUNC_SCOPE void isc__app_unblock(void); +ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx, + isc_appctx_t **ctxp); +ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp); +ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx, + isc_taskmgr_t *taskmgr); +ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx, + isc_socketmgr_t *socketmgr); +ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx, + isc_timermgr_t *timermgr); + +/* + * The application context of this module. This implementation actually + * doesn't use it. (This may change in the future). + */ +#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x') +#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC) + +typedef struct isc__appctx { + isc_appctx_t common; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_eventlist_t on_run; + isc_boolean_t shutdown_requested; + isc_boolean_t running; + + /*! + * We assume that 'want_shutdown' can be read and written atomically. + */ + isc_boolean_t want_shutdown; + /* + * We assume that 'want_reload' can be read and written atomically. + */ + isc_boolean_t want_reload; + + isc_boolean_t blocked; + + isc_taskmgr_t *taskmgr; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; +} isc__appctx_t; + +static isc__appctx_t isc_g_appctx; + +static struct { + isc_appmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *run, *shutdown, *start, *onrun, *reload, *finish, + *block, *unblock; +} appmethods = { + { + isc__appctx_destroy, + isc__app_ctxstart, + isc__app_ctxrun, + isc__app_ctxsuspend, + isc__app_ctxshutdown, + isc__app_ctxfinish, + isc__appctx_settaskmgr, + isc__appctx_setsocketmgr, + isc__appctx_settimermgr + }, + isc__app_run, isc__app_shutdown, + isc__app_start, isc__app_onrun, isc__app_reload, isc__app_finish, + isc__app_block, isc__app_unblock +}; + #ifdef HAVE_LINUXTHREADS /*! * Linux has sigwait(), but it appears to prevent signal handlers from @@ -91,13 +193,13 @@ static pthread_t main_thread; static void exit_action(int arg) { UNUSED(arg); - want_shutdown = ISC_TRUE; + isc_g_appctx.want_shutdown = ISC_TRUE; } static void reload_action(int arg) { UNUSED(arg); - want_reload = ISC_TRUE; + isc_g_appctx.want_reload = ISC_TRUE; } #endif @@ -123,12 +225,12 @@ handle_signal(int sig, void (*handler)(int)) { return (ISC_R_SUCCESS); } -isc_result_t -isc_app_start(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxstart(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_result_t result; - int presult; - sigset_t sset; - char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_APPCTX(ctx)); /* * Start an ISC library application. @@ -151,7 +253,35 @@ isc_app_start(void) { main_thread = pthread_self(); #endif - result = isc_mutex_init(&lock); + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) + return (result); + + ISC_LIST_INIT(ctx->on_run); + + ctx->shutdown_requested = ISC_FALSE; + ctx->running = ISC_FALSE; + ctx->want_shutdown = ISC_FALSE; + ctx->want_reload = ISC_FALSE; + ctx->blocked = ISC_FALSE; + + return (ISC_R_SUCCESS); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_start(void) { + isc_result_t result; + int presult; + sigset_t sset; + char strbuf[ISC_STRERRORSIZE]; + + isc_g_appctx.common.impmagic = APPCTX_MAGIC; + isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; + isc_g_appctx.common.methods = &appmethods.methods; + isc_g_appctx.mctx = NULL; + /* The remaining members will be initialized in ctxstart() */ + + result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx); if (result != ISC_R_SUCCESS) return (result); @@ -253,22 +383,20 @@ isc_app_start(void) { } #endif /* ISC_PLATFORM_USETHREADS */ - ISC_LIST_INIT(on_run); - return (ISC_R_SUCCESS); } -isc_result_t -isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, +ISC_APPFUNC_SCOPE isc_result_t +isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { isc_event_t *event; isc_task_t *cloned_task = NULL; isc_result_t result; - LOCK(&lock); + LOCK(&isc_g_appctx.lock); - if (running) { + if (isc_g_appctx.running) { result = ISC_R_ALREADYRUNNING; goto unlock; } @@ -285,24 +413,25 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, goto unlock; } - ISC_LIST_APPEND(on_run, event, ev_link); + ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link); result = ISC_R_SUCCESS; unlock: - UNLOCK(&lock); + UNLOCK(&isc_g_appctx.lock); return (result); } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_THREADS_SINGLECTX /*! * Event loop for nonthreaded programs. */ static isc_result_t -evloop(void) { +evloop(isc__appctx_t *ctx) { isc_result_t result; - while (!want_shutdown) { + + while (!ctx->want_shutdown) { int n; isc_time_t when, now; struct timeval tv, *tvp; @@ -310,14 +439,27 @@ evloop(void) { isc_boolean_t readytasks; isc_boolean_t call_timer_dispatch = ISC_FALSE; - readytasks = isc__taskmgr_ready(); + /* + * Check the reload (or suspend) case first for exiting the + * loop as fast as possible in case: + * - the direct call to isc__taskmgr_dispatch() in + * isc__app_ctxrun() completes all the tasks so far, + * - there is thus currently no active task, and + * - there is a timer event + */ + if (ctx->want_reload) { + ctx->want_reload = ISC_FALSE; + return (ISC_R_RELOAD); + } + + readytasks = isc__taskmgr_ready(ctx->taskmgr); if (readytasks) { tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; call_timer_dispatch = ISC_TRUE; } else { - result = isc__timermgr_nextevent(&when); + result = isc__timermgr_nextevent(ctx->timermgr, &when); if (result != ISC_R_SUCCESS) tvp = NULL; else { @@ -334,7 +476,7 @@ evloop(void) { } swait = NULL; - n = isc__socketmgr_waitevents(tvp, &swait); + n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait); if (n == 0 || call_timer_dispatch) { /* @@ -351,11 +493,11 @@ evloop(void) { * call, since this loop only runs in the non-thread * mode. */ - isc__timermgr_dispatch(); + isc__timermgr_dispatch(ctx->timermgr); } if (n > 0) - (void)isc__socketmgr_dispatch(swait); - (void)isc__taskmgr_dispatch(); + (void)isc__socketmgr_dispatch(ctx->socketmgr, swait); + (void)isc__taskmgr_dispatch(ctx->taskmgr); if (want_reload) { want_reload = ISC_FALSE; @@ -364,7 +506,9 @@ evloop(void) { } return (ISC_R_SUCCESS); } +#endif /* USE_THREADS_SINGLECTX */ +#ifndef ISC_PLATFORM_USETHREADS /* * This is a gross hack to support waiting for condition * variables in nonthreaded programs in a limited way; @@ -400,11 +544,11 @@ isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) { INSIST(*mp == 1); /* Mutex must be locked on entry. */ --*mp; - result = evloop(); + result = evloop(&isc_g_appctx); if (result == ISC_R_RELOAD) - want_reload = ISC_TRUE; + isc_g_appctx.want_reload = ISC_TRUE; if (signalled) { - want_shutdown = ISC_FALSE; + isc_g_appctx.want_shutdown = ISC_FALSE; signalled = ISC_FALSE; } @@ -420,43 +564,46 @@ isc__nothread_signal_hack(isc_condition_t *cp) { INSIST(in_recursive_evloop); - want_shutdown = ISC_TRUE; + isc_g_appctx.want_shutdown = ISC_TRUE; signalled = ISC_TRUE; return (ISC_R_SUCCESS); } #endif /* ISC_PLATFORM_USETHREADS */ -isc_result_t -isc_app_run(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxrun(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; int result; isc_event_t *event, *next_event; isc_task_t *task; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_THREADS_SINGLECTX sigset_t sset; char strbuf[ISC_STRERRORSIZE]; #ifdef HAVE_SIGWAIT int sig; #endif -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_THREADS_SINGLECTX */ + + REQUIRE(VALID_APPCTX(ctx)); #ifdef HAVE_LINUXTHREADS REQUIRE(main_thread == pthread_self()); #endif - LOCK(&lock); + LOCK(&ctx->lock); - if (!running) { - running = ISC_TRUE; + if (!ctx->running) { + ctx->running = ISC_TRUE; /* * Post any on-run events (in FIFO order). */ - for (event = ISC_LIST_HEAD(on_run); + for (event = ISC_LIST_HEAD(ctx->on_run); event != NULL; event = next_event) { next_event = ISC_LIST_NEXT(event, ev_link); - ISC_LIST_UNLINK(on_run, event, ev_link); + ISC_LIST_UNLINK(ctx->on_run, event, ev_link); task = event->ev_sender; event->ev_sender = NULL; isc_task_sendanddetach(&task, &event); @@ -464,7 +611,7 @@ isc_app_run(void) { } - UNLOCK(&lock); + UNLOCK(&ctx->lock); #ifndef HAVE_SIGWAIT /* @@ -473,19 +620,27 @@ isc_app_run(void) { * We do this here to ensure that the signal handler is installed * (i.e. that it wasn't a "one-shot" handler). */ - result = handle_signal(SIGHUP, reload_action); - if (result != ISC_R_SUCCESS) - return (ISC_R_SUCCESS); + if (ctx == &isc_g_appctx) { + result = handle_signal(SIGHUP, reload_action); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + } #endif -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_THREADS_SINGLECTX + /* + * When we are using multiple contexts, we don't rely on signals. + */ + if (ctx != &isc_g_appctx) + return (ISC_R_SUCCESS); + /* * There is no danger if isc_app_shutdown() is called before we wait * for signals. Signals are blocked, so any such signal will simply * be made pending and we will get it when we call sigwait(). */ - while (!want_shutdown) { + while (!ctx->want_shutdown) { #ifdef HAVE_SIGWAIT /* * Wait for SIGHUP, SIGINT, or SIGTERM. @@ -503,21 +658,19 @@ isc_app_run(void) { #ifndef HAVE_UNIXWARE_SIGWAIT result = sigwait(&sset, &sig); if (result == 0) { - if (sig == SIGINT || - sig == SIGTERM) - want_shutdown = ISC_TRUE; + if (sig == SIGINT || sig == SIGTERM) + ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) - want_reload = ISC_TRUE; + ctx->want_reload = ISC_TRUE; } #else /* Using UnixWare sigwait semantics. */ sig = sigwait(&sset); if (sig >= 0) { - if (sig == SIGINT || - sig == SIGTERM) - want_shutdown = ISC_TRUE; + if (sig == SIGINT || sig == SIGTERM) + ctx->want_shutdown = ISC_TRUE; else if (sig == SIGHUP) - want_reload = ISC_TRUE; + ctx->want_reload = ISC_TRUE; } #endif /* HAVE_UNIXWARE_SIGWAIT */ @@ -528,131 +681,174 @@ isc_app_run(void) { if (sigemptyset(&sset) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", strbuf); + "isc_app_run() sigsetops: %s", + strbuf); return (ISC_R_UNEXPECTED); } result = sigsuspend(&sset); #endif /* HAVE_SIGWAIT */ - if (want_reload) { - want_reload = ISC_FALSE; + if (ctx->want_reload) { + ctx->want_reload = ISC_FALSE; return (ISC_R_RELOAD); } - if (want_shutdown && blocked) + if (ctx->want_shutdown && ctx->blocked) exit(1); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_THREADS_SINGLECTX */ - (void)isc__taskmgr_dispatch(); + (void)isc__taskmgr_dispatch(ctx->taskmgr); - result = evloop(); + result = evloop(ctx); if (result != ISC_R_SUCCESS) return (result); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_THREADS_SINGLECTX */ return (ISC_R_SUCCESS); } -isc_result_t -isc_app_shutdown(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_run() { + return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx)); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxshutdown(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_boolean_t want_kill = ISC_TRUE; char strbuf[ISC_STRERRORSIZE]; - LOCK(&lock); + REQUIRE(VALID_APPCTX(ctx)); - REQUIRE(running); + LOCK(&ctx->lock); - if (shutdown_requested) + REQUIRE(ctx->running); + + if (ctx->shutdown_requested) want_kill = ISC_FALSE; else - shutdown_requested = ISC_TRUE; + ctx->shutdown_requested = ISC_TRUE; - UNLOCK(&lock); + UNLOCK(&ctx->lock); if (want_kill) { + if (ctx != &isc_g_appctx) + ctx->want_shutdown = ISC_TRUE; + else { #ifdef HAVE_LINUXTHREADS - int result; + int result; - result = pthread_kill(main_thread, SIGTERM); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } + result = pthread_kill(main_thread, SIGTERM); + if (result != 0) { + isc__strerror(result, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_shutdown() " + "pthread_kill: %s", + strbuf); + return (ISC_R_UNEXPECTED); + } #else - if (kill(getpid(), SIGTERM) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() kill: %s", strbuf); - return (ISC_R_UNEXPECTED); + if (kill(getpid(), SIGTERM) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_shutdown() " + "kill: %s", strbuf); + return (ISC_R_UNEXPECTED); + } +#endif /* HAVE_LINUXTHREADS */ } -#endif } return (ISC_R_SUCCESS); } -isc_result_t -isc_app_reload(void) { +ISC_APPFUNC_SCOPE isc_result_t +isc__app_shutdown() { + return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); +} + +ISC_APPFUNC_SCOPE isc_result_t +isc__app_ctxsuspend(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_boolean_t want_kill = ISC_TRUE; char strbuf[ISC_STRERRORSIZE]; - LOCK(&lock); + REQUIRE(VALID_APPCTX(ctx)); - REQUIRE(running); + LOCK(&ctx->lock); + + REQUIRE(ctx->running); /* * Don't send the reload signal if we're shutting down. */ - if (shutdown_requested) + if (ctx->shutdown_requested) want_kill = ISC_FALSE; - UNLOCK(&lock); + UNLOCK(&ctx->lock); if (want_kill) { + if (ctx != &isc_g_appctx) + ctx->want_reload = ISC_TRUE; + else { #ifdef HAVE_LINUXTHREADS - int result; + int result; - result = pthread_kill(main_thread, SIGHUP); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } + result = pthread_kill(main_thread, SIGHUP); + if (result != 0) { + isc__strerror(result, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_reload() " + "pthread_kill: %s", + strbuf); + return (ISC_R_UNEXPECTED); + } #else - if (kill(getpid(), SIGHUP) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } + if (kill(getpid(), SIGHUP) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_app_reload() " + "kill: %s", strbuf); + return (ISC_R_UNEXPECTED); + } #endif + } } return (ISC_R_SUCCESS); } -void -isc_app_finish(void) { - DESTROYLOCK(&lock); +ISC_APPFUNC_SCOPE isc_result_t +isc__app_reload(void) { + return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); } -void -isc_app_block(void) { +ISC_APPFUNC_SCOPE void +isc__app_ctxfinish(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + DESTROYLOCK(&ctx->lock); +} + +ISC_APPFUNC_SCOPE void +isc__app_finish(void) { + isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx); +} + +ISC_APPFUNC_SCOPE void +isc__app_block(void) { #ifdef ISC_PLATFORM_USETHREADS sigset_t sset; #endif /* ISC_PLATFORM_USETHREADS */ - REQUIRE(running); - REQUIRE(!blocked); + REQUIRE(isc_g_appctx.running); + REQUIRE(!isc_g_appctx.blocked); - blocked = ISC_TRUE; + isc_g_appctx.blocked = ISC_TRUE; #ifdef ISC_PLATFORM_USETHREADS blockedthread = pthread_self(); RUNTIME_CHECK(sigemptyset(&sset) == 0 && @@ -662,16 +858,16 @@ isc_app_block(void) { #endif /* ISC_PLATFORM_USETHREADS */ } -void -isc_app_unblock(void) { +ISC_APPFUNC_SCOPE void +isc__app_unblock(void) { #ifdef ISC_PLATFORM_USETHREADS sigset_t sset; #endif /* ISC_PLATFORM_USETHREADS */ - REQUIRE(running); - REQUIRE(blocked); + REQUIRE(isc_g_appctx.running); + REQUIRE(isc_g_appctx.blocked); - blocked = ISC_FALSE; + isc_g_appctx.blocked = ISC_FALSE; #ifdef ISC_PLATFORM_USETHREADS REQUIRE(blockedthread == pthread_self()); @@ -682,3 +878,77 @@ isc_app_unblock(void) { RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0); #endif /* ISC_PLATFORM_USETHREADS */ } + +ISC_APPFUNC_SCOPE isc_result_t +isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(mctx != NULL); + REQUIRE(ctxp != NULL && *ctxp == NULL); + + ctx = isc_mem_get(mctx, sizeof(*ctx)); + if (ctx == NULL) + return (ISC_R_NOMEMORY); + + ctx->common.impmagic = APPCTX_MAGIC; + ctx->common.magic = ISCAPI_APPCTX_MAGIC; + ctx->common.methods = &appmethods.methods; + + ctx->mctx = NULL; + isc_mem_attach(mctx, &ctx->mctx); + + ctx->taskmgr = NULL; + ctx->socketmgr = NULL; + ctx->timermgr = NULL; + + *ctxp = (isc_appctx_t *)ctx; + + return (ISC_R_SUCCESS); +} + +ISC_APPFUNC_SCOPE void +isc__appctx_destroy(isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(ctxp != NULL); + ctx = (isc__appctx_t *)*ctxp; + REQUIRE(VALID_APPCTX(ctx)); + + isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); + + *ctxp = NULL; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->taskmgr = taskmgr; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->socketmgr = socketmgr; +} + +ISC_APPFUNC_SCOPE void +isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->timermgr = timermgr; +} + +#ifdef USE_APPIMPREGISTER +isc_result_t +isc__app_register() { + return (isc_app_register(isc__appctx_create)); +} +#endif diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index df1002ab02..0edac59716 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.319 2009/08/13 02:11:20 marka Exp $ */ +/* $Id: socket.c,v 1.320 2009/09/01 00:22:28 jinmei Exp $ */ /*! \file */ @@ -72,9 +72,18 @@ #include "errno2result.h" -#ifndef ISC_PLATFORM_USETHREADS +/* See task.c about the following definition: */ +#ifdef BIND9 +#ifdef ISC_PLATFORM_USETHREADS +#define USE_WATCHER_THREAD +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* BIND9 */ + +#ifndef USE_WATCHER_THREAD #include "socket_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #if defined(SO_BSDCOMPAT) && defined(__linux__) #include @@ -97,7 +106,7 @@ typedef struct { #define USE_SELECT #endif /* ISC_PLATFORM_HAVEKQUEUE */ -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_WATCHER_THREAD #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) struct isc_socketwait { int nevents; @@ -110,7 +119,7 @@ struct isc_socketwait { int maxfd; }; #endif /* USE_KQUEUE */ -#endif /* !ISC_PLATFORM_USETHREADS */ +#endif /* !USE_WATCHER_THREAD */ /*% * Maximum number of allowable open sockets. This is also the maximum @@ -244,7 +253,7 @@ typedef enum { poll_idle, poll_active, poll_checking } pollstate_t; typedef isc_event_t intev_t; #define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') -#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC) +#define VALID_SOCKET(s) ISC_MAGIC_VALID(s, SOCKET_MAGIC) /*! * IPv6 control information. If the socket is an IPv6 socket we want @@ -278,16 +287,21 @@ typedef isc_event_t intev_t; */ #define NRETRIES 10 -struct isc_socket { +typedef struct isc__socket isc__socket_t; +typedef struct isc__socketmgr isc__socketmgr_t; + +#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket) + +struct isc__socket { /* Not locked. */ - unsigned int magic; - isc_socketmgr_t *manager; + isc_socket_t common; + isc__socketmgr_t *manager; isc_mutex_t lock; isc_sockettype_t type; const isc_statscounter_t *statsindex; /* Locked by socket lock. */ - ISC_LINK(isc_socket_t) link; + ISC_LINK(isc__socket_t) link; unsigned int references; int fd; int pf; @@ -335,9 +349,9 @@ struct isc_socket { #define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC) -struct isc_socketmgr { +struct isc__socketmgr { /* Not locked. */ - unsigned int magic; + isc_socketmgr_t common; isc_mem_t *mctx; isc_mutex_t lock; isc_mutex_t *fdlock; @@ -366,14 +380,14 @@ struct isc_socketmgr { #endif /* Locked by fdlock. */ - isc_socket_t **fds; + isc__socket_t **fds; int *fdstate; #ifdef USE_DEVPOLL pollinfo_t *fdpollinfo; #endif /* Locked by manager lock. */ - ISC_LIST(isc_socket_t) socklist; + ISC_LIST(isc__socket_t) socklist; #ifdef USE_SELECT fd_set *read_fds; fd_set *read_fds_copy; @@ -382,18 +396,18 @@ struct isc_socketmgr { int maxfd; #endif /* USE_SELECT */ int reserved; /* unlocked */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_thread_t watcher; isc_condition_t shutdown_ok; -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ unsigned int refs; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ int maxudp; }; -#ifndef ISC_PLATFORM_USETHREADS -static isc_socketmgr_t *socketmgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +#ifdef USE_SHARED_MANAGER +static isc__socketmgr_t *socketmgr = NULL; +#endif /* USE_SHARED_MANAGER */ #define CLOSED 0 /* this one must be zero */ #define MANAGED 1 @@ -409,27 +423,150 @@ static isc_socketmgr_t *socketmgr = NULL; # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) #endif -static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **); -static void send_senddone_event(isc_socket_t *, isc_socketevent_t **); -static void free_socket(isc_socket_t **); -static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t, - isc_socket_t **); -static void destroy(isc_socket_t **); +static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **); +static void send_senddone_event(isc__socket_t *, isc_socketevent_t **); +static void free_socket(isc__socket_t **); +static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t, + isc__socket_t **); +static void destroy(isc__socket_t **); static void internal_accept(isc_task_t *, isc_event_t *); static void internal_connect(isc_task_t *, isc_event_t *); static void internal_recv(isc_task_t *, isc_event_t *); static void internal_send(isc_task_t *, isc_event_t *); static void internal_fdwatch_write(isc_task_t *, isc_event_t *); static void internal_fdwatch_read(isc_task_t *, isc_event_t *); -static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *); -static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *, +static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *); +static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *, struct msghdr *, struct iovec *, size_t *); -static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *, +static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *, struct msghdr *, struct iovec *, size_t *); -#ifdef ISC_PLATFORM_USETHREADS -static isc_boolean_t process_ctlfd(isc_socketmgr_t *manager); +#ifdef USE_WATCHER_THREAD +static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager); #endif +/*% + * The following can be either static or public, depending on build environment. + */ + +#ifdef BIND9 +#define ISC_SOCKETFUNC_SCOPE +#else +#define ISC_SOCKETFUNC_SCOPE static +#endif + +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_detach(isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks); +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_destroy(isc_socketmgr_t **managerp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv2(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags); +ISC_SOCKETFUNC_SCOPE void +isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active); +ISC_SOCKETFUNC_SCOPE isc_boolean_t +isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, + isc_uint32_t owner, isc_uint32_t group); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_filter(isc_socket_t *sock, const char *filter); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_listen(isc_socket_t *sock, unsigned int backlog); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_accept(isc_socket_t *sock, + isc_task_t *task, isc_taskaction_t action, const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, + const void *arg); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp); +ISC_SOCKETFUNC_SCOPE void +isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); +ISC_SOCKETFUNC_SCOPE isc_sockettype_t +isc__socket_gettype(isc_socket_t *sock); +ISC_SOCKETFUNC_SCOPE isc_boolean_t +isc__socket_isbound(isc_socket_t *sock); +ISC_SOCKETFUNC_SCOPE void +isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes); +#if defined(HAVE_LIBXML2) && defined(BIND9) +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer); +#endif + +static struct { + isc_socketmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter, + *listen, *accept, *getpeername, *isbound; +} socketmethods = { + { + isc__socket_attach, + isc__socket_detach, + isc__socket_bind, + isc__socket_sendto, + isc__socket_connect, + isc__socket_recv, + isc__socket_cancel, + isc__socket_getsockname, + isc__socket_gettype, + isc__socket_ipv6only + }, + isc__socket_recvv, isc__socket_send, isc__socket_sendv, + isc__socket_sendto2, isc__socket_cleanunix, isc__socket_permunix, + isc__socket_filter, isc__socket_listen, isc__socket_accept, + isc__socket_getpeername, isc__socket_isbound +}; + +static isc_socketmgrmethods_t socketmgrmethods = { + isc__socketmgr_destroy, + isc__socket_create +}; + #define SELECT_POKE_SHUTDOWN (-1) #define SELECT_POKE_NOTHING (-2) #define SELECT_POKE_READ (-3) @@ -529,11 +666,11 @@ static const isc_statscounter_t fdwatchstatsindex[] = { }; static void -manager_log(isc_socketmgr_t *sockmgr, +manager_log(isc__socketmgr_t *sockmgr, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); static void -manager_log(isc_socketmgr_t *sockmgr, +manager_log(isc__socketmgr_t *sockmgr, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) { @@ -552,12 +689,12 @@ manager_log(isc_socketmgr_t *sockmgr, } static void -socket_log(isc_socket_t *sock, isc_sockaddr_t *address, +socket_log(isc__socket_t *sock, isc_sockaddr_t *address, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int message, const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10); static void -socket_log(isc_socket_t *sock, isc_sockaddr_t *address, +socket_log(isc__socket_t *sock, isc_sockaddr_t *address, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int message, const char *fmt, ...) @@ -592,7 +729,7 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address, * setting IPV6_V6ONLY. */ static void -FIX_IPV6_RECVPKTINFO(isc_socket_t *sock) +FIX_IPV6_RECVPKTINFO(isc__socket_t *sock) { char strbuf[ISC_STRERRORSIZE]; int on = 1; @@ -629,7 +766,7 @@ inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) { } static inline isc_result_t -watch_fd(isc_socketmgr_t *manager, int fd, int msg) { +watch_fd(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result = ISC_R_SUCCESS; #ifdef USE_KQUEUE @@ -696,7 +833,7 @@ watch_fd(isc_socketmgr_t *manager, int fd, int msg) { } static inline isc_result_t -unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) { +unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result = ISC_R_SUCCESS; #ifdef USE_KQUEUE @@ -782,7 +919,7 @@ unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) { } static void -wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { +wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) { isc_result_t result; int lockid = FDLOCK_ID(fd); @@ -843,14 +980,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Poke the select loop when there is something for us to do. * The write is required (by POSIX) to complete. That is, we * will not get partial writes. */ static void -select_poke(isc_socketmgr_t *mgr, int fd, int msg) { +select_poke(isc__socketmgr_t *mgr, int fd, int msg) { int cc; int buf[2]; char strbuf[ISC_STRERRORSIZE]; @@ -889,7 +1026,7 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) { * Read a message on the internal fd. */ static void -select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { +select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) { int buf[2]; int cc; char strbuf[ISC_STRERRORSIZE]; @@ -916,19 +1053,19 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { *fd = buf[0]; *msg = buf[1]; } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ /* * Update the state of the socketmgr when something changes. */ static void -select_poke(isc_socketmgr_t *manager, int fd, int msg) { +select_poke(isc__socketmgr_t *manager, int fd, int msg) { if (msg == SELECT_POKE_SHUTDOWN) return; else if (fd >= 0) wakeup_socket(manager, fd, msg); return; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ /* * Make a fd non-blocking. @@ -1021,7 +1158,7 @@ cmsg_space(ISC_SOCKADDR_LEN_T len) { * Process control messages received on a socket. */ static void -process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { +process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { #ifdef USE_CMSG struct cmsghdr *cmsgp; #ifdef ISC_PLATFORM_HAVEIN6PKTINFO @@ -1124,7 +1261,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { * this transaction can send. */ static void -build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, +build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, struct iovec *iov, size_t *write_countp) { unsigned int iovcount; @@ -1243,7 +1380,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, * this transaction can receive. */ static void -build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, +build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, struct iovec *iov, size_t *read_countp) { unsigned int iovcount; @@ -1364,7 +1501,7 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, } static void -set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, +set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock, isc_socketevent_t *dev) { if (sock->type == isc_sockettype_udp) { @@ -1388,7 +1525,7 @@ destroy_socketevent(isc_event_t *event) { } static isc_socketevent_t * -allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype, +allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype, isc_taskaction_t action, const void *arg) { isc_socketevent_t *ev; @@ -1441,7 +1578,7 @@ dump_msg(struct msghdr *msg) { #define DOIO_EOF 3 /* EOF, no event sent */ static int -doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { +doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { int cc; struct iovec iov[MAXSCATTERGATHER_RECV]; size_t read_count; @@ -1621,7 +1758,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { * No other return values are possible. */ static int -doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { +doio_send(isc__socket_t *sock, isc_socketevent_t *dev) { int cc; struct iovec iov[MAXSCATTERGATHER_SEND]; size_t write_count; @@ -1732,7 +1869,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { * references exist. */ static void -closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) { +closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) { isc_sockettype_t type = sock->type; int lockid = FDLOCK_ID(fd); @@ -1795,10 +1932,10 @@ closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) { } static void -destroy(isc_socket_t **sockp) { +destroy(isc__socket_t **sockp) { int fd; - isc_socket_t *sock = *sockp; - isc_socketmgr_t *manager = sock->manager; + isc__socket_t *sock = *sockp; + isc__socketmgr_t *manager = sock->manager; socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_DESTROYING, "destroying"); @@ -1819,10 +1956,10 @@ destroy(isc_socket_t **sockp) { ISC_LIST_UNLINK(manager->socklist, sock, link); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (ISC_LIST_EMPTY(manager->socklist)) SIGNAL(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ UNLOCK(&manager->lock); @@ -1830,10 +1967,10 @@ destroy(isc_socket_t **sockp) { } static isc_result_t -allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, - isc_socket_t **socketp) +allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, + isc__socket_t **socketp) { - isc_socket_t *sock; + isc__socket_t *sock; isc_result_t result; ISC_SOCKADDR_LEN_T cmsgbuflen; @@ -1844,7 +1981,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, result = ISC_R_UNEXPECTED; - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; sock->references = 0; sock->manager = manager; @@ -1908,7 +2046,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, */ result = isc_mutex_init(&sock->lock); if (result != ISC_R_SUCCESS) { - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; goto error; } @@ -1922,7 +2061,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW, NULL, sock, sock, NULL, NULL); - sock->magic = SOCKET_MAGIC; + sock->common.magic = ISCAPI_SOCKET_MAGIC; + sock->common.impmagic = SOCKET_MAGIC; *socketp = sock; return (ISC_R_SUCCESS); @@ -1947,8 +2087,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, * also close the socket. */ static void -free_socket(isc_socket_t **socketp) { - isc_socket_t *sock = *socketp; +free_socket(isc__socket_t **socketp) { + isc__socket_t *sock = *socketp; INSIST(sock->references == 0); INSIST(VALID_SOCKET(sock)); @@ -1968,7 +2108,8 @@ free_socket(isc_socket_t **socketp) { isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf, sock->sendcmsgbuflen); - sock->magic = 0; + sock->common.magic = 0; + sock->common.impmagic = 0; DESTROYLOCK(&sock->lock); @@ -2016,7 +2157,7 @@ clear_bsdcompat(void) { #endif static isc_result_t -opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) { +opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { char strbuf[ISC_STRERRORSIZE]; const char *err = "socket"; int tries = 0; @@ -2287,11 +2428,12 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) { * called with 'arg' as the arg value. The new socket is returned * in 'socketp'. */ -isc_result_t -isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, + isc_socket_t **socketp) { - isc_socket_t *sock = NULL; + isc__socket_t *sock = NULL; + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; isc_result_t result; int lockid; @@ -2327,8 +2469,9 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (result); } + sock->common.methods = (isc_socketmethods_t *)&socketmethods; sock->references = 1; - *socketp = sock; + *socketp = (isc_socket_t *)sock; /* * Note we don't have to lock the socket like we normally would because @@ -2359,9 +2502,11 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (ISC_R_SUCCESS); } -isc_result_t -isc_socket_open(isc_socket_t *sock) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_open(isc_socket_t *sock0) { isc_result_t result; + isc__socket_t *sock = (isc__socket_t *)sock0; REQUIRE(VALID_SOCKET(sock)); @@ -2408,12 +2553,13 @@ isc_socket_open(isc_socket_t *sock) { * called with 'arg' as the arg value. The new socket is returned * in 'socketp'. */ -isc_result_t -isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, - isc_sockfdwatch_t callback, void *cbarg, - isc_task_t *task, isc_socket_t **socketp) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags, + isc_sockfdwatch_t callback, void *cbarg, + isc_task_t *task, isc_socket_t **socketp) { - isc_socket_t *sock = NULL; + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + isc__socket_t *sock = NULL; isc_result_t result; int lockid; @@ -2431,8 +2577,9 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, sock->fdwatchtask = task; sock->statsindex = fdwatchstatsindex; + sock->common.methods = (isc_socketmethods_t *)&socketmethods; sock->references = 1; - *socketp = sock; + *socketp = (isc_socket_t *)sock; /* * Note we don't have to lock the socket like we normally would because @@ -2463,12 +2610,15 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, return (ISC_R_SUCCESS); } +#endif /* BIND9 */ /* * Attach to a socket. Caller must explicitly detach when it is done. */ -void -isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) { + isc__socket_t *sock = (isc__socket_t *)sock0; + REQUIRE(VALID_SOCKET(sock)); REQUIRE(socketp != NULL && *socketp == NULL); @@ -2476,20 +2626,20 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { sock->references++; UNLOCK(&sock->lock); - *socketp = sock; + *socketp = (isc_socket_t *)sock; } /* * Dereference a socket. If this is the last reference to it, clean things * up by destroying the socket. */ -void -isc_socket_detach(isc_socket_t **socketp) { - isc_socket_t *sock; +ISC_SOCKETFUNC_SCOPE void +isc__socket_detach(isc_socket_t **socketp) { + isc__socket_t *sock; isc_boolean_t kill_socket = ISC_FALSE; REQUIRE(socketp != NULL); - sock = *socketp; + sock = (isc__socket_t *)*socketp; REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -2505,10 +2655,12 @@ isc_socket_detach(isc_socket_t **socketp) { *socketp = NULL; } -isc_result_t -isc_socket_close(isc_socket_t *sock) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_close(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; int fd; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); @@ -2546,6 +2698,7 @@ isc_socket_close(isc_socket_t *sock) { return (ISC_R_SUCCESS); } +#endif /* BIND9 */ /* * I/O is possible on a given socket. Schedule an event to this task that @@ -2556,7 +2709,7 @@ isc_socket_close(isc_socket_t *sock) { * The socket and manager must be locked before calling this function. */ static void -dispatch_recv(isc_socket_t *sock) { +dispatch_recv(isc__socket_t *sock) { intev_t *iev; isc_socketevent_t *ev; isc_task_t *sender; @@ -2590,7 +2743,7 @@ dispatch_recv(isc_socket_t *sock) { } static void -dispatch_send(isc_socket_t *sock) { +dispatch_send(isc__socket_t *sock) { intev_t *iev; isc_socketevent_t *ev; isc_task_t *sender; @@ -2627,7 +2780,7 @@ dispatch_send(isc_socket_t *sock) { * Dispatch an internal accept event. */ static void -dispatch_accept(isc_socket_t *sock) { +dispatch_accept(isc__socket_t *sock) { intev_t *iev; isc_socket_newconnev_t *ev; @@ -2653,7 +2806,7 @@ dispatch_accept(isc_socket_t *sock) { } static void -dispatch_connect(isc_socket_t *sock) { +dispatch_connect(isc__socket_t *sock) { intev_t *iev; isc_socket_connev_t *ev; @@ -2683,7 +2836,7 @@ dispatch_connect(isc_socket_t *sock) { * Caller must have the socket locked if the event is attached to the socket. */ static void -send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { +send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) { isc_task_t *task; task = (*dev)->ev_sender; @@ -2706,7 +2859,7 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { * Caller must have the socket locked if the event is attached to the socket. */ static void -send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { +send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) { isc_task_t *task; INSIST(dev != NULL && *dev != NULL); @@ -2737,8 +2890,8 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { */ static void internal_accept(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; - isc_socketmgr_t *manager; + isc__socket_t *sock; + isc__socketmgr_t *manager; isc_socket_newconnev_t *dev; isc_task_t *task; ISC_SOCKADDR_LEN_T addrlen; @@ -2793,9 +2946,9 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { * daemons such as BIND 8 and Apache. */ - addrlen = sizeof(dev->newsocket->peer_address.type); - memset(&dev->newsocket->peer_address.type, 0, addrlen); - fd = accept(sock->fd, &dev->newsocket->peer_address.type.sa, + addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type); + memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen); + fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa, (void *)&addrlen); #ifdef F_DUPFD @@ -2865,14 +3018,14 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { (void)close(fd); goto soft_error; - } else if (dev->newsocket->peer_address.type.sa.sa_family != + } else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family != sock->pf) { UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_accept(): " "accept() returned peer address " "family %u (expected %u)", - dev->newsocket->peer_address. + NEWCONNSOCK(dev)->peer_address. type.sa.sa_family, sock->pf); (void)close(fd); @@ -2891,8 +3044,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { } if (fd != -1) { - dev->newsocket->peer_address.length = addrlen; - dev->newsocket->pf = sock->pf; + NEWCONNSOCK(dev)->peer_address.length = addrlen; + NEWCONNSOCK(dev)->pf = sock->pf; } /* @@ -2921,28 +3074,28 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { int lockid = FDLOCK_ID(fd); LOCK(&manager->fdlock[lockid]); - manager->fds[fd] = dev->newsocket; + manager->fds[fd] = NEWCONNSOCK(dev); manager->fdstate[fd] = MANAGED; UNLOCK(&manager->fdlock[lockid]); LOCK(&manager->lock); - ISC_LIST_APPEND(manager->socklist, dev->newsocket, link); + ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link); - dev->newsocket->fd = fd; - dev->newsocket->bound = 1; - dev->newsocket->connected = 1; + NEWCONNSOCK(dev)->fd = fd; + NEWCONNSOCK(dev)->bound = 1; + NEWCONNSOCK(dev)->connected = 1; /* * Save away the remote address */ - dev->address = dev->newsocket->peer_address; + dev->address = NEWCONNSOCK(dev)->peer_address; #ifdef USE_SELECT if (manager->maxfd < fd) manager->maxfd = fd; #endif - socket_log(sock, &dev->newsocket->peer_address, CREATION, + socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, "accepted connection, new socket %p", dev->newsocket); @@ -2952,8 +3105,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]); } else { inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]); - dev->newsocket->references--; - free_socket(&dev->newsocket); + NEWCONNSOCK(dev)->references--; + free_socket((isc__socket_t **)&dev->newsocket); } /* @@ -2977,7 +3130,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { static void internal_recv(isc_task_t *me, isc_event_t *ev) { isc_socketevent_t *dev; - isc_socket_t *sock; + isc__socket_t *sock; INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); @@ -3042,14 +3195,14 @@ internal_recv(isc_task_t *me, isc_event_t *ev) { static void internal_send(isc_task_t *me, isc_event_t *ev) { isc_socketevent_t *dev; - isc_socket_t *sock; + isc__socket_t *sock; INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3096,7 +3249,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) { static void internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; int more_data; INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); @@ -3104,7 +3257,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3115,7 +3268,8 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { INSIST(sock->pending_send == 1); UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg); + more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, + sock->fdwatcharg); LOCK(&sock->lock); sock->pending_send = 0; @@ -3136,7 +3290,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { static void internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; int more_data; INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); @@ -3144,7 +3298,7 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; + sock = (isc__socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -3155,7 +3309,8 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { INSIST(sock->pending_recv == 1); UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg); + more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, + sock->fdwatcharg); LOCK(&sock->lock); sock->pending_recv = 0; @@ -3179,10 +3334,10 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { * and unlocking twice if both reads and writes are possible. */ static void -process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable, +process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable, isc_boolean_t writeable) { - isc_socket_t *sock; + isc__socket_t *sock; isc_boolean_t unlock_sock; isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE; int lockid = FDLOCK_ID(fd); @@ -3248,11 +3403,11 @@ check_write: #ifdef USE_KQUEUE static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) { int i; isc_boolean_t readable, writable; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3270,7 +3425,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].ident < manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3281,7 +3436,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { process_fd(manager, events[i].ident, readable, writable); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3290,10 +3445,11 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) { } #elif defined(USE_EPOLL) static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents) +{ int i; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3306,7 +3462,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].data.fd < (int)manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].data.fd == manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3328,7 +3484,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { (events[i].events & EPOLLOUT) != 0); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3337,10 +3493,10 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) { } #elif defined(USE_DEVPOLL) static isc_boolean_t -process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { +process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) { int i; isc_boolean_t done = ISC_FALSE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD isc_boolean_t have_ctlevent = ISC_FALSE; #endif @@ -3353,7 +3509,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { for (i = 0; i < nevents; i++) { REQUIRE(events[i].fd < (int)manager->maxsocks); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (events[i].fd == manager->pipe_fds[0]) { have_ctlevent = ISC_TRUE; continue; @@ -3364,7 +3520,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { (events[i].events & POLLOUT) != 0); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (have_ctlevent) done = process_ctlfd(manager); #endif @@ -3373,27 +3529,27 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) { } #elif defined(USE_SELECT) static void -process_fds(isc_socketmgr_t *manager, int maxfd, - fd_set *readfds, fd_set *writefds) +process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds, + fd_set *writefds) { int i; REQUIRE(maxfd <= (int)manager->maxsocks); for (i = 0; i < maxfd; i++) { -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1]) continue; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ process_fd(manager, i, FD_ISSET(i, readfds), FD_ISSET(i, writefds)); } } #endif -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD static isc_boolean_t -process_ctlfd(isc_socketmgr_t *manager) { +process_ctlfd(isc__socketmgr_t *manager) { int msg, fd; for (;;) { @@ -3441,7 +3597,7 @@ process_ctlfd(isc_socketmgr_t *manager) { */ static isc_threadresult_t watcher(void *uap) { - isc_socketmgr_t *manager = uap; + isc__socketmgr_t *manager = uap; isc_boolean_t done; int ctlfd; int cc; @@ -3556,29 +3712,34 @@ watcher(void *uap) { return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ -void -isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) { +#ifdef BIND9 +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; REQUIRE(VALID_MANAGER(manager)); manager->reserved = reserved; } -void -isc__socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) { +ISC_SOCKETFUNC_SCOPE void +isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); manager->maxudp = maxudp; } +#endif /* BIND9 */ /* * Create a new socket manager. */ static isc_result_t -setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { +setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { isc_result_t result; #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) char strbuf[ISC_STRERRORSIZE]; @@ -3604,7 +3765,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->kqueue_fd); @@ -3612,7 +3773,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct kevent) * manager->nevents); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_EPOLL) manager->nevents = ISC_SOCKET_MAXEVENTS; manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) * @@ -3632,7 +3793,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct epoll_event) * manager->nevents); return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->epoll_fd); @@ -3640,7 +3801,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(struct epoll_event) * manager->nevents); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_DEVPOLL) /* * XXXJT: /dev/poll seems to reject large numbers of events, @@ -3678,7 +3839,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(pollinfo_t) * manager->maxsocks); return (result); } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); if (result != ISC_R_SUCCESS) { close(manager->devpoll_fd); @@ -3688,7 +3849,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { sizeof(pollinfo_t) * manager->maxsocks); return (result); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #elif defined(USE_SELECT) UNUSED(result); @@ -3736,20 +3897,20 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { memset(manager->read_fds, 0, manager->fd_bufsize); memset(manager->write_fds, 0, manager->fd_bufsize); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); manager->maxfd = manager->pipe_fds[0]; -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ manager->maxfd = 0; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #endif /* USE_KQUEUE */ return (ISC_R_SUCCESS); } static void -cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { -#ifdef ISC_PLATFORM_USETHREADS +cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { +#ifdef USE_WATCHER_THREAD isc_result_t result; result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); @@ -3759,7 +3920,7 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ #ifdef USE_KQUEUE close(manager->kqueue_fd); @@ -3787,35 +3948,35 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) { #endif /* USE_KQUEUE */ } -isc_result_t -isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { - return (isc_socketmgr_create2(mctx, managerp, 0)); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { + return (isc__socketmgr_create2(mctx, managerp, 0)); } -isc_result_t -isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, - unsigned int maxsocks) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks) { int i; - isc_socketmgr_t *manager; -#ifdef ISC_PLATFORM_USETHREADS + isc__socketmgr_t *manager; +#ifdef USE_WATCHER_THREAD char strbuf[ISC_STRERRORSIZE]; #endif isc_result_t result; REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (socketmgr != NULL) { /* Don't allow maxsocks to be updated */ if (maxsocks > 0 && socketmgr->maxsocks != maxsocks) return (ISC_R_EXISTS); socketmgr->refs++; - *managerp = socketmgr; + *managerp = (isc_socketmgr_t *)socketmgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ if (maxsocks == 0) maxsocks = ISC_SOCKET_MAXSOCKETS; @@ -3830,7 +3991,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, manager->reserved = 0; manager->maxudp = 0; manager->fds = isc_mem_get(mctx, - manager->maxsocks * sizeof(isc_socket_t *)); + manager->maxsocks * sizeof(isc__socket_t *)); if (manager->fds == NULL) { result = ISC_R_NOMEMORY; goto free_manager; @@ -3842,7 +4003,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, } manager->stats = NULL; - manager->magic = SOCKET_MANAGER_MAGIC; + manager->common.methods = &socketmgrmethods; + manager->common.magic = ISCAPI_SOCKETMGR_MAGIC; + manager->common.impmagic = SOCKET_MANAGER_MAGIC; manager->mctx = NULL; memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *)); ISC_LIST_INIT(manager->socklist); @@ -3866,7 +4029,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", @@ -3895,9 +4058,11 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, #if 0 RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS); #endif -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ + +#ifdef USE_SHARED_MANAGER manager->refs = 1; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ /* * Set up initial state for the select loop @@ -3906,7 +4071,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, if (result != ISC_R_SUCCESS) goto cleanup; memset(manager->fdstate, 0, manager->maxsocks * sizeof(int)); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Start up the select/poll thread. */ @@ -3920,26 +4085,26 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, result = ISC_R_UNEXPECTED; goto cleanup; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ isc_mem_attach(mctx, &manager->mctx); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER socketmgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ - *managerp = manager; +#endif /* USE_SHARED_MANAGER */ + *managerp = (isc_socketmgr_t *)manager; return (ISC_R_SUCCESS); cleanup: -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)close(manager->pipe_fds[0]); (void)close(manager->pipe_fds[1]); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD cleanup_condition: (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ cleanup_lock: @@ -3967,8 +4132,10 @@ free_manager: return (result); } +#ifdef BIND9 isc_result_t -isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { +isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; REQUIRE(VALID_MANAGER(manager)); REQUIRE(nsockp != NULL); @@ -3978,7 +4145,9 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { } void -isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { +isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); REQUIRE(ISC_LIST_EMPTY(manager->socklist)); REQUIRE(manager->stats == NULL); @@ -3986,10 +4155,11 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { isc_stats_attach(stats, &manager->stats); } +#endif -void -isc_socketmgr_destroy(isc_socketmgr_t **managerp) { - isc_socketmgr_t *manager; +ISC_SOCKETFUNC_SCOPE void +isc__socketmgr_destroy(isc_socketmgr_t **managerp) { + isc__socketmgr_t *manager; int i; isc_mem_t *mctx; @@ -3998,20 +4168,20 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__socketmgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (manager->refs > 1) { manager->refs--; *managerp = NULL; return; } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ LOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Wait for all sockets to be destroyed. */ @@ -4022,7 +4192,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { "sockets exist")); WAIT(&manager->shutdown_ok, &manager->lock); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_WATCHER_THREAD */ /* * Hope all sockets have been destroyed. */ @@ -4033,7 +4203,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { "sockets exist")); INSIST(0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ UNLOCK(&manager->lock); @@ -4044,7 +4214,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { */ select_poke(manager, 0, SELECT_POKE_SHUTDOWN); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD /* * Wait for thread to exit. */ @@ -4053,25 +4223,25 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ /* * Clean up. */ cleanup_watcher(manager->mctx, manager); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_WATCHER_THREAD (void)close(manager->pipe_fds[0]); (void)close(manager->pipe_fds[1]); (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ for (i = 0; i < (int)manager->maxsocks; i++) if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */ (void)close(i); isc_mem_put(manager->mctx, manager->fds, - manager->maxsocks * sizeof(isc_socket_t *)); + manager->maxsocks * sizeof(isc__socket_t *)); isc_mem_put(manager->mctx, manager->fdstate, manager->maxsocks * sizeof(int)); @@ -4085,17 +4255,22 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { FDLOCK_COUNT * sizeof(isc_mutex_t)); } DESTROYLOCK(&manager->lock); - manager->magic = 0; + manager->common.magic = 0; + manager->common.impmagic = 0; mctx= manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; + +#ifdef USE_SHARED_MANAGER + socketmgr = NULL; +#endif } static isc_result_t -socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, +socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, unsigned int flags) { int io_state; @@ -4166,13 +4341,14 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, return (result); } -isc_result_t -isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; unsigned int iocount; isc_buffer_t *buffer; @@ -4220,12 +4396,14 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, return (socket_recv(sock, dev, task, 0)); } -isc_result_t -isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv(isc_socket_t *sock0, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; REQUIRE(VALID_SOCKET(sock)); REQUIRE(action != NULL); @@ -4239,14 +4417,16 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, if (dev == NULL) return (ISC_R_NOMEMORY); - return (isc_socket_recv2(sock, region, minimum, task, dev, 0)); + return (isc__socket_recv2(sock0, region, minimum, task, dev, 0)); } -isc_result_t -isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_socketevent_t *event, unsigned int flags) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags) { + isc__socket_t *sock = (isc__socket_t *)sock0; + event->ev_sender = sock; event->result = ISC_R_UNEXPECTED; ISC_LIST_INIT(event->bufferlist); @@ -4271,7 +4451,7 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, } static isc_result_t -socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, +socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, unsigned int flags) { @@ -4362,24 +4542,25 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, return (result); } -isc_result_t -isc_socket_send(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg) { /* * REQUIRE() checking is performed in isc_socket_sendto(). */ - return (isc_socket_sendto(sock, region, task, action, arg, NULL, - NULL)); + return (isc__socket_sendto(sock, region, task, action, arg, NULL, + NULL)); } -isc_result_t -isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; REQUIRE(VALID_SOCKET(sock)); REQUIRE(region != NULL); @@ -4401,21 +4582,22 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, return (socket_send(sock, dev, task, address, pktinfo, 0)); } -isc_result_t -isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg) { - return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL, - NULL)); + return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL, + NULL)); } -isc_result_t -isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socketevent_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; unsigned int iocount; isc_buffer_t *buffer; @@ -4449,12 +4631,15 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, return (socket_send(sock, dev, task, address, pktinfo, 0)); } -isc_result_t -isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - isc_socketevent_t *event, unsigned int flags) +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags) { + isc__socket_t *sock = (isc__socket_t *)sock0; + + REQUIRE(VALID_SOCKET(sock)); REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0); if ((flags & ISC_SOCKFLAG_NORETRY) != 0) REQUIRE(sock->type == isc_sockettype_udp); @@ -4469,8 +4654,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, return (socket_send(sock, event, task, address, pktinfo, flags)); } -void -isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { #ifdef ISC_PLATFORM_HAVESYSUNH int s; struct stat sb; @@ -4599,8 +4784,8 @@ isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { #endif } -isc_result_t -isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, isc_uint32_t owner, isc_uint32_t group) { #ifdef ISC_PLATFORM_HAVESYSUNH @@ -4653,12 +4838,15 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, #endif } -isc_result_t -isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, - unsigned int options) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr, + unsigned int options) { + isc__socket_t *sock = (isc__socket_t *)sock0; char strbuf[ISC_STRERRORSIZE]; int on = 1; + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); INSIST(!sock->bound); @@ -4717,8 +4905,9 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, return (ISC_R_SUCCESS); } -isc_result_t -isc_socket_filter(isc_socket_t *sock, const char *filter) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_filter(isc_socket_t *sock0, const char *filter) { + isc__socket_t *sock = (isc__socket_t *)sock0; #ifdef SO_ACCEPTFILTER char strbuf[ISC_STRERRORSIZE]; struct accept_filter_arg afa; @@ -4756,8 +4945,9 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) { * is a new connection we'll have to allocate a new one anyway, so we might * as well keep things simple rather than having to track them. */ -isc_result_t -isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) { + isc__socket_t *sock = (isc__socket_t *)sock0; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); @@ -4790,14 +4980,15 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { /* * This should try to do aggressive accept() XXXMLG */ -isc_result_t -isc_socket_accept(isc_socket_t *sock, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_accept(isc_socket_t *sock0, isc_task_t *task, isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socket_newconnev_t *dev; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; isc_task_t *ntask = NULL; - isc_socket_t *nsock; + isc__socket_t *nsock; isc_result_t result; isc_boolean_t do_poke = ISC_FALSE; @@ -4838,7 +5029,7 @@ isc_socket_accept(isc_socket_t *sock, nsock->statsindex = sock->statsindex; dev->ev_sender = ntask; - dev->newsocket = nsock; + dev->newsocket = (isc_socket_t *)nsock; /* * Poke watcher here. We still have the socket locked, so there @@ -4857,13 +5048,14 @@ isc_socket_accept(isc_socket_t *sock, return (ISC_R_SUCCESS); } -isc_result_t -isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr, isc_task_t *task, isc_taskaction_t action, const void *arg) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_socket_connev_t *dev; isc_task_t *ntask = NULL; - isc_socketmgr_t *manager; + isc__socketmgr_t *manager; int cc; char strbuf[ISC_STRERRORSIZE]; @@ -5000,7 +5192,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, */ static void internal_connect(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; + isc__socket_t *sock; isc_socket_connev_t *dev; isc_task_t *task; int cc; @@ -5114,8 +5306,9 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev)); } -isc_result_t -isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_result_t result; REQUIRE(VALID_SOCKET(sock)); @@ -5129,14 +5322,15 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { } else { result = ISC_R_NOTCONNECTED; } - + UNLOCK(&sock->lock); return (result); } -isc_result_t -isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) { + isc__socket_t *sock = (isc__socket_t *)sock0; ISC_SOCKADDR_LEN_T len; isc_result_t result; char strbuf[ISC_STRERRORSIZE]; @@ -5173,8 +5367,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { * Run through the list of events on this socket, and cancel the ones * queued for task "task" of type "how". "how" is a bitmask. */ -void -isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) { + isc__socket_t *sock = (isc__socket_t *)sock0; REQUIRE(VALID_SOCKET(sock)); @@ -5253,8 +5448,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { ISC_LIST_UNLINK(sock->accept_list, dev, ev_link); - dev->newsocket->references--; - free_socket(&dev->newsocket); + NEWCONNSOCK(dev)->references--; + free_socket((isc__socket_t **)&dev->newsocket); dev->result = ISC_R_CANCELED; dev->ev_sender = sock; @@ -5293,17 +5488,22 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { UNLOCK(&sock->lock); } -isc_sockettype_t -isc_socket_gettype(isc_socket_t *sock) { +ISC_SOCKETFUNC_SCOPE isc_sockettype_t +isc__socket_gettype(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; + REQUIRE(VALID_SOCKET(sock)); return (sock->type); } -isc_boolean_t -isc_socket_isbound(isc_socket_t *sock) { +ISC_SOCKETFUNC_SCOPE isc_boolean_t +isc__socket_isbound(isc_socket_t *sock0) { + isc__socket_t *sock = (isc__socket_t *)sock0; isc_boolean_t val; + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); val = ((sock->bound) ? ISC_TRUE : ISC_FALSE); UNLOCK(&sock->lock); @@ -5311,8 +5511,9 @@ isc_socket_isbound(isc_socket_t *sock) { return (val); } -void -isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { +ISC_SOCKETFUNC_SCOPE void +isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) { + isc__socket_t *sock = (isc__socket_t *)sock0; #if defined(IPV6_V6ONLY) int onoff = yes ? 1 : 0; #else @@ -5342,12 +5543,21 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { #endif } -#ifndef ISC_PLATFORM_USETHREADS -/* In our assumed scenario, we can simply use a single static object. */ +#ifndef USE_WATCHER_THREAD +/* + * In our assumed scenario, we can simply use a single static object. + * XXX: this is not true if the application uses multiple threads with + * 'multi-context' mode. Fixing this is a future TODO item. + */ static isc_socketwait_t swait_private; int -isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { +isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp, + isc_socketwait_t **swaitp) +{ + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + + int n; #ifdef USE_KQUEUE struct timespec ts, *tsp; @@ -5361,7 +5571,11 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { REQUIRE(swaitp != NULL && *swaitp == NULL); - if (socketmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = socketmgr; +#endif + if (manager == NULL) return (0); #ifdef USE_KQUEUE @@ -5371,8 +5585,8 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { tsp = &ts; } else tsp = NULL; - swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0, - socketmgr->events, socketmgr->nevents, + swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0, + manager->events, manager->nevents, tsp); n = swait_private.nevents; #elif defined(USE_EPOLL) @@ -5380,29 +5594,28 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000; else timeout = -1; - swait_private.nevents = epoll_wait(socketmgr->epoll_fd, - socketmgr->events, - socketmgr->nevents, timeout); + swait_private.nevents = epoll_wait(manager->epoll_fd, + manager->events, + manager->nevents, timeout); n = swait_private.nevents; #elif defined(USE_DEVPOLL) - dvp.dp_fds = socketmgr->events; - dvp.dp_nfds = socketmgr->nevents; + dvp.dp_fds = manager->events; + dvp.dp_nfds = manager->nevents; if (tvp != NULL) { dvp.dp_timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000; } else dvp.dp_timeout = -1; - swait_private.nevents = ioctl(socketmgr->devpoll_fd, DP_POLL, &dvp); + swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp); n = swait_private.nevents; #elif defined(USE_SELECT) - memcpy(socketmgr->read_fds_copy, socketmgr->read_fds, - socketmgr->fd_bufsize); - memcpy(socketmgr->write_fds_copy, socketmgr->write_fds, - socketmgr->fd_bufsize); + memcpy(manager->read_fds_copy, manager->read_fds, manager->fd_bufsize); + memcpy(manager->write_fds_copy, manager->write_fds, + manager->fd_bufsize); - swait_private.readset = socketmgr->read_fds_copy; - swait_private.writeset = socketmgr->write_fds_copy; - swait_private.maxfd = socketmgr->maxfd + 1; + swait_private.readset = manager->read_fds_copy; + swait_private.writeset = manager->write_fds_copy; + swait_private.maxfd = manager->maxfd + 1; n = select(swait_private.maxfd, swait_private.readset, swait_private.writeset, NULL, tvp); @@ -5413,24 +5626,32 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) { } isc_result_t -isc__socketmgr_dispatch(isc_socketwait_t *swait) { +isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) { + isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; + REQUIRE(swait == &swait_private); - if (socketmgr == NULL) +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = socketmgr; +#endif + if (manager == NULL) return (ISC_R_NOTFOUND); #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) - (void)process_fds(socketmgr, socketmgr->events, swait->nevents); + (void)process_fds(manager, manager->events, swait->nevents); return (ISC_R_SUCCESS); #elif defined(USE_SELECT) - process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset); + process_fds(manager, swait->maxfd, swait->readset, swait->writeset); return (ISC_R_SUCCESS); #endif } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_WATCHER_THREAD */ +#ifdef BIND9 void -isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { +isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) { + isc__socket_t *socket = (isc__socket_t *)socket0; /* * Name 'socket'. @@ -5445,17 +5666,29 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { UNLOCK(&socket->lock); } -const char * -isc_socket_getname(isc_socket_t *socket) { +ISC_SOCKETFUNC_SCOPE const char * +isc__socket_getname(isc_socket_t *socket0) { + isc__socket_t *socket = (isc__socket_t *)socket0; + return (socket->name); } void * -isc_socket_gettag(isc_socket_t *socket) { +isc__socket_gettag(isc_socket_t *socket0) { + isc__socket_t *socket = (isc__socket_t *)socket0; + return (socket->tag); } +#endif /* BIND9 */ -#ifdef HAVE_LIBXML2 +#ifdef USE_SOCKETIMPREGISTER +isc_result_t +isc__socket_register() { + return (isc_socket_register(isc__socketmgr_create)); +} +#endif + +#if defined(HAVE_LIBXML2) && defined(BIND9) static const char * _socktype(isc_sockettype_t type) @@ -5472,21 +5705,21 @@ _socktype(isc_sockettype_t type) return ("not-initialized"); } -void -isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer) -{ - isc_socket_t *sock; +ISC_SOCKETFUNC_SCOPE void +isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) { + isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0; + isc__socket_t *sock; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t addr; ISC_SOCKADDR_LEN_T len; LOCK(&mgr->lock); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"); xmlTextWriterWriteFormatString(writer, "%d", mgr->refs); xmlTextWriterEndElement(writer); -#endif +#endif /* USE_SHARED_MANAGER */ xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets"); sock = ISC_LIST_HEAD(mgr->socklist); diff --git a/lib/isc/unix/socket_p.h b/lib/isc/unix/socket_p.h index fc044e58b2..e4a19baaaf 100644 --- a/lib/isc/unix/socket_p.h +++ b/lib/isc/unix/socket_p.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket_p.h,v 1.13 2008/06/23 23:47:11 tbox Exp $ */ +/* $Id: socket_p.h,v 1.14 2009/09/01 00:22:28 jinmei Exp $ */ #ifndef ISC_SOCKET_P_H #define ISC_SOCKET_P_H @@ -27,6 +27,7 @@ #endif typedef struct isc_socketwait isc_socketwait_t; -int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **); -isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *); +int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *, + isc_socketwait_t **); +isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *); #endif /* ISC_SOCKET_P_H */ diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in index 5c71dffb60..280b04e4f0 100644 --- a/lib/isc/win32/Makefile.in +++ b/lib/isc/win32/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.11 2007/06/19 23:47:19 tbox Exp $ +# $Id: Makefile.in,v 1.12 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -23,7 +23,7 @@ CINCLUDES = -I${srcdir}/.. \ -I./include \ -I${srcdir}/include \ -I${srcdir}/../include -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = # Alphabetically diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c index b0db90d410..65eddb050a 100644 --- a/lib/isc/win32/app.c +++ b/lib/isc/win32/app.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: app.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */ +/* $Id: app.c,v 1.8 2009/09/01 00:22:28 jinmei Exp $ */ #include @@ -75,7 +75,7 @@ DWORD dwWaitResult; static isc_thread_t main_thread; isc_result_t -isc_app_start(void) { +isc__app_start(void) { isc_result_t result; /* @@ -99,7 +99,7 @@ isc_app_start(void) { } isc_result_t -isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, +isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { isc_event_t *event; isc_task_t *cloned_task = NULL; @@ -133,7 +133,7 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, } isc_result_t -isc_app_run(void) { +isc__app_run(void) { isc_event_t *event, *next_event; isc_task_t *task; HANDLE *pHandles = NULL; @@ -199,7 +199,7 @@ isc_app_run(void) { } isc_result_t -isc_app_shutdown(void) { +isc__app_shutdown(void) { isc_boolean_t want_kill = ISC_TRUE; LOCK(&lock); @@ -218,7 +218,7 @@ isc_app_shutdown(void) { } isc_result_t -isc_app_reload(void) { +isc__app_reload(void) { isc_boolean_t want_reload = ISC_TRUE; LOCK(&lock); @@ -238,12 +238,12 @@ isc_app_reload(void) { } void -isc_app_finish(void) { +isc__app_finish(void) { DESTROYLOCK(&lock); } void -isc_app_block(void) { +isc__app_block(void) { REQUIRE(running); REQUIRE(!blocked); @@ -252,7 +252,7 @@ isc_app_block(void) { } void -isc_app_unblock(void) { +isc__app_unblock(void) { REQUIRE(running); REQUIRE(blocked); blocked = ISC_FALSE; diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index e60618cdfb..b63eebe508 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.76 2009/07/17 06:25:44 each Exp $ */ +/* $Id: socket.c,v 1.77 2009/09/01 00:22:28 jinmei Exp $ */ /* This code uses functions which are only available on Server 2003 and * higher, and Windows XP and higher. @@ -1594,7 +1594,7 @@ free_socket(isc_socket_t **sockp, int lineno) { * in 'socketp'. */ isc_result_t -isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, +isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, isc_socket_t **socketp) { isc_socket_t *sock = NULL; isc_result_t result; @@ -1774,7 +1774,7 @@ isc_socket_open(isc_socket_t *sock) { * Attach to a socket. Caller must explicitly detach when it is done. */ void -isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { +isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { REQUIRE(VALID_SOCKET(sock)); REQUIRE(socketp != NULL && *socketp == NULL); @@ -1791,7 +1791,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { * up by destroying the socket. */ void -isc_socket_detach(isc_socket_t **socketp) { +isc__socket_detach(isc_socket_t **socketp) { isc_socket_t *sock; isc_boolean_t kill_socket = ISC_FALSE; @@ -2434,13 +2434,13 @@ SocketIoThread(LPVOID ThreadContext) { * Create a new socket manager. */ isc_result_t -isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { return (isc_socketmgr_create2(mctx, managerp, 0)); } isc_result_t -isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, - unsigned int maxsocks) +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks) { isc_socketmgr_t *manager; isc_result_t result; @@ -2489,7 +2489,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, } isc_result_t -isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { +isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { REQUIRE(VALID_MANAGER(manager)); REQUIRE(nsockp != NULL); @@ -2497,7 +2497,7 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { } void -isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { +isc__socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { REQUIRE(VALID_MANAGER(manager)); REQUIRE(ISC_LIST_EMPTY(manager->socklist)); REQUIRE(manager->stats == NULL); @@ -2507,7 +2507,7 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { } void -isc_socketmgr_destroy(isc_socketmgr_t **managerp) { +isc__socketmgr_destroy(isc_socketmgr_t **managerp) { isc_socketmgr_t *manager; int i; isc_mem_t *mctx; @@ -2635,7 +2635,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, } isc_result_t -isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, +isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, unsigned int minimum, isc_task_t *task, isc_taskaction_t action, const void *arg) { @@ -2705,8 +2705,9 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, } isc_result_t -isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, - isc_task_t *task, isc_taskaction_t action, const void *arg) +isc__socket_recv(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, const void *arg) { isc_socketevent_t *dev; isc_socketmgr_t *manager; @@ -2742,9 +2743,9 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, } isc_result_t -isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_socketevent_t *event, unsigned int flags) +isc__socket_recv2(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags) { isc_result_t ret; @@ -2852,8 +2853,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, } isc_result_t -isc_socket_send(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg) +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg) { /* * REQUIRE() checking is performed in isc_socket_sendto(). @@ -2863,9 +2864,9 @@ isc_socket_send(isc_socket_t *sock, isc_region_t *region, } isc_result_t -isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +isc__socket_sendto(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { isc_socketevent_t *dev; isc_socketmgr_t *manager; @@ -2906,17 +2907,17 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, } isc_result_t -isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg) +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg) { return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL, NULL)); } isc_result_t -isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, const void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) { isc_socketevent_t *dev; isc_socketmgr_t *manager; @@ -2969,10 +2970,10 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, } isc_result_t -isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - isc_socketevent_t *event, unsigned int flags) +isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags) { isc_result_t ret; @@ -3004,8 +3005,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, } isc_result_t -isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, - unsigned int options) { +isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options) { int bind_errno; char strbuf[ISC_STRERRORSIZE]; int on = 1; @@ -3070,7 +3071,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, } isc_result_t -isc_socket_filter(isc_socket_t *sock, const char *filter) { +isc__socket_filter(isc_socket_t *sock, const char *filter) { UNUSED(sock); UNUSED(filter); @@ -3089,7 +3090,7 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) { * as well keep things simple rather than having to track them. */ isc_result_t -isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { +isc__socket_listen(isc_socket_t *sock, unsigned int backlog) { char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); @@ -3134,8 +3135,8 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { * This should try to do aggressive accept() XXXMLG */ isc_result_t -isc_socket_accept(isc_socket_t *sock, - isc_task_t *task, isc_taskaction_t action, const void *arg) +isc__socket_accept(isc_socket_t *sock, + isc_task_t *task, isc_taskaction_t action, const void *arg) { isc_socket_newconnev_t *adev; isc_socketmgr_t *manager; @@ -3245,8 +3246,8 @@ isc_socket_accept(isc_socket_t *sock, } isc_result_t -isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, - isc_task_t *task, isc_taskaction_t action, const void *arg) +isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, const void *arg) { char strbuf[ISC_STRERRORSIZE]; isc_socket_connev_t *cdev; @@ -3360,7 +3361,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, } isc_result_t -isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { +isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { isc_result_t result; REQUIRE(VALID_SOCKET(sock)); @@ -3390,7 +3391,7 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { } isc_result_t -isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { +isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { ISC_SOCKADDR_LEN_T len; isc_result_t result; char strbuf[ISC_STRERRORSIZE]; @@ -3437,7 +3438,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { * queued for task "task" of type "how". "how" is a bitmask. */ void -isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { +isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { REQUIRE(VALID_SOCKET(sock)); @@ -3563,7 +3564,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { } isc_sockettype_t -isc_socket_gettype(isc_socket_t *sock) { +isc__socket_gettype(isc_socket_t *sock) { isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); @@ -3584,7 +3585,7 @@ isc_socket_gettype(isc_socket_t *sock) { } isc_boolean_t -isc_socket_isbound(isc_socket_t *sock) { +isc__socket_isbound(isc_socket_t *sock) { isc_boolean_t val; REQUIRE(VALID_SOCKET(sock)); @@ -3607,7 +3608,7 @@ isc_socket_isbound(isc_socket_t *sock) { } void -isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { +isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { #if defined(IPV6_V6ONLY) int onoff = yes ? 1 : 0; #else @@ -3625,14 +3626,14 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { } void -isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) { +isc__socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) { UNUSED(addr); UNUSED(active); } isc_result_t -isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm, - isc_uint32_t owner, isc_uint32_t group) +isc__socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm, + isc_uint32_t owner, isc_uint32_t group) { UNUSED(addr); UNUSED(perm); @@ -3642,7 +3643,7 @@ isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm, } void -isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { +isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) { /* * Name 'socket'. @@ -3658,12 +3659,12 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) { } const char * -isc_socket_getname(isc_socket_t *socket) { +isc__socket_getname(isc_socket_t *socket) { return (socket->name); } void * -isc_socket_gettag(isc_socket_t *socket) { +isc__socket_gettag(isc_socket_t *socket) { return (socket->tag); } diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in index 5dcc2251b0..1bae4b35cb 100644 --- a/lib/isccc/Makefile.in +++ b/lib/isccc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.9 2007/06/19 23:47:21 tbox Exp $ +# $Id: Makefile.in,v 1.10 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCC_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../lib/isc/libisc.@A@ diff --git a/lib/isccfg/Makefile.in b/lib/isccfg/Makefile.in index 6dcacdd370..c3d2ee4aff 100644 --- a/lib/isccfg/Makefile.in +++ b/lib/isccfg/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.18 2007/06/19 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.19 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} -CDEFINES = @USE_DLZ@ +CDEFINES = -DBIND9 @USE_DLZ@ CWARNINGS = ISCLIBS = ../../lib/isc/libisc.@A@ diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index 3fc1070a37..2b7719444f 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.c,v 1.24 2009/01/18 23:48:14 tbox Exp $ */ +/* $Id: aclconf.c,v 1.25 2009/09/01 00:22:28 jinmei Exp $ */ #include @@ -150,7 +150,7 @@ convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx, isc_buffer_add(&buf, keylen); dns_fixedname_init(&fixname); result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING, "key name '%s' is not a valid domain name", diff --git a/lib/isccfg/dnsconf.c b/lib/isccfg/dnsconf.c new file mode 100644 index 0000000000..e8907bdbb9 --- /dev/null +++ b/lib/isccfg/dnsconf.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2002, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dnsconf.c,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +/*! \file */ + +#include +#include + +/*% + * A trusted key, as used in the "trusted-keys" statement. + */ +static cfg_tuplefielddef_t trustedkey_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "flags", &cfg_type_uint32, 0 }, + { "protocol", &cfg_type_uint32, 0 }, + { "algorithm", &cfg_type_uint32, 0 }, + { "key", &cfg_type_qstring, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_trustedkey = { + "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, trustedkey_fields +}; + +static cfg_type_t cfg_type_trustedkeys = { + "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list, + cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_trustedkey +}; + +/*% + * Clauses that can be found within the top level of the dns.conf + * file only. + */ +static cfg_clausedef_t +dnsconf_clauses[] = { + { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; + +/*% The top-level dns.conf syntax. */ + +static cfg_clausedef_t * +dnsconf_clausesets[] = { + dnsconf_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_dnsconf = { + "dnsconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, dnsconf_clausesets +}; diff --git a/lib/isccfg/include/isccfg/dnsconf.h b/lib/isccfg/include/isccfg/dnsconf.h new file mode 100644 index 0000000000..da34788704 --- /dev/null +++ b/lib/isccfg/include/isccfg/dnsconf.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2002 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dnsconf.h,v 1.2 2009/09/01 00:22:28 jinmei Exp $ */ + +#ifndef ISCCFG_NAMEDCONF_H +#define ISCCFG_NAMEDCONF_H 1 + +/*! \file + * \brief + * This module defines the named.conf, rndc.conf, and rndc.key grammars. + */ + +#include + +/* + * Configuration object types. + */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_dnsconf; +/*%< A complete dns.conf file. */ + +#endif /* ISCCFG_CFG_H */ diff --git a/lib/tests/Makefile.in b/lib/tests/Makefile.in index 81b0bfbdf3..b57a35cf95 100644 --- a/lib/tests/Makefile.in +++ b/lib/tests/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.25 2007/06/19 23:47:23 tbox Exp $ +# $Id: Makefile.in,v 1.26 2009/09/01 00:22:28 jinmei Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -22,7 +22,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${TEST_INCLUDES} -CDEFINES = +CDEFINES = -DBIND9 CWARNINGS = ISCLIBS = ../../lib/isc/libisc.@A@ diff --git a/make/rules.in b/make/rules.in index 2effeef1d8..4191ef038f 100644 --- a/make/rules.in +++ b/make/rules.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: rules.in,v 1.66 2009/01/10 23:47:28 tbox Exp $ +# $Id: rules.in,v 1.67 2009/09/01 00:22:28 jinmei Exp $ ### ### Common Makefile rules for BIND 9. @@ -35,6 +35,8 @@ sysconfdir = @sysconfdir@ localstatedir = @localstatedir@ mandir = @mandir@ datarootdir = @datarootdir@ +export_libdir = @export_libdir@ +export_includedir = @export_includedir@ DESTDIR = @@ -122,7 +124,7 @@ ALL_CPPFLAGS = \ ALL_CFLAGS = ${EXT_CFLAGS} ${ALL_CPPFLAGS} ${CFLAGS} \ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} -.c.@O@: +@BIND9_CO_RULE@ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c $< SHELL = @SHELL@