]> git.saurik.com Git - apple/libresolv.git/commitdiff
libresolv-38.tar.gz mac-os-x-106 mac-os-x-1061 mac-os-x-1062 v38
authorApple <opensource@apple.com>
Mon, 20 Apr 2009 21:27:09 +0000 (21:27 +0000)
committerApple <opensource@apple.com>
Mon, 20 Apr 2009 21:27:09 +0000 (21:27 +0000)
18 files changed:
APPLE_LICENSE [new file with mode: 0644]
BUILD [new file with mode: 0644]
Makefile
Makefile.preamble
dns.c
dns_async.c
dns_plugin.c [new file with mode: 0644]
dns_private.h
dns_util.c
nameser.h
ns_print.c
res_mkquery.c
res_private.h
res_query.c
res_send.c
resolv.h
resolver.3
resolver.5

diff --git a/APPLE_LICENSE b/APPLE_LICENSE
new file mode 100644 (file)
index 0000000..fe81a60
--- /dev/null
@@ -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 (file)
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
index 9f285732316f16916f12bb934e735cfd7c73c4c3..1f10d4f8fa45ef50ebeec32962505cfc3abf8202 100644 (file)
--- 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
index e50fc53f62e68012064e33bfdb30ddb286b44082..046bb8dc29eb66ba3f9f9694791311c7c4238e0f 100644 (file)
@@ -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 7c5ceb425029576166436d3ea44db690f275d0bc..fa2e658a7733e99fa9505f7de847331b9b01230e 100644 (file)
--- a/dns.c
+++ b/dns.c
 
 #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"
 
 
 #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;
index 9aa367ac807b32abc0023bab5795e95f12b9f4fd..66bff8bf97f850935c81212560905a85acccebfa 100644 (file)
@@ -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 <stdlib.h>
 #include <arpa/inet.h>
 #include <dns.h>
 #include <dns_util.h>
+#include <stdarg.h>
+#include <si_module.h>
 
-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 (file)
index 0000000..58d8de6
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <dns.h>
+#include <dns_util.h>
+#include <resolv.h>
+#include <nameser.h>
+#include <pthread.h>
+#include <si_module.h>
+#include <ils.h>
+#include <dns_private.h>
+
+/* 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;
+}
+
index 1ca315d095e5eb5ce19b23c07a1d6986faa1807e..8320ab73c0629881588492ca4f8b5a73da448239 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <sys/cdefs.h>
 
+#define MDNS_HANDLE_NAME "*MDNS*"
+
 #define DNS_FLAG_DEBUG                    0x00000001
 #define DNS_FLAG_CHECK_RESOLVER_DIR       0x00000002
 #define DNS_FLAG_HAVE_IPV6_SERVER         0x00000004
index adb13249f617c7dcff6554980a2175ab2ade4c2d..b09c8170837a0370ae4a35c16d5da7584f51c905 100644 (file)
@@ -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; i<r->data.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;
        }
 
index 8f402034e2933604ab34d33ae62d3c85e6913741..978ba5c17a8b2176499baad6fc4388169b587fe5 100644 (file)
--- a/nameser.h
+++ b/nameser.h
@@ -56,8 +56,8 @@
 #define _NAMESER_9_H_
 
 #ifdef BIND_8_COMPAT
-#include <arpa/nameser8_compat.h>
-#else
+#include <arpa/nameser_compat.h>
+#endif
 
 #include <sys/param.h>
 #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_ */
index fd9c71f10ceadd7a7239ef949e6b1579fcc7e947..1029839ae8ed1e6363bd8f9d289c2995aa427e25 100644 (file)
@@ -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;
index 09e1cf30d5b9e4289f444eef519f011378e1be8d..7dcf45b7d567f38a799c0ca3f683351a875a1486 100644 (file)
@@ -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
index b9e076d3074acf8b259018f142f7518e10c6fcc5..34bf952fa22e1c39b97522a2aba733ac8afd12c5 100644 (file)
@@ -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);
-voidres_init_interrupt_token(void);
-void res_delete_interrupt_token(voidtoken);
+void res_interrupt_request(void *token);
+void *res_init_interrupt_token(void);
+void res_delete_interrupt_token(void *token);
 
 #endif
index 7df8c6c42a36230a12a9fe2992ca953aeb575616..d2e3760ac9958ff56e5c347ed2f6a5e765369bd8 100644 (file)
@@ -94,10 +94,16 @@ static const char rcsid[] = "$Id: res_query.c,v 1.1 2006/03/01 19:01:38 majka Ex
 #include <sys/time.h>
 #include <time.h>
 #include <unistd.h>
+#include <notify.h>
+#include <pthread.h>
 #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(&notify_name, "self.thread.%lu", (unsigned long)pthread_self());
+       if (notify_name != NULL) 
+       {
+               status = notify_register_plain(notify_name, &notify_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))
        {
index 1018e6c247e05f2e0c2e1316b1ecb42254ab9e2d..d731ca269bf1c4b88154f9907922c14225587210 100644 (file)
@@ -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;
index 2a36c2237a6e9d5c1dc6a9b0713efbd3ad925fc3..d2dbd439c3b181e6018e4f25c8d8796ecbc783c2 100644 (file)
--- a/resolv.h
+++ b/resolv.h
 #ifndef _RESOLV_9_H_
 #define        _RESOLV_9_H_
 
-#ifdef BIND_8_COMPAT
-#include <resolv8_compat.h>
-#else
-
 #include <sys/param.h>
 #if (!defined(BSD)) || (BSD < 199306)
 # include <sys/bitypes.h>
@@ -82,8 +78,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <stdio.h>
-#include <arpa/nameser.h>
-
+#include <nameser.h>
 
 /*
  * 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_ */
index cd03597a21fc2efe8e573d95a68d06ed2070cd87..9f891417ff7d093cb083e0ab3a4f178610a93cdd 100644 (file)
@@ -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.
index 81618077cdf3cfe08c98518e5edb1fcd73818ae2..27b5444e51f747e7d02cb4233e3110d161c84c0e 100644 (file)
@@ -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