From 9571391bd39d60ebb0aa5cf2a7e0182d72c5fcd0 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 20 Apr 2009 21:27:09 +0000 Subject: [PATCH] libresolv-38.tar.gz --- APPLE_LICENSE | 367 +++++++++++++++++++++ BUILD | 191 +++++++++++ Makefile | 76 ++--- Makefile.preamble | 1 + dns.c | 139 +++++++- dns_async.c | 341 +++++++------------- dns_plugin.c | 791 ++++++++++++++++++++++++++++++++++++++++++++++ dns_private.h | 2 + dns_util.c | 204 ++++++------ nameser.h | 5 +- ns_print.c | 2 +- res_mkquery.c | 2 +- res_private.h | 8 +- res_query.c | 116 ++++++- res_send.c | 25 +- resolv.h | 8 +- resolver.3 | 9 +- resolver.5 | 4 +- 18 files changed, 1866 insertions(+), 425 deletions(-) create mode 100644 APPLE_LICENSE create mode 100644 BUILD create mode 100644 dns_plugin.c diff --git a/APPLE_LICENSE b/APPLE_LICENSE new file mode 100644 index 0000000..fe81a60 --- /dev/null +++ b/APPLE_LICENSE @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License." diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..5a42a1e --- /dev/null +++ b/BUILD @@ -0,0 +1,191 @@ +#! /bin/sh +# This script will build resolver library +# + +TARGET=resolver +echo +echo "==================================================" +echo $TARGET +echo "==================================================" + +PROJECT_ROOT=../netinfo.build/root +TARGET_DYNAMIC_LIB=libresolv.9.dylib +TARGET_LIB_LINK=libresolv.dylib +TARGET_STATIC_LIB=libresolv.a +TARGET_VERSION=A +TARGET_DIR=usr/lib +COMPAT_VERS=1.0.0 +CURR_VERS=2.0.0 +TARGET_MAN_DIR=/usr/share/man/man5 + +BLD=$TARGET.build +DERIVED_SRC_DIR=$BLD/derived_src +OBJECT_DIR=$BLD/objects + +DST_DIR=$PROJECT_ROOT/$TARGET_DIR +PUBLIC_HEADERS_DIR=$PROJECT_ROOT/usr/include +PRIVATE_HEADERS_DIR=$PROJECT_ROOT/usr/local/include +PROJECT_HEADERS_DIR=../netinfo.build/ProjectHeaders +MAN_DIR=${PROJECT_ROOT}${TARGET_MAN_DIR} + +CFLAGS="-g -dynamic -fno-common -Wall -D_REENTRANT" +INCLUDE="-I. -I$PUBLIC_HEADERS_DIR" +LIBS= +nm /usr/lib/libSystem.B.dylib | grep -q pselect +if [ $? = 1 ]; then + CFLAGS="$CFLAGS -DNEED_PSELECT" +fi + +CLEAN=0 +BUILD=1 + +while [ $# != 0 ]; do + if [ ${1}x = cleanx ]; then + CLEAN=1 + BUILD=0 + fi + + if [ ${1}x = freshx ]; then + CLEAN=1 + BUILD=1 + fi + + shift +done + +if [ $CLEAN = 1 ]; then + echo "Cleaning $TARGET" + rm -rf $BLD + rm -rf .gdb_history +fi + +if [ $BUILD = 0 ]; then + echo "Done" + exit 0 +fi + +if [ ! -d $BLD ]; then + mkdir $BLD +fi +if [ ! -d $DERIVED_SRC_DIR ]; then + mkdir $DERIVED_SRC_DIR + ln -s ../.. $DERIVED_SRC_DIR/NetInfo +fi +if [ ! -d $OBJECT_DIR ]; then + mkdir $OBJECT_DIR +fi + +if [ ! -d $DST_DIR ]; then + if [ -f /bin/mkdirs ]; then + mkdirs $DST_DIR + else + mkdir -p $DST_DIR + fi +fi + +if [ ! -d $PUBLIC_HEADERS_DIR ]; then + if [ -f /bin/mkdirs ]; then + mkdirs $PUBLIC_HEADERS_DIR + mkdirs $PUBLIC_HEADERS_DIR/arpa + else + mkdir -p $PUBLIC_HEADERS_DIR + mkdir -p $PUBLIC_HEADERS_DIR/arpa + fi +fi + +if [ ! -d $PRIVATE_HEADERS_DIR ]; then + if [ -f /bin/mkdirs ]; then + mkdirs $PRIVATE_HEADERS_DIR + else + mkdir -p $PRIVATE_HEADERS_DIR + fi +fi + +if [ ! -d $PROJECT_HEADERS_DIR ]; then + if [ -f /bin/mkdirs ]; then + mkdirs $PROJECT_HEADERS_DIR + else + mkdir -p $PROJECT_HEADERS_DIR + fi +fi + +if [ ! -f $PUBLIC_HEADERS_DIR/dns.h ]; then + echo "cp dns.h $PUBLIC_HEADERS_DIR" + cp dns.h $PUBLIC_HEADERS_DIR +fi + +if [ ! -f $PUBLIC_HEADERS_DIR/dns_util.h ]; then + echo "cp dns_util.h $PUBLIC_HEADERS_DIR" + cp dns_util.h $PUBLIC_HEADERS_DIR +fi + +if [ ! -f $PRIVATE_HEADERS_DIR/dns_private.h ]; then + echo "cp dns_private.h $PRIVATE_HEADERS_DIR" + cp dns_private.h $PRIVATE_HEADERS_DIR +fi + +if [ ! -f $PROJECT_HEADERS_DIR/dns_private.h ]; then + echo "cp dns_private.h $PROJECT_HEADERS_DIR" + cp dns_private.h $PROJECT_HEADERS_DIR +fi + +if [ ! -f $PUBLIC_HEADERS_DIR/resolv.h ]; then + echo "cp resolv.h $PUBLIC_HEADERS_DIR" + cp resolv.h $PUBLIC_HEADERS_DIR +fi + +if [ ! -f $PUBLIC_HEADERS_DIR/nameser.h ]; then + echo "cp nameser.h $PUBLIC_HEADERS_DIR" + cp nameser.h $PUBLIC_HEADERS_DIR + echo "ln -s ../nameser.h $PUBLIC_HEADERS_DIR/arpa/nameser.h" + ln -s ../nameser.h $PUBLIC_HEADERS_DIR/arpa/nameser.h +fi + +if [ ! -d $MAN_DIR ]; then + if [ -f /bin/mkdirs ]; then + mkdirs $MAN_DIR + else + mkdir -p $MAN_DIR + fi +fi + +if [ ! -f $MAN_DIR/resolver.5 ]; then + echo "cp resolver.5 $MAN_DIR" + cp resolver.5 $MAN_DIR +fi + +MAKE_TARGET=0 +if [ ! -f $DST_DIR/$TARGET_DYNAMIC_LIB ]; then + MAKE_TARGET=1 +fi + +for c in *.[mc] +do + OBJ=`echo $c | sed 's/..$/.o/'` + SRC=$c + DST=$OBJECT_DIR/$OBJ + + MAKEIT=1 + if [ -f $DST ]; then + RECENT=`/bin/ls -1t $DST $SRC | head -1` + if [ $RECENT = $DST ]; then + MAKEIT=0 + fi + fi + + if [ $MAKEIT = 1 ]; then + MAKE_TARGET=1 + echo cc -c $CFLAGS $INCLUDE -o $DST $SRC + cc -c $CFLAGS $INCLUDE -o $DST $SRC + fi +done + +if [ $MAKE_TARGET = 1 ]; then + echo libtool -dynamic -install_name /${TARGET_DIR}/${TARGET_DYNAMIC_LIB} -compatibility_version $COMPAT_VERS -current_version $CURR_VERS -arch_only ppc -o $DST_DIR/${TARGET_DYNAMIC_LIB} $OBJECT_DIR/*.o -lcc_dynamic -framework System + libtool -dynamic -install_name /${TARGET_DIR}/${TARGET_DYNAMIC_LIB} -compatibility_version $COMPAT_VERS -current_version $CURR_VERS -arch_only ppc -o $DST_DIR/${TARGET_DYNAMIC_LIB} $OBJECT_DIR/*.o -lcc_dynamic -ldnsinfo -framework System + echo "ln -s $TARGET_DYNAMIC_LIB $DST_DIR/${TARGET_LIB_LINK}" + ln -s $TARGET_DYNAMIC_LIB $DST_DIR/${TARGET_LIB_LINK} +fi + +echo "Finished building $TARGET" +exit 0 diff --git a/Makefile b/Makefile index 9f28573..1f10d4f 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,6 @@ -# -# Generated by the Apple Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = resolv - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Library +Project = resolv +ProductType = dylib +Install_Dir = /usr/lib HFILES = dns.h dns_private.h dns_util.h dst.h dst_internal.h\ nameser.h res_debug.h res_private.h res_update.h resolv.h @@ -22,43 +12,45 @@ CFILES = base64.c dns.c dns_async.c dns_util.c dst_api.c\ res_findzonecut.c res_init.c res_mkquery.c res_mkupdate.c\ res_query.c res_send.c res_sendsigned.c res_update.c -OTHERSRCS = Makefile Makefile.postamble Makefile.preamble resolver.3 resolver_so.3 resolver.5 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CURRENTLY_ACTIVE_VERSION = YES -DEPLOY_WITH_VERSION_NAME = 9 -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = library.make -NEXTSTEP_INSTALLDIR = /usr/lib -LIBS = -ldnsinfo -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - +# NOTE dns_plugin.c is not included in CFILES since it isn't part of the dylib -PUBLIC_HEADERS = dns.h dns_util.h nameser.h resolv.h +MANPAGES = resolver.3 resolver.5 -PROJECT_HEADERS = dns.h dns_private.h dns_util.h dst.h dst_internal.h\ - nameser.h res_debug.h res_private.h res_update.h\ - resolv.h +Install_Headers = dns.h dns_util.h nameser.h resolv.h +Install_Private_Headers = dns_private.h +Library_Version = 9 +Extra_CC_Flags = -Wall -Werror -fno-common -I. -WINDOWS_PUBLIC_HEADERS_DIR = LOCAL_DEVELOPER_DIR/Headers/$(NAME) +PRODUCT = $(shell tconf --product) +ifeq "$(PRODUCT)" "iPhone" +Extra_CC_Flags += -DUSE_DNS_PSELECT +endif -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make -include $(MAKEFILEDIR)/platform.make +build:: dns.so --include Makefile.preamble +PLUGIN_LD_Flags = -L$(SYMROOT) -lresolv.9 +PLUGIN_CC_Flags = -bundle -include $(MAKEFILEDIR)/$(MAKEFILE) +PLUGIN_DEST = $(DSTROOT)/$(DESTDIR)usr/lib/info --include Makefile.postamble +dns.so: dns_plugin.c + cc -c $(CFLAGS) dns_plugin.c + cc $(PLUGIN_CC_Flags) $(LDFLAGS) $(PLUGIN_LD_Flags) -o $(SYMROOT)/dns.so dns_plugin.o + dsymutil --out=$(SYMROOT)/dns.so.dSYM $(SYMROOT)/dns.so || exit 0 + $(INSTALL_DIRECTORY) $(PLUGIN_DEST) + $(INSTALL_LIBRARY) $(SYMROOT)/dns.so $(PLUGIN_DEST) + strip -S $(PLUGIN_DEST)/dns.so --include Makefile.dependencies +after_install: + $(INSTALL_DIRECTORY) $(DSTROOT)/usr/include/arpa + $(LN) -sf ../nameser.h $(DSTROOT)/usr/include/arpa + @for FILE in \ + dn_comp.3 dn_expand.3 dn_skipname.3 \ + ns_get16.3 ns_get32.3 ns_put16.3 ns_put32.3 \ + res_init.3 res_mkquery.3 res_query.3 res_search.3 res_send.3 ; do \ + $(INSTALL_FILE) resolver_so.3 $(DSTROOT)/usr/share/man/man3/$${FILE} ; \ + done diff --git a/Makefile.preamble b/Makefile.preamble index e50fc53..046bb8d 100644 --- a/Makefile.preamble +++ b/Makefile.preamble @@ -1,3 +1,4 @@ +OTHER_LDFLAGS += -undefined dynamic_lookup PUBLIC_HEADER_DIR=/usr/include PUBLIC_HEADER_DIR_SUFFIX = ARPA_HEADER_DIR_SUFFIX = /arpa diff --git a/dns.c b/dns.c index 7c5ceb4..fa2e658 100644 --- a/dns.c +++ b/dns.c @@ -51,6 +51,10 @@ #define DNS_RESOLVER_DIR "/etc/resolver" +#define NOTIFY_DNS_CONTROL_NAME "com.apple.system.dns" +#define DNS_CONTROL_FLAG_DEBUG 0x0000000000000001LL +#define DNS_CONTROL_FLAG_NO_MDNS 0x0000000000000002LL + #define NOTIFY_DIR_NAME "com.apple.system.dns.resolver.dir" #define DNS_DELAY_NAME "com.apple.system.dns.delay" @@ -61,6 +65,11 @@ #define MDNS_MIN_TTL 2 +static int dns_control_token = -1; +static int dns_control_mdns = 1; +static int dns_control_debug = 0; +static pthread_mutex_t dns_control_lock = PTHREAD_MUTEX_INITIALIZER; + extern uint32_t notify_monitor_file(int token, const char *name, int flags); extern void res_client_close(res_state res); @@ -472,6 +481,43 @@ _pdns_convert_sc(dns_resolver_t *r) return pdns; } +static pdns_handle_t * +_mdns_primary(dns_resolver_t *r) +{ + pdns_handle_t *pdns; + char *val, *p; + int i; + + pdns = _pdns_build_start(r->domain); + if (r->domain == NULL) _pdns_build(pdns, "default", NULL); + + p = getenv("RES_RETRY_TIMEOUT"); + if (p != NULL) pdns->send_timeout = atoi(p); + + p = getenv("RES_RETRY"); + if (p != NULL) pdns->res->retry= atoi(p); + + if (r->n_search > MAXDNSRCH) r->n_search = MAXDNSRCH; + for (i = 0; i < r->n_search; i++) + { + val = NULL; + asprintf(&val, "%s", r->search[i]); + if (val == NULL) + { + _pdns_free(pdns); + return NULL; + } + + _pdns_build(pdns, "search", val); + free(val); + } + + _pdns_build(pdns, "mdns", NULL); + + _pdns_build_finish(pdns); + return pdns; +} + /* * Open a named resolver client from the system config data. */ @@ -740,8 +786,17 @@ _check_cache(sdns_handle_t *sdns) sc_dns_count = 0; if ((sc_dns != NULL) && (sc_dns->n_resolver > 0)) { - sc_dns_count = sc_dns->n_resolver; - sdns->pdns_primary = _pdns_convert_sc(sc_dns->resolver[0]); + if (sdns->flags & DNS_FLAG_FORWARD_TO_MDNSRESPONDER) + { + sc_dns_count = 1; + sdns->pdns_primary = _mdns_primary(sc_dns->resolver[0]); + } + else + { + sc_dns_count = sc_dns->n_resolver; + sdns->pdns_primary = _pdns_convert_sc(sc_dns->resolver[0]); + } + _pdns_check_search_list(sdns->pdns_primary); } else @@ -882,7 +937,7 @@ _pdns_get_default_handles(sdns_handle_t *sdns, pdns_handle_t ***pdns) } static uint32_t -_pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, uint32_t nlabels, pdns_handle_t ***pdns) +_pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, pdns_handle_t ***pdns) { char *p, *vname; int i, j, k, count; @@ -906,9 +961,6 @@ _pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, uint32_t nlabe { if (sdns->client[i]->name == NULL) continue; - /* Special case: Don't send to ".local[.]" queries to mDNSResponder if nlabels > 2 */ - if ((nlabels > 2) && (sdns->client[i]->flags & DNS_FLAG_FORWARD_TO_MDNSRESPONDER) && (!strcasecmp(sdns->client[i]->name, "local"))) continue; - if (!strcasecmp(sdns->client[i]->name, p)) { if (count == 0) @@ -942,7 +994,7 @@ _pdns_get_handles_for_name(sdns_handle_t *sdns, const char *name, uint32_t nlabe if (count != 0) return count; - return _pdns_get_default_handles(sdns, pdns);; + return _pdns_get_default_handles(sdns, pdns); } static void @@ -1024,11 +1076,45 @@ dns_handle_t dns_open(const char *name) { dns_private_handle_t *dns; + struct stat sb; + int check, status, local_control; + uint64_t control; dns = (dns_private_handle_t *)calloc(1, sizeof(dns_private_handle_t)); if (dns == NULL) return NULL; - if (name == NULL) + /* set up control notification if necessary */ + if (dns_control_token == -1) + { + pthread_mutex_lock(&dns_control_lock); + if (dns_control_token == -1) status = notify_register_check(NOTIFY_DNS_CONTROL_NAME, &dns_control_token); + pthread_mutex_unlock(&dns_control_lock); + } + + /* check for dns flags */ + if (dns_control_token != -1) + { + pthread_mutex_lock(&dns_control_lock); + status = notify_check(dns_control_token, &check); + if ((status == 0) && (check == 1)) + { + /* notification was triggered */ + status = notify_get_state(dns_control_token, &control); + if (status == 0) + { + if (control & DNS_CONTROL_FLAG_NO_MDNS) dns_control_mdns = 0; + if (control & DNS_CONTROL_FLAG_DEBUG) dns_control_debug = 1; + } + } + + pthread_mutex_unlock(&dns_control_lock); + } + + if (name == NULL) local_control = dns_control_mdns; + else if (!strcmp(name, MDNS_HANDLE_NAME)) local_control = 2; + else local_control = 0; + + if ((name == NULL) && (local_control == 0)) { dns->handle_type = DNS_PRIVATE_HANDLE_TYPE_SUPER; dns->sdns = (sdns_handle_t *)calloc(1, sizeof(sdns_handle_t)); @@ -1044,6 +1130,31 @@ dns_open(const char *name) dns->sdns->notify_delay_token = -1; _dns_open_notify(dns->sdns); + memset(&sb, 0, sizeof(struct stat)); + dns_set_debug((dns_handle_t)dns, dns_control_debug); + + return (dns_handle_t)dns; + } + + if (local_control != 0) + { + dns->handle_type = DNS_PRIVATE_HANDLE_TYPE_SUPER; + dns->sdns = (sdns_handle_t *)calloc(1, sizeof(sdns_handle_t)); + if (dns->sdns == NULL) + { + free(dns); + return NULL; + } + + dns->sdns->flags = DNS_FLAG_FORWARD_TO_MDNSRESPONDER; + dns->sdns->notify_sys_config_token = -1; + dns->sdns->notify_dir_token = -1; + dns->sdns->notify_delay_token = -1; + if (local_control == 1) _dns_open_notify(dns->sdns); + + memset(&sb, 0, sizeof(struct stat)); + dns_set_debug((dns_handle_t)dns, dns_control_debug); + return (dns_handle_t)dns; } @@ -1059,6 +1170,7 @@ dns_open(const char *name) return NULL; } + dns_set_debug((dns_handle_t)dns, dns_control_debug); return (dns_handle_t)dns; } @@ -1358,7 +1470,7 @@ _pdns_search(sdns_handle_t *sdns, pdns_handle_t *pdns, const char *name, uint32_ } static int -_sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, uint32_t nlabels, int *min) +_sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min) { char *qname; pdns_handle_t **pdns; @@ -1373,7 +1485,7 @@ _sdns_send(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, *min = -1; m = -1; - pdns_count = _pdns_get_handles_for_name(sdns, name, nlabels, &pdns); + pdns_count = _pdns_get_handles_for_name(sdns, name, &pdns); if (pdns_count == 0) return -1; @@ -1412,7 +1524,7 @@ __private_extern__ int _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min) { pdns_handle_t *primary, **pdns; - int i, n, ndots, nlabels, status; + int i, n, ndots, status; int m, tmin, minstate; char *dot, *qname; uint32_t pdns_count; @@ -1455,9 +1567,6 @@ _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t typ /* the last dot is the last character, name is fully qualified */ if ((fqdn == 0) && (dot != NULL) && (*(dot + 1) == '\0')) fqdn = 1; - /* number of labels */ - nlabels = n + 1 - fqdn; - /* * If n >= ndots, or it's a FQDN, or if it's a PTR query, * we try a query with the name "as is". @@ -1465,7 +1574,7 @@ _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t typ if ((n >= ndots) || (fqdn == 1) || (type == ns_t_ptr)) { tmin = -1; - status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, nlabels, &tmin); + status = _sdns_send(sdns, name, class, type, fqdn, buf, len, from, fromlen, &tmin); if (status > 0) return status; if (tmin < 0) minstate = -1; diff --git a/dns_async.c b/dns_async.c index 9aa367a..66bff8b 100644 --- a/dns_async.c +++ b/dns_async.c @@ -1,25 +1,24 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003 - 2008 Apple, Inc. All rights reserved. * - * @APPLE_LICENSE_headER_START@ + * @APPLE_LICENSE_HEADER_START@ * - * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_headER_END@ + * @APPLE_LICENSE_HEADER_END@ */ #include @@ -33,114 +32,136 @@ #include #include #include +#include +#include -typedef struct -{ - uint32_t datalen; - char *databuf; - uint32_t _size; - uint32_t _dict; - uint32_t _key; - uint32_t _vlist; - uint32_t _val; -} kvbuf_t; +extern void *LI_ils_create(char *fmt, ...); + +/* + typedef void (*dns_async_callback)(int32_t status, char *buf, uint32_t len, struct sockaddr *from, int fromlen, void *context); +*/ typedef struct { - uint32_t kcount; - const char **key; - uint32_t *vcount; - const char ***val; -} kvdict_t; + void *orig_callback; + void *orig_context; + si_mod_t *dns; +} _dns_context_t; -typedef struct +static void +_dns_callback(si_item_t *item, uint32_t status, void *ctx) { - uint32_t count; - uint32_t curr; - kvdict_t *dict; - kvbuf_t *kv; -} kvarray_t; + _dns_context_t *my_ctx; + si_dnspacket_t *res; + char *packet; + struct sockaddr *from; + uint32_t pl; + int fl; -extern kvbuf_t *kvbuf_new(void); -extern void kvbuf_add_dict(kvbuf_t *kv); -extern void kvbuf_add_key(kvbuf_t *kv, const char *key); -extern void kvbuf_add_val(kvbuf_t *kv, const char *val); -extern void kvbuf_free(kvbuf_t *kv); -extern void kvarray_free(kvarray_t *kva); -extern uint32_t kvbuf_get_val_len(const char *val); -extern kern_return_t LI_DSLookupGetProcedureNumber(const char *name, int *procno); -extern kern_return_t LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context); -extern kern_return_t LI_async_handle_reply(void *msg, kvarray_t **reply, void **callback, void **context); -extern kern_return_t LI_async_receive(mach_port_t p, kvarray_t **reply); -extern void LI_async_call_cancel(mach_port_t p, void **context); -extern uint32_t kvbuf_get_len(const char *p); + if (ctx == NULL) return; + + my_ctx = (_dns_context_t *)ctx; + if (my_ctx->orig_callback == NULL) + { + si_item_release(item); + si_module_release(my_ctx->dns); + free(my_ctx); + return; + } -static kvbuf_t * -dns_make_query(const char *name, uint16_t dnsclass, uint16_t dnstype, uint32_t do_search) -{ - kvbuf_t *request; - char str[128]; + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; - if (name == NULL) return NULL; + packet = NULL; + pl = 0; + from = NULL; + fl = 0; - request = kvbuf_new(); - if (request == NULL) return NULL; - - kvbuf_add_dict(request); - - /* Encode name */ - kvbuf_add_key(request, "domain"); - kvbuf_add_val(request, name); + res = NULL; + if (item != NULL) res = (si_dnspacket_t *)((char *)item + sizeof(si_item_t)); - /* Encode class */ - snprintf(str, 128, "%hu", dnsclass); - kvbuf_add_key(request, "class"); - kvbuf_add_val(request, str); + if ((res != NULL) && (res->dns_packet_len > 0)) + { + packet = malloc(res->dns_packet_len); + if (packet == NULL) status = NO_RECOVERY; + else + { + pl = res->dns_packet_len; + memcpy(packet, res->dns_packet, res->dns_packet_len); + + if (res->dns_server_len > 0) + { + from = malloc(res->dns_server_len); + if (from == NULL) + { + status = NO_RECOVERY; + free(packet); + packet = NULL; + pl = 0; + } + else + { + fl = res->dns_server_len; + memcpy(from, res->dns_server, res->dns_server_len); + } + } + } + } - /* Encode type */ - snprintf(str, 128, "%hu", dnstype); - kvbuf_add_key(request, "type"); - kvbuf_add_val(request, str); + si_item_release(item); - /* Encode do_search */ - snprintf(str, 128, "%hu", do_search); - kvbuf_add_key(request, "search"); - kvbuf_add_val(request, str); + ((dns_async_callback)(my_ctx->orig_callback))(status, packet, pl, from, fl, my_ctx->orig_context); - return request; + si_module_release(my_ctx->dns); + free(my_ctx); } int32_t dns_async_start(mach_port_t *p, const char *name, uint16_t dnsclass, uint16_t dnstype, uint32_t do_search, dns_async_callback callback, void *context) { - int32_t status; - kvbuf_t *request; - static int proc = -1; + si_mod_t *dns; + int call; + uint32_t c, t; + _dns_context_t *my_ctx; *p = MACH_PORT_NULL; if (name == NULL) return NO_RECOVERY; - if (proc < 0) + dns = si_module_with_name("mdns"); + if (dns == NULL) return NO_RECOVERY; + + my_ctx = (_dns_context_t *)calloc(1, sizeof(_dns_context_t)); + if (my_ctx == NULL) { - status = LI_DSLookupGetProcedureNumber("dns_proxy", &proc); - if (status != KERN_SUCCESS) return NO_RECOVERY; + si_module_release(dns); + return NO_RECOVERY; } - request = dns_make_query(name, dnsclass, dnstype, do_search); - if (request == NULL) return NO_RECOVERY; + my_ctx->orig_callback = callback; + my_ctx->orig_context = context; + my_ctx->dns = dns; + + call = SI_CALL_DNS_QUERY; + if (do_search != 0) call = SI_CALL_DNS_SEARCH; + + c = dnsclass; + t = dnstype; + + *p = si_async_call(dns, call, name, NULL, c, t, 0, 0, (void *)_dns_callback, (void *)my_ctx); + if (*p == MACH_PORT_NULL) + { + free(my_ctx); + si_module_release(dns); + return NO_RECOVERY; + } - status = LI_async_start(p, proc, request, (void *)callback, context); - - kvbuf_free(request); - if (status != 0) return NO_RECOVERY; return 0; } void dns_async_cancel(mach_port_t p) { - LI_async_call_cancel(p, NULL); + si_async_cancel(p); } int32_t @@ -149,156 +170,16 @@ dns_async_send(mach_port_t *p, const char *name, uint16_t dnsclass, uint16_t dns return dns_async_start(p, name, dnsclass, dnstype, do_search, NULL, NULL); } -static int -dns_extract_data(kvarray_t *in, char **buf, uint32_t *len, struct sockaddr **from, uint32_t *fromlen) -{ - int32_t status; - struct in_addr addr4; - struct sockaddr_in sin4; - struct in6_addr addr6; - struct sockaddr_in6 sin6; - uint32_t d, k, kcount; - - if (in == NULL) return -1; - if (buf == NULL) return -1; - if (len == NULL) return -1; - if (from == NULL) return -1; - if (fromlen == NULL) return -1; - - *buf = NULL; - *len = 0; - *from = NULL; - *fromlen = 0; - - d = in->curr; - in->curr++; - - if (d >= in->count) return -1; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "data")) - { - if (in->dict[d].vcount[k] == 0) continue; - if (*buf != NULL) continue; - - /* - * dns_proxy contains binary data, possibly with embedded nuls, - * so we extract the string length from the kvbuf_t reply that - * Libinfo got from directory services, rather than calling strlen(). - */ - *len = kvbuf_get_len(in->dict[d].val[k][0]); - if (*len == 0) continue; - - *buf = malloc(*len); - if (*buf == NULL) return -1; - - memcpy(*buf, in->dict[d].val[k][0], *len); - } - else if (!strcmp(in->dict[d].key[k], "server")) - { - if (in->dict[d].vcount[k] == 0) continue; - if (*from != NULL) continue; - - memset(&addr4, 0, sizeof(struct in_addr)); - memset(&sin4, 0, sizeof(struct sockaddr_in)); - - memset(&addr6, 0, sizeof(struct in6_addr)); - memset(&sin6, 0, sizeof(struct sockaddr_in6)); - - status = inet_pton(AF_INET6, in->dict[d].val[k][0], &addr6); - if (status == 1) - { - sin6.sin6_addr = addr6; - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(struct sockaddr_in6); - *from = (struct sockaddr *)calloc(1, sin6.sin6_len); - memcpy(*from, &sin6, sin6.sin6_len); - *fromlen = sin6.sin6_len; - } - - status = inet_pton(AF_INET, in->dict[d].val[k][0], &addr4); - if (status == 1) - { - sin4.sin_addr = addr4; - sin4.sin_family = AF_INET; - sin4.sin_len = sizeof(struct sockaddr_in); - *from = (struct sockaddr *)calloc(1, sin4.sin_len); - memcpy(*from, &sin4, sin4.sin_len); - *fromlen = sin4.sin_len; - } - } - } - - return 0; -} - +/* unsupported */ int32_t dns_async_receive(mach_port_t p, char **buf, uint32_t *len, struct sockaddr **from, uint32_t *fromlen) { - kern_return_t status; - kvarray_t *reply; - - reply = NULL; - - status = LI_async_receive(p, &reply); - if (status != 0) return NO_RECOVERY; - if (reply == NULL) return HOST_NOT_FOUND; - - status = dns_extract_data(reply, buf, len, from, fromlen); - kvarray_free(reply); - if (status != 0) return NO_RECOVERY; - - if (*buf == NULL) return NO_DATA; - return 0; } int32_t dns_async_handle_reply(void *msg) { - dns_async_callback callback; - void *context; - char *buf; - kvarray_t *reply; - kern_return_t status; - struct sockaddr *from; - uint32_t len, fromlen; - - callback = (dns_async_callback)NULL; - context = NULL; - reply = NULL; - buf = NULL; - len = 0; - from = NULL; - fromlen = 0; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, &context); - if (status != KERN_SUCCESS) - { - if (status == MIG_REPLY_MISMATCH) return 0; - callback(NO_RECOVERY, NULL, 0, NULL, 0, context); - return NO_RECOVERY; - } - - status = dns_extract_data(reply, &buf, &len, &from, &fromlen); - kvarray_free(reply); - if (status != 0) - { - callback(NO_RECOVERY, NULL, 0, NULL, 0, context); - return 0; - } - - if (buf == NULL) - { - callback(NO_DATA, NULL, 0, NULL, 0, context); - return NO_DATA; - } - - callback(0, buf, len, from, fromlen, context); - + si_async_handle_reply(msg); return 0; } - diff --git a/dns_plugin.c b/dns_plugin.c new file mode 100644 index 0000000..58d8de6 --- /dev/null +++ b/dns_plugin.c @@ -0,0 +1,791 @@ +/* + * Copyright (c) 2008 Apple, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* from dns_util.c */ +#define DNS_MAX_RECEIVE_SIZE 65536 + +#define MDNS_HANDLE_NAME "*MDNS*" + +#define DNS_HANDLE_BUSY 0x00000001 +#define MDNS_HANDLE_BUSY 0x00000002 + +#define MODULE_DNS 0 +#define MODULE_MDNS 1 + +static pthread_mutex_t dns_plugin_lock = PTHREAD_MUTEX_INITIALIZER; + +typedef struct +{ + struct hostent host; + int alias_count; + int addr_count; + uint64_t ttl; +} dns_build_hostent_t; + +typedef struct +{ + dns_handle_t dns; + dns_handle_t mdns; + uint32_t flags; +} dns_plugin_private_t; + +#define DNS_FLAGS_RCODE_MASK 0x000f +static const char hexchar[] = "0123456789abcdef"; + +static dns_handle_t +dns_checkout_handle(si_mod_t *si) +{ + dns_plugin_private_t *pp; + dns_handle_t dns; + + if (si == NULL) return NULL; + + pthread_mutex_lock(&dns_plugin_lock); + if (si->private == NULL) + { + pp = (dns_plugin_private_t *)calloc(1, sizeof(dns_plugin_private_t)); + si->private = pp; + } + + dns = NULL; + pp = (dns_plugin_private_t *)si->private; + + if (pp == NULL) + { + /* shouldn't happen */ + dns = dns_open(NULL); + pthread_mutex_unlock(&dns_plugin_lock); + return dns; + } + + if ((pp->flags & DNS_HANDLE_BUSY) == 0) + { + if (pp->dns == NULL) pp->dns = dns_open(NULL); + pp->flags |= DNS_HANDLE_BUSY; + pthread_mutex_unlock(&dns_plugin_lock); + return pp->dns; + } + + /* main dns handle is busy - create a temporary one */ + dns = dns_open(NULL); + pthread_mutex_unlock(&dns_plugin_lock); + return dns; +} + +static dns_handle_t +mdns_checkout_handle(si_mod_t *si) +{ + dns_plugin_private_t *pp; + dns_handle_t dns; + + if (si == NULL) return NULL; + + pthread_mutex_lock(&dns_plugin_lock); + if (si->private == NULL) + { + pp = (dns_plugin_private_t *)calloc(1, sizeof(dns_plugin_private_t)); + si->private = pp; + } + + dns = NULL; + pp = (dns_plugin_private_t *)si->private; + + if (pp == NULL) + { + /* shouldn't happen */ + dns = dns_open(MDNS_HANDLE_NAME); + pthread_mutex_unlock(&dns_plugin_lock); + return dns; + } + + if ((pp->flags & MDNS_HANDLE_BUSY) == 0) + { + if (pp->mdns == NULL) pp->mdns = dns_open(MDNS_HANDLE_NAME); + pp->flags |= MDNS_HANDLE_BUSY; + pthread_mutex_unlock(&dns_plugin_lock); + return pp->mdns; + } + + /* main mdns handle is busy - create a temporary one */ + dns = dns_open(MDNS_HANDLE_NAME); + pthread_mutex_unlock(&dns_plugin_lock); + return dns; +} + +static void +dns_checkin_handle(si_mod_t *si, dns_handle_t dns) +{ + dns_plugin_private_t *pp; + + if (si == NULL) return; + if (dns == NULL) return; + + pthread_mutex_lock(&dns_plugin_lock); + if (si->private == NULL) + { + /* shouldn't happen */ + pp = (dns_plugin_private_t *)calloc(1, sizeof(dns_plugin_private_t)); + si->private = pp; + } + + pp = (dns_plugin_private_t *)si->private; + + if (pp == NULL) + { + /* shouldn't happen */ + dns_free(dns); + pthread_mutex_unlock(&dns_plugin_lock); + return; + } + + if (pp->dns == dns) + { + pp->flags &= ~DNS_HANDLE_BUSY; + pthread_mutex_unlock(&dns_plugin_lock); + return; + } + else if (pp->mdns == dns) + { + pp->flags &= ~MDNS_HANDLE_BUSY; + pthread_mutex_unlock(&dns_plugin_lock); + return; + } + + dns_free(dns); + pthread_mutex_unlock(&dns_plugin_lock); +} + +static char * +dns_reverse_ipv4(const char *addr) +{ + union + { + uint32_t a; + unsigned char b[4]; + } ab; + char *p; + + if (addr == NULL) return NULL; + + memcpy(&(ab.a), addr, 4); + + asprintf(&p, "%u.%u.%u.%u.in-addr.arpa.", ab.b[3], ab.b[2], ab.b[1], ab.b[0]); + return p; +} + +static char * +dns_reverse_ipv6(const char *addr) +{ + char x[65], *p; + int i, j; + u_int8_t d, hi, lo; + + if (addr == NULL) return NULL; + + x[64] = '\0'; + j = 63; + for (i = 0; i < 16; i++) + { + d = addr[i]; + lo = d & 0x0f; + hi = d >> 4; + x[j--] = '.'; + x[j--] = hexchar[hi]; + x[j--] = '.'; + x[j--] = hexchar[lo]; + } + + p = calloc(1, 75); + if (p == NULL) return NULL; + + memmove(p, x, 64); + strcat(p, "ip6.arpa."); + + return p; +} + +static char * +dns_lower_case(const char *s) +{ + int i; + char *t; + + if (s == NULL) return NULL; + t = malloc(strlen(s) + 1); + + for (i = 0; s[i] != '\0'; i++) + { + if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32; + else t[i] = s[i]; + } + t[i] = '\0'; + return t; +} + +static int +dns_host_merge_alias(const char *name, dns_build_hostent_t *h) +{ + int i; + + if (name == NULL) return 0; + if (h == NULL) return 0; + + if ((h->host.h_name != NULL) && (!strcmp(name, h->host.h_name))) return 0; + for (i = 0; i < h->alias_count; i++) if (!strcmp(name, h->host.h_aliases[i])) return 0; + + h->host.h_aliases = (char **)reallocf(h->host.h_aliases, (h->alias_count + 2) * sizeof(char *)); + if (h->host.h_aliases == NULL) + { + h->alias_count = 0; + return -1; + } + + h->host.h_aliases[h->alias_count] = dns_lower_case(name); + h->alias_count++; + h->host.h_aliases[h->alias_count] = NULL; + + return 0; +} + +static int +dns_host_append_addr(const char *addr, uint32_t len, dns_build_hostent_t *h) +{ + if (addr == NULL) return 0; + if (h == NULL) return 0; + + if (h->addr_count == 0) h->host.h_addr_list = (char **)calloc(2, sizeof(char *)); + else h->host.h_addr_list = (char **)reallocf(h->host.h_addr_list, (h->addr_count + 2) * sizeof(char *)); + + if (h->host.h_addr_list == NULL) + { + h->addr_count = 0; + return -1; + } + + h->host.h_addr_list[h->addr_count] = malloc(len); + if (h->host.h_addr_list[h->addr_count] == NULL) return -1; + + memcpy(h->host.h_addr_list[h->addr_count], addr, len); + h->addr_count++; + h->host.h_addr_list[h->addr_count] = NULL; + + return 0; +} + +static void +dns_plugin_clear_host(dns_build_hostent_t *h) +{ + uint32_t i; + char **aliases; + + if (h == NULL) return; + + if (h->host.h_name != NULL) free(h->host.h_name); + h->host.h_name = NULL; + + aliases = h->host.h_aliases; + if (aliases != NULL) + { + while (*aliases != NULL) free(*aliases++); + free(h->host.h_aliases); + } + + h->host.h_aliases = NULL; + + if (h->host.h_addr_list != NULL) + { + for (i = 0; h->host.h_addr_list[i] != NULL; i++) free(h->host.h_addr_list[i]); + free(h->host.h_addr_list); + } + + h->host.h_addr_list = NULL; +} + +static int +dns_reply_to_hostent(dns_reply_t *r, int af, const char *addr, dns_build_hostent_t *h) +{ + int i, got_data, got_addr; + int ptrx, cnamex; + + if (r == NULL) return -1; + if (r->status != DNS_STATUS_OK) return -1; + if ((r->header->flags & DNS_FLAGS_RCODE_MASK) != ns_r_noerror) return -1; + + if (r == NULL) return -1; + if (r->header == NULL) return -1; + if (r->header->ancount == 0) return -1; + + got_data = 0; + got_addr = 0; + ptrx = -1; + cnamex = -1; + + for (i = 0; i < r->header->ancount; i++) + { + if ((af == AF_INET) && (r->answer[i]->dnstype == ns_t_a)) + { + got_data++; + got_addr++; + dns_host_append_addr((const char *)&(r->answer[i]->data.A->addr), 4, h); + if (h->ttl == 0) h->ttl = r->answer[i]->ttl; + else if (r->answer[i]->ttl < h->ttl) h->ttl = r->answer[i]->ttl; + } + + else if ((af == AF_INET6) && (r->answer[i]->dnstype == ns_t_aaaa)) + { + got_data++; + got_addr++; + dns_host_append_addr((const char *)&(r->answer[i]->data.AAAA->addr), 16, h); + if (h->ttl == 0) h->ttl = r->answer[i]->ttl; + else if (r->answer[i]->ttl < h->ttl) h->ttl = r->answer[i]->ttl; + } + + else if (r->answer[i]->dnstype == ns_t_cname) + { + got_data++; + if (cnamex == -1) cnamex = i; + if (h->ttl == 0) h->ttl = r->answer[i]->ttl; + else if (r->answer[i]->ttl < h->ttl) h->ttl = r->answer[i]->ttl; + } + + else if (r->answer[i]->dnstype == ns_t_ptr) + { + got_data++; + if (ptrx == -1) ptrx = i; + if (h->ttl == 0) h->ttl = r->answer[i]->ttl; + else if (r->answer[i]->ttl < h->ttl) h->ttl = r->answer[i]->ttl; + } + } + + if (addr != NULL) + { + if (af == AF_INET) + { + got_addr++; + dns_host_append_addr(addr, 4, h); + } + else if (af == AF_INET6) + { + got_addr++; + dns_host_append_addr(addr, 16, h); + } + } + + if (got_data == 0) return -1; + if (got_addr == 0) return -1; + + h->host.h_addrtype = af; + if (af == AF_INET) h->host.h_length = 4; + else h->host.h_length = 16; + + if (ptrx != -1) + { + /* use name from PTR record */ + h->host.h_name = dns_lower_case(r->answer[ptrx]->data.PTR->name); + } + else if (cnamex != -1) + { + /* use name from CNAME record */ + h->host.h_name = dns_lower_case(r->answer[cnamex]->data.CNAME->name); + } + else + { + /* use name in first answer */ + h->host.h_name = dns_lower_case(r->answer[0]->name); + } + + for (i = 0; i < r->header->ancount; i++) + { + if (r->answer[i]->dnstype == ns_t_cname) + { + dns_host_merge_alias(r->answer[cnamex]->data.CNAME->name, h); + dns_host_merge_alias(r->answer[cnamex]->name, h); + } + } + + if (h->alias_count == 0) h->host.h_aliases = (char **)calloc(1, sizeof(char *)); + + return 0; +} + +static si_item_t * +_internal_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err, int which) +{ + uint32_t type; + dns_reply_t *r; + dns_build_hostent_t h; + si_item_t *out; + dns_handle_t dns; + uint64_t bb; + int status; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (name == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + if (af == AF_INET) type = ns_t_a; + else if (af == AF_INET6) type = ns_t_aaaa; + else + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + r = NULL; + dns = NULL; + + if (which == MODULE_DNS) dns = dns_checkout_handle(si); + else if (which == MODULE_MDNS) dns = mdns_checkout_handle(si); + + if (dns == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + r = dns_lookup(dns, name, ns_c_in, type); + dns_checkin_handle(si, dns); + + if (r == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + memset(&h, 0, sizeof(dns_build_hostent_t)); + + status = dns_reply_to_hostent(r, af, NULL, &h); + dns_free_reply(r); + + if (status < 0) + { + dns_plugin_clear_host(&h); + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + bb = h.ttl + time(NULL); + + if (af == AF_INET) + { + out = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, af, h.host.h_length, h.host.h_addr_list); + } + else + { + out = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, af, h.host.h_length, h.host.h_addr_list); + } + + dns_plugin_clear_host(&h); + + if ((out == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + + return out; +} + +si_item_t * +dns_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + return _internal_host_byname(si, name, af, err, MODULE_DNS); +} + +si_item_t * +mdns_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + return _internal_host_byname(si, name, af, err, MODULE_MDNS); +} + +static si_item_t * +_internal_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err, int which) +{ + uint32_t type; + dns_reply_t *r; + dns_build_hostent_t h; + char *name; + si_item_t *out; + dns_handle_t dns; + socklen_t len; + uint64_t bb; + int cat; + struct sockaddr_storage from; + uint32_t fromlen; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (addr == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + if (si == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + fromlen = sizeof(struct sockaddr_storage); + memset(&from, 0, fromlen); + + name = NULL; + type = ns_t_ptr; + + len = 0; + cat = -1; + + if (af == AF_INET) + { + len = 4; + name = dns_reverse_ipv4(addr); + cat = CATEGORY_HOST_IPV4; + } + else if (af == AF_INET6) + { + len = 16; + name = dns_reverse_ipv6(addr); + cat = CATEGORY_HOST_IPV6; + } + else + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + r = NULL; + dns = NULL; + + if (which == MODULE_DNS) dns = dns_checkout_handle(si); + else if (which == MODULE_MDNS) dns = mdns_checkout_handle(si); + + if (dns == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + r = dns_lookup(dns, name, ns_c_in, type); + dns_checkin_handle(si, dns); + + free(name); + if (r == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + memset(&h, 0, sizeof(dns_build_hostent_t)); + + if (dns_reply_to_hostent(r, af, addr, &h) < 0) + { + dns_plugin_clear_host(&h); + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + bb = h.ttl + time(NULL); + out = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, cat, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, af, h.host.h_length, h.host.h_addr_list); + + dns_plugin_clear_host(&h); + + if ((out == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + + return out; +} + +si_item_t * +dns_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + return _internal_host_byaddr(si, addr, af, err, MODULE_DNS); +} + +si_item_t * +mdns_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + return _internal_host_byaddr(si, addr, af, err, MODULE_MDNS); +} + +/* + * We support dns_async_start / cancel / handle_reply using dns_item_call + */ +static si_item_t * +_internal_item_call(si_mod_t *si, int call, const char *name, const char *ignored, uint32_t class, uint32_t type, uint32_t *err, int which) +{ + dns_handle_t dns; + char buf[DNS_MAX_RECEIVE_SIZE]; + int len; + struct sockaddr_storage from; + uint32_t fromlen; + si_item_t *out; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + if ((call != SI_CALL_DNS_QUERY) && (call != SI_CALL_DNS_SEARCH)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + if (name == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + dns = NULL; + + if (which == MODULE_DNS) dns = dns_checkout_handle(si); + else if (which == MODULE_MDNS) dns = mdns_checkout_handle(si); + + if (dns == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + fromlen = sizeof(struct sockaddr_storage); + memset(&from, 0, fromlen); + + len = 0; + if (call == SI_CALL_DNS_QUERY) len = dns_query(dns, name, class, type, buf, sizeof(buf), (struct sockaddr *)&from, &fromlen); + else if (call == SI_CALL_DNS_SEARCH) len = dns_search(dns, name, class, type, buf, sizeof(buf), (struct sockaddr *)&from, &fromlen); + + dns_checkin_handle(si, dns); + + if ((len <= 0) || (len > DNS_MAX_RECEIVE_SIZE)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + out = (si_item_t *)LI_ils_create("L4488@@", (unsigned long)si, CATEGORY_DNSPACKET, 1, 0LL, 0LL, len, buf, fromlen, &from); + if ((out == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + + return out; +} + +si_item_t * +dns_item_call(si_mod_t *si, int call, const char *name, const char *ignored, uint32_t class, uint32_t type, uint32_t *err) +{ + return _internal_item_call(si, call, name, ignored, class, type, err, MODULE_DNS); +} + +si_item_t * +mdns_item_call(si_mod_t *si, int call, const char *name, const char *ignored, uint32_t class, uint32_t type, uint32_t *err) +{ + return _internal_item_call(si, call, name, ignored, class, type, err, MODULE_MDNS); +} + +int +dns_is_valid(si_mod_t *si, si_item_t *item) +{ + uint64_t now; + si_mod_t *src; + + if (si == NULL) return 0; + if (item == NULL) return 0; + if (si->name == NULL) return 0; + if (item->src == NULL) return 0; + + src = (si_mod_t *)item->src; + + if (src->name == NULL) return 0; + if (string_not_equal(si->name, src->name)) return 0; + + now = time(NULL); + if (item->validation_a < now) return 0; + return 1; +} + +int +mdns_is_valid(si_mod_t *si, si_item_t *item) +{ + return 0; +} + +void +dns_close(si_mod_t *si) +{ + dns_plugin_private_t *pp; + + if (si == NULL) return; + + pp = (dns_plugin_private_t *)si->private; + if (pp == NULL) return; + + if (pp->dns != NULL) dns_free(pp->dns); + free(si->private); +} + +int +dns_init(si_mod_t *si) +{ + if (si == NULL) return 1; + + si->vers = 1; + + si->sim_close = dns_close; + si->sim_is_valid = dns_is_valid; + si->sim_host_byname = dns_host_byname; + si->sim_host_byaddr = dns_host_byaddr; + si->sim_item_call = dns_item_call; + + return 0; +} + +void +mdns_close(si_mod_t *si) +{ + dns_close(si); +} + +int +mdns_init(si_mod_t *si) +{ + if (si == NULL) return 1; + + si->vers = 1; + + si->sim_close = dns_close; + si->sim_is_valid = mdns_is_valid; + si->sim_host_byname = mdns_host_byname; + si->sim_host_byaddr = mdns_host_byaddr; + si->sim_item_call = mdns_item_call; + + return 0; +} + diff --git a/dns_private.h b/dns_private.h index 1ca315d..8320ab7 100644 --- a/dns_private.h +++ b/dns_private.h @@ -3,6 +3,8 @@ #include +#define MDNS_HANDLE_NAME "*MDNS*" + #define DNS_FLAG_DEBUG 0x00000001 #define DNS_FLAG_CHECK_RESOLVER_DIR 0x00000002 #define DNS_FLAG_HAVE_IPV6_SERVER 0x00000004 diff --git a/dns_util.c b/dns_util.c index adb1324..b09c817 100644 --- a/dns_util.c +++ b/dns_util.c @@ -332,13 +332,13 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->name = _dns_parse_domain_name(p, x, remaining); if (r->name == NULL) { - free(r); + dns_free_resource_record(r); return NULL; } if (*remaining < 10) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -357,7 +357,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_a: if (*remaining < 4) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -371,7 +371,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_aaaa: if (*remaining < 16) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -398,8 +398,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.CNAME->name = _dns_parse_domain_name(p, x, remaining); if (r->data.CNAME->name == NULL) { - free(r->data.CNAME); - free(r); + dns_free_resource_record(r); return NULL; } break; @@ -411,26 +410,20 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.SOA->mname = _dns_parse_domain_name(p, x, remaining); if (r->data.SOA->mname == NULL) { - free(r->data.SOA); - free(r); + dns_free_resource_record(r); return NULL; } r->data.SOA->rname = _dns_parse_domain_name(p, x, remaining); if (r->data.SOA->rname == NULL) { - free(r->data.SOA->mname); - free(r->data.SOA); - free(r); + dns_free_resource_record(r); return NULL; } if (*remaining < 20) { - free(r->data.SOA->mname); - free(r->data.SOA->rname); - free(r->data.SOA); - free(r); + dns_free_resource_record(r); return NULL; } @@ -446,7 +439,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_wks: if (*remaining < 5) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -483,17 +476,14 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.HINFO->cpu = _dns_parse_string(p, x, remaining); if (r->data.HINFO->cpu == NULL) { - free(r->data.HINFO); - free(r); + dns_free_resource_record(r); return NULL; } r->data.HINFO->os = _dns_parse_string(p, x, remaining); if (r->data.HINFO->os == NULL) { - free(r->data.HINFO->cpu); - free(r->data.HINFO); - free(r); + dns_free_resource_record(r); return NULL; } @@ -506,17 +496,14 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.MINFO->rmailbx = _dns_parse_domain_name(p, x, remaining); if (r->data.MINFO->rmailbx == NULL) { - free(r->data.MINFO); - free(r); + dns_free_resource_record(r); return NULL; } r->data.MINFO->emailbx = _dns_parse_domain_name(p, x, remaining); if (r->data.MINFO->emailbx == NULL) { - free(r->data.MINFO->rmailbx); - free(r->data.MINFO); - free(r); + dns_free_resource_record(r); return NULL; } @@ -525,7 +512,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_mx: if (*remaining < 2) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -538,8 +525,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.MX->name = _dns_parse_domain_name(p, x, remaining); if (r->data.MX->name == NULL) { - free(r->data.MX); - free(r); + dns_free_resource_record(r); return NULL; } @@ -565,9 +551,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.TXT->strings[r->data.TXT->string_count] = _dns_parse_string(p, x, remaining); if (r->data.TXT->strings[r->data.TXT->string_count] == NULL) { - free(r->data.TXT->strings); - free(r->data.TXT); - free(r); + dns_free_resource_record(r); return NULL; } r->data.TXT->string_count++; @@ -582,17 +566,14 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.RP->mailbox = _dns_parse_domain_name(p, x, remaining); if (r->data.RP->mailbox == NULL) { - free(r->data.RP); - free(r); + dns_free_resource_record(r); return NULL; } r->data.RP->txtdname = _dns_parse_domain_name(p, x, remaining); if (r->data.RP->txtdname == NULL) { - free(r->data.RP->mailbox); - free(r->data.RP); - free(r); + dns_free_resource_record(r); return NULL; } @@ -601,7 +582,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_afsdb: if (*remaining < 4) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -613,8 +594,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.AFSDB->hostname = _dns_parse_domain_name(p, x, remaining); if (r->data.AFSDB->hostname == NULL) { - free(r->data.AFSDB); - free(r); + dns_free_resource_record(r); return NULL; } @@ -627,8 +607,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.X25->psdn_address = _dns_parse_string(p, x, remaining); if (r->data.X25->psdn_address == NULL) { - free(r->data.X25); - free(r); + dns_free_resource_record(r); return NULL; } @@ -641,8 +620,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.ISDN->isdn_address = _dns_parse_string(p, x, remaining); if (r->data.ISDN->isdn_address == NULL) { - free(r->data.ISDN); - free(r); + dns_free_resource_record(r); return NULL; } @@ -651,9 +629,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.ISDN->subaddress = _dns_parse_string(p, x, remaining); if (r->data.ISDN->subaddress == NULL) { - free(r->data.ISDN->isdn_address); - free(r->data.ISDN); - free(r); + dns_free_resource_record(r); return NULL; } } @@ -667,7 +643,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_rt: if (*remaining < 2) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -680,8 +656,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.RT->intermediate = _dns_parse_domain_name(p, x, remaining); if (r->data.RT->intermediate == NULL) { - free(r->data.RT); - free(r); + dns_free_resource_record(r); return NULL; } @@ -690,7 +665,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_loc: if (*remaining < 16) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -711,7 +686,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) case ns_t_srv: if (*remaining < 6) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -726,8 +701,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) r->data.SRV->target = _dns_parse_domain_name(p, x, remaining); if (r->data.SRV->target == NULL) { - free(r->data.SRV); - free(r); + dns_free_resource_record(r); return NULL; } @@ -737,7 +711,7 @@ _dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) default: if (*remaining < rdlen) { - free(r); + dns_free_resource_record(r); return NULL; } @@ -915,11 +889,11 @@ dns_free_resource_record(dns_resource_record_t *r) switch (r->dnstype) { case ns_t_a: - free(r->data.A); + if (r->data.A != NULL) free(r->data.A); break; case ns_t_aaaa: - free(r->data.AAAA); + if (r->data.AAAA != NULL) free(r->data.AAAA); break; case ns_t_ns: @@ -930,90 +904,130 @@ dns_free_resource_record(dns_resource_record_t *r) case ns_t_mg: case ns_t_mr: case ns_t_ptr: - free(r->data.CNAME->name); - free(r->data.CNAME); + if (r->data.CNAME != NULL) + { + if (r->data.CNAME->name != NULL) free(r->data.CNAME->name); + free(r->data.CNAME); + } break; case ns_t_soa: - free(r->data.SOA->mname); - free(r->data.SOA->rname); - free(r->data.SOA); + if (r->data.SOA != NULL) + { + if (r->data.SOA->mname != NULL) free(r->data.SOA->mname); + if (r->data.SOA->rname != NULL) free(r->data.SOA->rname); + free(r->data.SOA); + } break; case ns_t_wks: - free(r->data.WKS->map); - free(r->data.WKS); + if (r->data.WKS != NULL) + { + if (r->data.WKS->map != NULL) free(r->data.WKS->map); + free(r->data.WKS); + } break; case ns_t_hinfo: - free(r->data.HINFO->cpu); - free(r->data.HINFO->os); - free(r->data.HINFO); + if (r->data.HINFO != NULL) + { + if (r->data.HINFO->cpu != NULL) free(r->data.HINFO->cpu); + if (r->data.HINFO->os != NULL) free(r->data.HINFO->os); + free(r->data.HINFO); + } break; case ns_t_minfo: - free(r->data.MINFO->rmailbx); - free(r->data.MINFO->emailbx); - free(r->data.MINFO); + if (r->data.MINFO != NULL) + { + if (r->data.MINFO->rmailbx != NULL) free(r->data.MINFO->rmailbx); + if (r->data.MINFO->emailbx != NULL) free(r->data.MINFO->emailbx); + free(r->data.MINFO); + } break; case ns_t_mx: - free(r->data.MX->name); - free(r->data.MX); + if (r->data.MX != NULL) + { + if (r->data.MX->name != NULL) free(r->data.MX->name); + free(r->data.MX); + } break; case ns_t_txt: - for (i=0; idata.TXT->string_count; i++) + if (r->data.TXT != NULL) { - free(r->data.TXT->strings[i]); + for (i = 0; i < r->data.TXT->string_count; i++) free(r->data.TXT->strings[i]); + if (r->data.TXT->strings != NULL) free(r->data.TXT->strings); + free(r->data.TXT); } - if (r->data.TXT->strings != NULL) - free(r->data.TXT->strings); - free(r->data.TXT); break; case ns_t_rp: - free(r->data.RP->mailbox); - free(r->data.RP->txtdname); - free(r->data.RP); + if (r->data.RP != NULL) + { + if (r->data.RP->mailbox != NULL) free(r->data.RP->mailbox); + if (r->data.RP->txtdname != NULL) free(r->data.RP->txtdname); + free(r->data.RP); + } break; case ns_t_afsdb: - free(r->data.AFSDB->hostname); - free(r->data.AFSDB); + if (r->data.AFSDB != NULL) + { + if (r->data.AFSDB->hostname != NULL) free(r->data.AFSDB->hostname); + free(r->data.AFSDB); + } break; case ns_t_x25: - free(r->data.X25->psdn_address); - free(r->data.X25); + if (r->data.X25 != NULL) + { + if (r->data.X25->psdn_address != NULL) free(r->data.X25->psdn_address); + free(r->data.X25); + } break; case ns_t_isdn: - free(r->data.ISDN->isdn_address); - if (r->data.ISDN->subaddress != NULL) - free(r->data.ISDN->subaddress); - free(r->data.ISDN); + if (r->data.ISDN != NULL) + { + if (r->data.ISDN->isdn_address != NULL) free(r->data.ISDN->isdn_address); + if (r->data.ISDN->subaddress != NULL) free(r->data.ISDN->subaddress); + free(r->data.ISDN); + } break; case ns_t_rt: - free(r->data.RT->intermediate); - free(r->data.RT); + if (r->data.RT != NULL) + { + if (r->data.RT->intermediate != NULL) free(r->data.RT->intermediate); + free(r->data.RT); + } break; case ns_t_loc: - free(r->data.LOC); + if (r->data.LOC != NULL) free(r->data.LOC); break; case ns_t_srv: - free(r->data.SRV->target); - free(r->data.SRV); + if (r->data.SRV != NULL) + { + if (r->data.SRV->target != NULL) free(r->data.SRV->target); + free(r->data.SRV); + } + break; + + case ns_t_invalid: break; case ns_t_null: default: - free(r->data.DNSNULL->data); - free(r->data.DNSNULL); + if (r->data.DNSNULL != NULL) + { + if (r->data.DNSNULL->data != NULL) free(r->data.DNSNULL->data); + free(r->data.DNSNULL); + } break; } diff --git a/nameser.h b/nameser.h index 8f40203..978ba5c 100644 --- a/nameser.h +++ b/nameser.h @@ -56,8 +56,8 @@ #define _NAMESER_9_H_ #ifdef BIND_8_COMPAT -#include -#else +#include +#endif #include #if (!defined(BSD)) || (BSD < 199306) @@ -584,5 +584,4 @@ int ns_makecanon __P((const char *, char *, size_t)); int ns_samename __P((const char *, const char *)); __END_DECLS -#endif /* !BIND_8_COMPAT */ #endif /* !_NAMESER_9_H_ */ diff --git a/ns_print.c b/ns_print.c index fd9c71f..1029839 100644 --- a/ns_print.c +++ b/ns_print.c @@ -718,7 +718,7 @@ ns_sprintrrf(const u_char *msg, size_t msglen, int n, m; char *p; - len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment)); + len = SPRINTF((tmp, "\\# %u (\t; %s", (unsigned int)(edata - rdata), comment)); T(addstr(tmp, len, &buf, &buflen)); while (rdata < edata) { p = tmp; diff --git a/res_mkquery.c b/res_mkquery.c index 09e1cf3..7dcf45b 100644 --- a/res_mkquery.c +++ b/res_mkquery.c @@ -115,7 +115,7 @@ res_nmkquery(res_state statp, u_char *dnptrs[20], **dpp, **lastdnptr; #ifdef __APPLE__ - n = (int)newrr_in; n = 0; + n = 0; #else UNUSED(newrr_in); #endif diff --git a/res_private.h b/res_private.h index b9e076d..34bf952 100644 --- a/res_private.h +++ b/res_private.h @@ -94,7 +94,7 @@ void res_client_close(res_state res); */ extern uint32_t notify_register_plain(const char *name, int *out_token); -__private_extern__ int res_query_mDNSResponder(res_state statp, const char *name, int class, int type, u_char *answer, int anslen, struct sockaddr *from, uint32_t *fromlen); +extern int res_query_mDNSResponder(res_state statp, const char *name, int class, int type, u_char *answer, int anslen, struct sockaddr *from, uint32_t *fromlen); int dns_res_once(struct sockaddr *server, struct timeval *timeout, int options, const char *name, int class, int type, u_char *res, int *reslen); @@ -103,8 +103,8 @@ int dns_res_once(struct sockaddr *server, struct timeval *timeout, int options, */ void res_interrupt_requests_enable(void); void res_interrupt_requests_disable(void); -void res_interrupt_requests(void* token); -void* res_init_interrupt_token(void); -void res_delete_interrupt_token(void* token); +void res_interrupt_request(void *token); +void *res_init_interrupt_token(void); +void res_delete_interrupt_token(void *token); #endif diff --git a/res_query.c b/res_query.c index 7df8c6c..d2e3760 100644 --- a/res_query.c +++ b/res_query.c @@ -94,10 +94,16 @@ static const char rcsid[] = "$Id: res_query.c,v 1.1 2006/03/01 19:01:38 majka Ex #include #include #include +#include +#include #ifndef __APPLE__ #include "port_after.h" #endif +/* interrupt mechanism is implemented in res_send.c */ +__private_extern__ int interrupt_pipe_enabled; +__private_extern__ pthread_key_t interrupt_pipe_key; + /* Options. Leave them on. */ #define DEBUG @@ -135,7 +141,9 @@ struct res_query_context u_char *answer; size_t anslen; size_t ansmaxlen; + uint16_t lastanstype; uint32_t ifnum; + uint32_t res_flags; DNSServiceFlags flags; DNSServiceErrorType error; }; @@ -155,10 +163,18 @@ res_query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, context->flags = flags; context->error = errorCode; - if (errorCode != kDNSServiceErr_NoError) return; + if (errorCode != kDNSServiceErr_NoError) + { + if (context->res_flags & RES_DEBUG) printf(";; res_query_mDNSResponder callback [%s %hu %hu]: error %u\n", fullname, rrtype, rrclass, errorCode); + return; + } buflen = context->ansmaxlen - context->anslen; - if (buflen < NS_HFIXEDSZ) return; + if (buflen < NS_HFIXEDSZ) + { + if (context->res_flags & RES_DEBUG) printf(";; res_query_mDNSResponder callback [%s %hu %hu]: malformed reply\n", fullname, rrtype, rrclass); + return; + } dnlist[0] = context->answer + NS_HFIXEDSZ; dnlist[1] = NULL; @@ -166,13 +182,23 @@ res_query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, cp = context->answer + context->anslen; n = dn_comp((char *)fullname, cp, buflen, dnlist, &dnlist[1]); - if (n < 0) return; + if (n < 0) + { + if (context->res_flags & RES_DEBUG) printf(";; res_query_mDNSResponder callback [%s %hu %hu]: name mismatch\n", fullname, rrtype, rrclass); + return; + } /* * Check that there is enough space in the buffer for the resource name (n), * the resource record data (rdlen) and the resource record header (10). */ - if (buflen < n + rdlen + 10) return; + if (buflen < n + rdlen + 10) + { + if (context->res_flags & RES_DEBUG) printf(";; res_query_mDNSResponder callback [%s %hu %hu]: insufficient buffer space for reply\n", fullname, rrtype, rrclass); + return; + } + + if (context->res_flags & RES_DEBUG) printf(";; res_query_mDNSResponder callback for %s %hu %hu\n", fullname, rrtype, rrclass); cp += n; buflen -= n; @@ -197,6 +223,8 @@ res_query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, context->anslen = (size_t)(cp - context->answer); + context->lastanstype = rrtype; + /* * Save the interface number for the first AAAA record for link-local addresses. * It's used by getaddrinfo to set the scope id. @@ -266,29 +294,34 @@ _is_rev_link_local(const char *name) return 1; } -__private_extern__ int +int res_query_mDNSResponder(res_state statp, const char *name, int class, int type, u_char *answer, int anslen, struct sockaddr *from, uint32_t *fromlen) { DNSServiceRef sdRef; DNSServiceErrorType result; struct res_query_context context; - int i, kq, n, wait; - struct kevent kv; + int i, kq, n, wait, cancelled, notify_token, status; + struct kevent mevent, ievent, event; struct timeval ctv; struct timespec now, finish, timeout; HEADER *ans; uint32_t iface; uint16_t nibble; - char *qname; + char *qname, *notify_name; + int *interrupt_pipe; + uint64_t exit_requested; + + interrupt_pipe = NULL; result = 0; kq = -1; ans = (HEADER *)answer; - + cancelled = 0; ans->rcode = 0; memset(&context, 0, sizeof(struct res_query_context)); /* Build a dummy DNS header with question for the answer */ + context.res_flags = statp->options; context.answer = answer; context.ansmaxlen = anslen; context.anslen = res_nmkquery(statp, ns_o_query, name, class, type, NULL, 0, NULL, answer, anslen); @@ -338,6 +371,8 @@ res_query_mDNSResponder(res_state statp, const char *name, int class, int type, } } + if (statp->options & RES_DEBUG) printf(";; res_query_mDNSResponder\n"); + result = DNSServiceQueryRecord(&sdRef, kDNSServiceFlagsReturnIntermediates, iface, qname, type, class, res_query_callback, &context); if (iface != 0) free(qname); @@ -356,12 +391,59 @@ res_query_mDNSResponder(res_state statp, const char *name, int class, int type, finish.tv_sec = ctv.tv_sec + statp->retrans; finish.tv_nsec = ctv.tv_usec * 1000; - EV_SET(&kv, DNSServiceRefSockFD(sdRef), EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); + /* add mdns reply FD to kqueue */ + EV_SET(&mevent, DNSServiceRefSockFD(sdRef), EVFILT_READ, EV_ADD, 0, 0, 0); + n = kevent(kq, &mevent, 1, NULL, 0, NULL); + if (n != 0) return 0; + + /* add interrupt pipe to kqueue if interrupt is enabled */ + if (interrupt_pipe_enabled != 0) + { + interrupt_pipe = pthread_getspecific(interrupt_pipe_key); + if (interrupt_pipe != NULL) + { + if (interrupt_pipe[0] >= 0) + { + EV_SET(&ievent, interrupt_pipe[0], EVFILT_READ, EV_ADD, 0, 0, (void *)name); + /* allow this to fail silently (should never happen, but it would only break interrupts */ + n = kevent(kq, &ievent, 1, NULL, 0, NULL); + } + } + } + + /* + * Get notification token + * we use a self-notification token to allow a caller + * to signal the thread doing this DNS query to quit. + */ + notify_name = NULL; + notify_token = -1; + + asprintf(¬ify_name, "self.thread.%lu", (unsigned long)pthread_self()); + if (notify_name != NULL) + { + status = notify_register_plain(notify_name, ¬ify_token); + free(notify_name); + } wait = 1; while (wait == 1) { - n = kevent(kq, &kv, 1, &kv, 1, &timeout); + memset(&event, 0, sizeof(struct kevent)); + n = kevent(kq, NULL, 0, &event, 1, &timeout); + + if (notify_token != -1) + { + exit_requested = 0; + status = notify_get_state(notify_token, &exit_requested); + if (exit_requested == ThreadStateExitRequested) + { + /* interrupted */ + if (statp->options & RES_DEBUG) printf(";; cancelled\n"); + cancelled = 1; + break; + } + } if (n < 0) { @@ -374,6 +456,13 @@ res_query_mDNSResponder(res_state statp, const char *name, int class, int type, h_errno = TRY_AGAIN; wait = 0; } + else if (event.udata == (void *)name) + { + /* interrupted */ + if (statp->options & RES_DEBUG) printf(";; cancelled\n"); + cancelled = 1; + break; + } else { result = DNSServiceProcessResult(sdRef); @@ -384,7 +473,7 @@ res_query_mDNSResponder(res_state statp, const char *name, int class, int type, wait = 0; } - if ((ans->ancount > 0) && ((context.flags & kDNSServiceFlagsMoreComing) == 0)) wait = 0; + if ((ans->ancount > 0) && ((context.flags & kDNSServiceFlagsMoreComing) == 0) && ((context.lastanstype != ns_t_cname) || (type == ns_t_cname))) wait = 0; } keep_waiting: @@ -410,10 +499,11 @@ res_query_mDNSResponder(res_state statp, const char *name, int class, int type, } } + if (notify_token != -1) notify_cancel(notify_token); DNSServiceRefDeallocate(sdRef); close(kq); - if (ans->ancount == 0) context.anslen = -1; + if ((ans->ancount == 0) || (cancelled == 1)) context.anslen = -1; if ((from != NULL) && (fromlen != NULL) && (context.ifnum != 0)) { diff --git a/res_send.c b/res_send.c index 1018e6c..d731ca2 100644 --- a/res_send.c +++ b/res_send.c @@ -146,13 +146,15 @@ static int send_dg(res_state, const u_char *, int, u_char *, int *, int *, int, static void Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *, int); static void Perror(const res_state, FILE *, const char *, int); static int sock_eq(struct sockaddr *, struct sockaddr *); -#ifdef NEED_PSELECT -static int pselect(int, void *, void *, void *, struct timespec *, const sigset_t *); +#ifdef USE_DNS_PSELECT +static int dns_pselect(int, void *, void *, void *, struct timespec *, const sigset_t *); #endif static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; -static int interrupt_pipe_enabled = 0; -static pthread_key_t interrupt_pipe_key; + +/* interrupt mechanism is shared with res_query.c */ +int interrupt_pipe_enabled = 0; +pthread_key_t interrupt_pipe_key; static int bind_random(int sock) @@ -297,7 +299,7 @@ evNowTime() return (evTimeSpec(now)); } -#ifdef NEED_PSELECT +#ifdef USE_DNS_PSELECT static struct timeval evTimeVal(struct timespec ts) { @@ -1324,11 +1326,11 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz finish = evAddTime(now, timeout); #endif /* __APPLE__ */ goto nonow; - wait: +wait: now = evNowTime(); - nonow: +nonow: if (notify_token != -1) { @@ -1357,7 +1359,11 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz if (evCmpTime(finish, now) > 0) timeout = evSubTime(finish, now); else timeout = evConsTime(0, 0); +#ifdef USE_DNS_PSELECT + n = dns_pselect(nfds, &dsmask, NULL, NULL, &timeout, NULL); +#else n = pselect(nfds, &dsmask, NULL, NULL, &timeout, NULL); +#endif if (n == 0) { Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); @@ -1553,10 +1559,9 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) } } -#ifdef NEED_PSELECT -/* XXX needs to move to the porting library. */ +#ifdef USE_DNS_PSELECT static int -pselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp, const sigset_t *sigmask) +dns_pselect(int nfds, void *rfds, void *wfds, void *efds, struct timespec *tsp, const sigset_t *sigmask) { struct timeval tv, *tvp = NULL; sigset_t sigs; diff --git a/resolv.h b/resolv.h index 2a36c22..d2dbd43 100644 --- a/resolv.h +++ b/resolv.h @@ -68,10 +68,6 @@ #ifndef _RESOLV_9_H_ #define _RESOLV_9_H_ -#ifdef BIND_8_COMPAT -#include -#else - #include #if (!defined(BSD)) || (BSD < 199306) # include @@ -82,8 +78,7 @@ #include #include #include -#include - +#include /* * Revision information. This is the release date in YYYYMMDD format. @@ -495,5 +490,4 @@ void res_setservers __P((res_state, const union res_sockaddr_union *, int)); int res_getservers __P((res_state, union res_sockaddr_union *, int)); __END_DECLS -#endif /* !BIND_8_COMPAT */ #endif /* !_RESOLV_9_H_ */ diff --git a/resolver.3 b/resolver.3 index cd03597..9f89141 100644 --- a/resolver.3 +++ b/resolver.3 @@ -260,7 +260,12 @@ The reply message is left in the .Fa answer buffer with length .Fa anslen -supplied by the caller. +supplied by the caller. Constants for +.Fa type +and +.Fa class +are defined in +.Aq Pa arpa/nameser.h . .Pp The .Fn res_search @@ -350,7 +355,7 @@ The entry expands the compressed domain name .Fa comp_dn -to a full domain name +to a full domain name. The compressed name is contained in a query or reply message; .Fa msg is a pointer to the beginning of the message. diff --git a/resolver.5 b/resolver.5 index 8161807..27b5444 100644 --- a/resolver.5 +++ b/resolver.5 @@ -86,7 +86,7 @@ Domain name associated with this resolver configuration. This option is normally not required by the Mac OS X DNS search system when the resolver configuration is read from a file in the .Pa /etc/resolver -directroy. +directory. In that case the file name is used as the domain name. However, .Sx domain @@ -212,7 +212,7 @@ These are at present located by the system in the file and in the files found in the .Pa /etc/resolver -directroy. +directory. However, client configurations are not limited to file storage. The implementation of the DNS multi-client search strategy may also locate client configuratins in other data sources, such as the System Configuration -- 2.47.2